contextify: dealloc only after global and sandbox

Functions created using: `vm.runInNewContext('(function() { })')` will
reference only `proxy_global_` object and not `sandbox_`. Thus in case,
where there're no references to sandbox (such as in example above),
`ContextifyContext` will be destroyed and use-after-free might happen.
archived-io.js-v0.10
Fedor Indutny 2013-09-12 17:51:55 +04:00
parent 59dac01e4e
commit 3d4c663ee6
2 changed files with 17 additions and 2 deletions

View File

@ -58,15 +58,20 @@ class ContextifyContext {
Persistent<Object> sandbox_; Persistent<Object> sandbox_;
Persistent<Context> context_; Persistent<Context> context_;
Persistent<Object> proxy_global_; Persistent<Object> proxy_global_;
int references_;
public: public:
explicit ContextifyContext(Environment* env, Local<Object> sandbox) explicit ContextifyContext(Environment* env, Local<Object> sandbox)
: env_(env) : env_(env)
, sandbox_(env->isolate(), sandbox) , sandbox_(env->isolate(), sandbox)
, context_(env->isolate(), CreateV8Context(env)) , context_(env->isolate(), CreateV8Context(env))
, proxy_global_(env->isolate(), context()->Global()) { , proxy_global_(env->isolate(), context()->Global())
// Wait for both sandbox_'s and proxy_global_'s death
, references_(2) {
sandbox_.MakeWeak(this, SandboxFreeCallback); sandbox_.MakeWeak(this, SandboxFreeCallback);
sandbox_.MarkIndependent(); sandbox_.MarkIndependent();
proxy_global_.MakeWeak(this, SandboxFreeCallback);
proxy_global_.MarkIndependent();
} }
@ -173,6 +178,7 @@ class ContextifyContext {
static void SandboxFreeCallback(Isolate* isolate, static void SandboxFreeCallback(Isolate* isolate,
Persistent<Object>* target, Persistent<Object>* target,
ContextifyContext* context) { ContextifyContext* context) {
if (--context->references_ == 0)
delete context; delete context;
} }

View File

@ -19,10 +19,14 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE. // USE OR OTHER DEALINGS IN THE SOFTWARE.
// Flags: --expose-gc
var common = require('../common'); var common = require('../common');
var assert = require('assert'); var assert = require('assert');
var vm = require('vm'); var vm = require('vm');
assert.equal(typeof gc, 'function', 'Run this test with --expose-gc');
common.globalCheck = false; common.globalCheck = false;
console.error('run a string'); console.error('run a string');
@ -60,3 +64,8 @@ var f = { a: 1 };
vm.runInNewContext('f.a = 2', { f: f }); vm.runInNewContext('f.a = 2', { f: f });
assert.equal(f.a, 2); assert.equal(f.a, 2);
console.error('use function in context without referencing context');
var fn = vm.runInNewContext('(function() { obj.p = {}; })', { obj: {} })
gc();
fn();
// Should not crash