From 823f726f665fdaace0533859191ca5c6f5d4101b Mon Sep 17 00:00:00 2001 From: Ali Ijaz Sheikh Date: Fri, 18 Mar 2016 11:32:44 -0700 Subject: [PATCH] contextify: tie lifetimes of context & sandbox When the previous set of changes (bfff07b) it was possible to have the context get garbage collected while sandbox was still live. We need to tie the lifetime of the context to the lifetime of the sandbox. This is a backport of #5786 to v5.x. Ref: https://github.com/nodejs/node/pull/5786 PR-URL: https://github.com/nodejs/node/pull/5800 Reviewed-By: Ben Noordhuis Reviewed-By: Colin Ihrig Reviewed-By: James M Snell --- src/node_contextify.cc | 10 ++++++++++ test/parallel/test-vm-create-and-run-in-context.js | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/src/node_contextify.cc b/src/node_contextify.cc index 16019a0ecb3002..8235dcd49e093c 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -207,7 +207,17 @@ class ContextifyContext { CHECK(!ctx.IsEmpty()); ctx->SetSecurityToken(env->context()->GetSecurityToken()); + + // We need to tie the lifetime of the sandbox object with the lifetime of + // newly created context. We do this by making them hold references to each + // other. The context can directly hold a reference to the sandbox as an + // embedder data field. However, we cannot hold a reference to a v8::Context + // directly in an Object, we instead hold onto the new context's global + // object instead (which then has a reference to the context). ctx->SetEmbedderData(kSandboxObjectIndex, sandbox_obj); + sandbox_obj->SetHiddenValue( + FIXED_ONE_BYTE_STRING(env->isolate(), "_contextifyHiddenGlobal"), + ctx->Global()); env->AssignToContext(ctx); diff --git a/test/parallel/test-vm-create-and-run-in-context.js b/test/parallel/test-vm-create-and-run-in-context.js index 94527598ca27b1..15efc8f527b8c9 100644 --- a/test/parallel/test-vm-create-and-run-in-context.js +++ b/test/parallel/test-vm-create-and-run-in-context.js @@ -1,4 +1,5 @@ 'use strict'; +// Flags: --expose-gc require('../common'); var assert = require('assert'); @@ -18,3 +19,11 @@ console.error('test updating context'); result = vm.runInContext('var foo = 3;', context); assert.equal(3, context.foo); assert.equal('lala', context.thing); + +// https://github.com/nodejs/node/issues/5768 +console.error('run in contextified sandbox without referencing the context'); +var sandbox = {x: 1}; +vm.createContext(sandbox); +gc(); +vm.runInContext('x = 2', sandbox); +// Should not crash.