Skip to content

Commit 0a5a2c4

Browse files
fhinkelgibfahn
authored andcommitted
src: fix vm module for strict mode
This patch fixes the problem with variables that are declared only on the sandbox but not on the global proxy. PR-URL: #16487 Fixes: #12300 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
1 parent 4ba06d0 commit 0a5a2c4

File tree

3 files changed

+27
-41
lines changed

3 files changed

+27
-41
lines changed

src/node_contextify.cc

+20-4
Original file line numberDiff line numberDiff line change
@@ -414,15 +414,21 @@ class ContextifyContext {
414414
return;
415415

416416
auto attributes = PropertyAttribute::None;
417-
bool is_declared =
418-
ctx->global_proxy()->GetRealNamedPropertyAttributes(ctx->context(),
419-
property)
417+
bool is_declared_on_global_proxy = ctx->global_proxy()
418+
->GetRealNamedPropertyAttributes(ctx->context(), property)
420419
.To(&attributes);
421420
bool read_only =
422421
static_cast<int>(attributes) &
423422
static_cast<int>(PropertyAttribute::ReadOnly);
424423

425-
if (is_declared && read_only)
424+
bool is_declared_on_sandbox = ctx->sandbox()
425+
->GetRealNamedPropertyAttributes(ctx->context(), property)
426+
.To(&attributes);
427+
read_only = read_only ||
428+
(static_cast<int>(attributes) &
429+
static_cast<int>(PropertyAttribute::ReadOnly));
430+
431+
if (read_only)
426432
return;
427433

428434
// true for x = 5
@@ -440,10 +446,20 @@ class ContextifyContext {
440446
// this.f = function() {}, is_contextual_store = false.
441447
bool is_function = value->IsFunction();
442448

449+
bool is_declared = is_declared_on_global_proxy || is_declared_on_sandbox;
443450
if (!is_declared && args.ShouldThrowOnError() && is_contextual_store &&
444451
!is_function)
445452
return;
446453

454+
if (!is_declared_on_global_proxy && is_declared_on_sandbox &&
455+
args.ShouldThrowOnError() && is_contextual_store && !is_function) {
456+
// The property exists on the sandbox but not on the global
457+
// proxy. Setting it would throw because we are in strict mode.
458+
// Don't attempt to set it by signaling that the call was
459+
// intercepted. Only change the value on the sandbox.
460+
args.GetReturnValue().Set(false);
461+
}
462+
447463
ctx->sandbox()->Set(property, value);
448464
}
449465

test/known_issues/test-vm-strict-mode.js

-17
This file was deleted.

test/parallel/test-vm-strict-mode.js

+7-20
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,14 @@
11
'use strict';
2+
// https://github.com/nodejs/node/issues/12300
3+
24
require('../common');
35
const assert = require('assert');
46
const vm = require('vm');
5-
const ctx = vm.createContext();
6-
7-
// Test strict mode inside a vm script, i.e., using an undefined variable
8-
// throws a ReferenceError. Also check that variables
9-
// that are not successfully set in the vm, must not be set
10-
// on the sandboxed context.
11-
12-
vm.runInContext('w = 1;', ctx);
13-
assert.strictEqual(1, ctx.w);
14-
15-
assert.throws(function() { vm.runInContext('"use strict"; x = 1;', ctx); },
16-
/ReferenceError: x is not defined/);
17-
assert.strictEqual(undefined, ctx.x);
187

19-
vm.runInContext('"use strict"; var y = 1;', ctx);
20-
assert.strictEqual(1, ctx.y);
8+
const ctx = vm.createContext({ x: 42 });
219

22-
vm.runInContext('"use strict"; this.z = 1;', ctx);
23-
assert.strictEqual(1, ctx.z);
10+
// This might look as if x has not been declared, but x is defined on the
11+
// sandbox and the assignment should not throw.
12+
vm.runInContext('"use strict"; x = 1', ctx);
2413

25-
// w has been defined
26-
vm.runInContext('"use strict"; w = 2;', ctx);
27-
assert.strictEqual(2, ctx.w);
14+
assert.strictEqual(ctx.x, 1);

0 commit comments

Comments
 (0)