From bcdbbde4dcfecfbe0213d8b68501c90cd4e4e5ed Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Wed, 22 Jan 2014 16:41:15 -0800 Subject: [PATCH] Bug 952885: When doing cross-global compilations in the shell, properly wrap CompileOptions members for the new global. r=njn --- .../jit-test/tests/debug/Source-element-02.js | 6 +++++ js/src/jsapi.cpp | 24 +++++++++++++++++++ js/src/jsapi.h | 8 +++++++ js/src/shell/js.cpp | 2 ++ 4 files changed, 40 insertions(+) create mode 100644 js/src/jit-test/tests/debug/Source-element-02.js diff --git a/js/src/jit-test/tests/debug/Source-element-02.js b/js/src/jit-test/tests/debug/Source-element-02.js new file mode 100644 index 000000000000..38c92280b48a --- /dev/null +++ b/js/src/jit-test/tests/debug/Source-element-02.js @@ -0,0 +1,6 @@ +// Specifying an owning element in a cross-global evaluation shouldn't crash. +// That is, when 'evaluate' switches compartments, it should properly wrap +// the CompileOptions members that will become cross-compartment +// references. + +evaluate('42 + 1729', { global: newGlobal(), element: {} }); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 02fc703653f9..55347eceb30e 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4373,6 +4373,18 @@ JS::OwningCompileOptions::setSourceMapURL(JSContext *cx, const jschar *s) return true; } +bool +JS::OwningCompileOptions::wrap(JSContext *cx, JSCompartment *compartment) +{ + if (!compartment->wrap(cx, &elementRoot)) + return false; + if (elementPropertyRoot) { + if (!compartment->wrap(cx, elementPropertyRoot.address())) + return false; + } + return true; +} + JS::CompileOptions::CompileOptions(JSContext *cx, JSVersion version) : ReadOnlyCompileOptions(), elementRoot(cx), elementPropertyRoot(cx) { @@ -4386,6 +4398,18 @@ JS::CompileOptions::CompileOptions(JSContext *cx, JSVersion version) asmJSOption = cx->options().asmJS(); } +bool +JS::CompileOptions::wrap(JSContext *cx, JSCompartment *compartment) +{ + if (!compartment->wrap(cx, &elementRoot)) + return false; + if (elementPropertyRoot) { + if (!compartment->wrap(cx, elementPropertyRoot.address())) + return false; + } + return true; +} + JSScript * JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options, const jschar *chars, size_t length) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index d533a3044f95..1674f8312d2a 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -3506,6 +3506,10 @@ class JS_FRIEND_API(ReadOnlyCompileOptions) SAVE_SOURCE } sourcePolicy; + // Wrap any compilation option values that need it as appropriate for + // use from |compartment|. + virtual bool wrap(JSContext *cx, JSCompartment *compartment) = 0; + private: static JSObject * const nullObjectPtr; void operator=(const ReadOnlyCompileOptions &) MOZ_DELETE; @@ -3576,6 +3580,8 @@ class JS_FRIEND_API(OwningCompileOptions) : public ReadOnlyCompileOptions OwningCompileOptions &setSelfHostingMode(bool shm) { selfHostingMode = shm; return *this; } OwningCompileOptions &setCanLazilyParse(bool clp) { canLazilyParse = clp; return *this; } OwningCompileOptions &setSourcePolicy(SourcePolicy sp) { sourcePolicy = sp; return *this; } + + virtual bool wrap(JSContext *cx, JSCompartment *compartment) MOZ_OVERRIDE; }; /* @@ -3632,6 +3638,8 @@ class MOZ_STACK_CLASS JS_FRIEND_API(CompileOptions) : public ReadOnlyCompileOpti CompileOptions &setSelfHostingMode(bool shm) { selfHostingMode = shm; return *this; } CompileOptions &setCanLazilyParse(bool clp) { canLazilyParse = clp; return *this; } CompileOptions &setSourcePolicy(SourcePolicy sp) { sourcePolicy = sp; return *this; } + + virtual bool wrap(JSContext *cx, JSCompartment *compartment) MOZ_OVERRIDE; }; extern JS_PUBLIC_API(JSScript *) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 597e2b29029d..e627151841ef 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -1019,6 +1019,8 @@ Evaluate(JSContext *cx, unsigned argc, jsval *vp) .setElementProperty(elementProperty) .setSourcePolicy(sourcePolicy) .setCompileAndGo(compileAndGo); + if (!options.wrap(cx, cx->compartment())) + return false; script = JS::Compile(cx, global, options, codeChars, codeLength); if (!script)