diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 0291ef814aa..872262aa46f 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -2450,15 +2450,14 @@ unsigned js_InferFlags(JSContext *cx, unsigned defaultFlags) { /* - * Use ScriptFrameIter since we intentionally want to look across - * compartment boundaries in the case of cross-compartment property access. + * We intentionally want to look across compartment boundaries to correctly + * handle the case of cross-compartment property access. */ - ScriptFrameIter i(cx); - if (i.done()) + jsbytecode *pc; + JSScript *script = cx->stack.currentScript(&pc, ContextStack::ALLOW_CROSS_COMPARTMENT); + if (!script) return defaultFlags; - jsbytecode *pc = i.pc(); - JSScript *script = i.script(); const JSCodeSpec *cs = &js_CodeSpec[*pc]; uint32_t format = cs->format; unsigned flags = 0; diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h index 7304799f202..559a3cc3c50 100644 --- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -516,7 +516,8 @@ ContextStack::popFrameAfterOverflow() } inline JSScript * -ContextStack::currentScript(jsbytecode **ppc) const +ContextStack::currentScript(jsbytecode **ppc, + MaybeAllowCrossCompartment allowCrossCompartment) const { if (ppc) *ppc = NULL; @@ -531,7 +532,7 @@ ContextStack::currentScript(jsbytecode **ppc) const if (fp->beginsIonActivation()) { JSScript *script = NULL; ion::GetPcScript(cx_, &script, ppc); - if (script->compartment() != cx_->compartment) + if (!allowCrossCompartment && script->compartment() != cx_->compartment) return NULL; return script; } @@ -544,7 +545,7 @@ ContextStack::currentScript(jsbytecode **ppc) const JS_ASSERT(inlined->inlineIndex < chunk->nInlineFrames); mjit::InlineFrame *frame = &chunk->inlineFrames()[inlined->inlineIndex]; JSScript *script = frame->fun->script(); - if (script->compartment() != cx_->compartment) + if (!allowCrossCompartment && script->compartment() != cx_->compartment) return NULL; if (ppc) *ppc = script->code + inlined->pcOffset; @@ -553,7 +554,7 @@ ContextStack::currentScript(jsbytecode **ppc) const #endif JSScript *script = fp->script(); - if (script->compartment() != cx_->compartment) + if (!allowCrossCompartment && script->compartment() != cx_->compartment) return NULL; if (ppc) diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h index 3ede461919c..5a646b758bf 100644 --- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -1588,8 +1588,18 @@ class ContextStack /* Pop a partially-pushed frame after hitting the limit before throwing. */ void popFrameAfterOverflow(); - /* Get the topmost script and optional pc on the stack. */ - inline JSScript *currentScript(jsbytecode **pc = NULL) const; + /* + * Get the topmost script and optional pc on the stack. By default, this + * function only returns a JSScript in the current compartment, returning + * NULL if the current script is in a different compartment. This behavior + * can be overridden by passing ALLOW_CROSS_COMPARTMENT. + */ + enum MaybeAllowCrossCompartment { + DONT_ALLOW_CROSS_COMPARTMENT = false, + ALLOW_CROSS_COMPARTMENT = true + }; + inline JSScript *currentScript(jsbytecode **pc = NULL, + MaybeAllowCrossCompartment = DONT_ALLOW_CROSS_COMPARTMENT) const; /* Get the scope chain for the topmost scripted call on the stack. */ inline HandleObject currentScriptedScopeChain() const;