mirror of https://github.com/nodejs/node.git
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
parent
59dac01e4e
commit
3d4c663ee6
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue