Skip to content

Commit 5856c83

Browse files
committed
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 fa939f0 commit 5856c83

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

src/node_contextify.cc

+19-2
Original file line numberDiff line numberDiff line change
@@ -346,14 +346,21 @@ class ContextifyContext {
346346
return;
347347

348348
auto attributes = PropertyAttribute::None;
349-
bool is_declared = ctx->global_proxy()
349+
bool is_declared_on_global_proxy = ctx->global_proxy()
350350
->GetRealNamedPropertyAttributes(ctx->context(), property)
351351
.To(&attributes);
352352
bool read_only =
353353
static_cast<int>(attributes) &
354354
static_cast<int>(PropertyAttribute::ReadOnly);
355355

356-
if (is_declared && read_only)
356+
bool is_declared_on_sandbox = ctx->sandbox()
357+
->GetRealNamedPropertyAttributes(ctx->context(), property)
358+
.To(&attributes);
359+
read_only = read_only ||
360+
(static_cast<int>(attributes) &
361+
static_cast<int>(PropertyAttribute::ReadOnly));
362+
363+
if (read_only)
357364
return;
358365

359366
// true for x = 5
@@ -371,10 +378,20 @@ class ContextifyContext {
371378
// this.f = function() {}, is_contextual_store = false.
372379
bool is_function = value->IsFunction();
373380

381+
bool is_declared = is_declared_on_global_proxy || is_declared_on_sandbox;
374382
if (!is_declared && args.ShouldThrowOnError() && is_contextual_store &&
375383
!is_function)
376384
return;
377385

386+
if (!is_declared_on_global_proxy && is_declared_on_sandbox &&
387+
args.ShouldThrowOnError() && is_contextual_store && !is_function) {
388+
// The property exists on the sandbox but not on the global
389+
// proxy. Setting it would throw because we are in strict mode.
390+
// Don't attempt to set it by signaling that the call was
391+
// intercepted. Only change the value on the sandbox.
392+
args.GetReturnValue().Set(false);
393+
}
394+
378395
ctx->sandbox()->Set(property, value);
379396
}
380397

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

+2-5
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,8 @@ const vm = require('vm');
77

88
const ctx = vm.createContext({ x: 42 });
99

10-
// The following line wrongly throws an
11-
// error because GlobalPropertySetterCallback()
12-
// does not check if the property exists
13-
// on the sandbox. It should just set x to 1
14-
// instead of throwing an error.
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.
1512
vm.runInContext('"use strict"; x = 1', ctx);
1613

1714
assert.strictEqual(ctx.x, 1);

0 commit comments

Comments
 (0)