From 524f693872cf453af2655ec47356d25d52394e3d Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sun, 11 Dec 2016 17:28:21 +0100 Subject: [PATCH] src: don't overwrite non-writable vm globals Check that the property doesn't have the read-only flag set before overwriting it. Fixes: https://github.com/nodejs/node/issues/10223 PR-URL: https://github.com/nodejs/node/pull/10227 Reviewed-By: Benjamin Gruenbaum Reviewed-By: Franziska Hinkelmann --- src/node_contextify.cc | 23 +++++++++++++---------- test/parallel/test-vm-context.js | 11 +++++++++++ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/node_contextify.cc b/src/node_contextify.cc index d74b01ea0d..fc8aa45134 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -383,19 +383,22 @@ class ContextifyContext { if (ctx->context_.IsEmpty()) return; + auto attributes = PropertyAttribute::None; bool is_declared = - ctx->global_proxy()->HasRealNamedProperty(ctx->context(), - property).FromJust(); - bool is_contextual_store = ctx->global_proxy() != args.This(); + ctx->global_proxy()->GetRealNamedPropertyAttributes(ctx->context(), + property) + .To(&attributes); + bool read_only = + static_cast(attributes) & + static_cast(PropertyAttribute::ReadOnly); + + if (is_declared && read_only) + return; - bool set_property_will_throw = - args.ShouldThrowOnError() && - !is_declared && - is_contextual_store; + if (!is_declared && args.ShouldThrowOnError()) + return; - if (!set_property_will_throw) { - ctx->sandbox()->Set(property, value); - } + ctx->sandbox()->Set(property, value); } diff --git a/test/parallel/test-vm-context.js b/test/parallel/test-vm-context.js index 659a092eb3..d3269d9035 100644 --- a/test/parallel/test-vm-context.js +++ b/test/parallel/test-vm-context.js @@ -75,3 +75,14 @@ assert.throws(function() { // https://github.com/nodejs/node/issues/6158 ctx = new Proxy({}, {}); assert.strictEqual(typeof vm.runInNewContext('String', ctx), 'function'); + +// https://github.com/nodejs/node/issues/10223 +ctx = vm.createContext(); +vm.runInContext('Object.defineProperty(this, "x", { value: 42 })', ctx); +assert.strictEqual(ctx.x, undefined); // Not copied out by cloneProperty(). +assert.strictEqual(vm.runInContext('x', ctx), 42); +vm.runInContext('x = 0', ctx); // Does not throw but x... +assert.strictEqual(vm.runInContext('x', ctx), 42); // ...should be unaltered. +assert.throws(() => vm.runInContext('"use strict"; x = 0', ctx), + /Cannot assign to read only property 'x'/); +assert.strictEqual(vm.runInContext('x', ctx), 42);