Bug 1022773 - Resolve hazard by switching Compile to MutableHandle, r=terrence,smaug,bholley

--HG--
extra : rebase_source : a6f4eb9138688c09bce15f36ffc0bdb5b6e3dc5f
This commit is contained in:
Steve Fink 2014-06-11 17:38:22 -07:00
parent 2fd16970b2
commit 0df35e9c80
6 changed files with 61 additions and 49 deletions

View File

@ -1535,13 +1535,15 @@ nsFrameScriptExecutor::TryCacheLoadAndCompileScript(const nsAString& aURL,
JS::Rooted<JSObject*> funobj(cx);
if (aRunInGlobalScope) {
options.setNoScriptRval(true);
script = JS::Compile(cx, JS::NullPtr(), options, srcBuf);
if (!JS::Compile(cx, JS::NullPtr(), options, srcBuf, &script)) {
return;
}
} else {
JS::Rooted<JSFunction *> fun(cx);
fun = JS::CompileFunction(cx, JS::NullPtr(), options,
nullptr, 0, nullptr, /* name, nargs, args */
srcBuf);
if (!fun) {
if (!JS::CompileFunction(cx, JS::NullPtr(), options,
nullptr, 0, nullptr, /* name, nargs, args */
srcBuf, &fun))
{
return;
}
funobj = JS_GetFunctionObject(fun);

View File

@ -2762,8 +2762,8 @@ nsXULPrototypeScript::Compile(JS::SourceBufferHolder& aSrcBuf,
// This reference will be consumed by the NotifyOffThreadScriptCompletedRunnable.
NS_ADDREF(aOffThreadReceiver);
} else {
JSScript* script = JS::Compile(cx, scope, options, aSrcBuf);
if (!script)
JS::Rooted<JSScript*> script(cx);
if (!JS::Compile(cx, scope, options, aSrcBuf, &script))
return NS_ERROR_OUT_OF_MEMORY;
Set(script);
}

View File

@ -4538,9 +4538,9 @@ JS::CompileOptions::wrap(JSContext *cx, JSCompartment *compartment)
return true;
}
JSScript *
bool
JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
SourceBufferHolder &srcBuf)
SourceBufferHolder &srcBuf, MutableHandleScript script)
{
JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
AssertHeapIsIdle(cx);
@ -4548,7 +4548,8 @@ JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optio
assertSameCompartment(cx, obj);
AutoLastFrameCheck lfc(cx);
return frontend::CompileScript(cx, &cx->tempLifoAlloc(), obj, NullPtr(), options, srcBuf);
script.set(frontend::CompileScript(cx, &cx->tempLifoAlloc(), obj, NullPtr(), options, srcBuf));
return !!script;
}
JSScript *
@ -4556,7 +4557,10 @@ JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optio
const jschar *chars, size_t length)
{
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
return Compile(cx, obj, options, srcBuf);
RootedScript script(cx);
if (!Compile(cx, obj, options, srcBuf, &script))
return nullptr;
return script;
}
JSScript *
@ -4595,8 +4599,7 @@ JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optio
return nullptr;
CompileOptions options(cx, optionsArg);
options.setFileAndLine(filename, 1);
JSScript *script = Compile(cx, obj, options, file.fp());
return script;
return Compile(cx, obj, options, file.fp());
}
JS_PUBLIC_API(bool)
@ -4709,10 +4712,10 @@ JS_GetGlobalFromScript(JSScript *script)
return &script->global();
}
JS_PUBLIC_API(JSFunction *)
JS_PUBLIC_API(bool)
JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
const char *name, unsigned nargs, const char *const *argnames,
SourceBufferHolder &srcBuf)
SourceBufferHolder &srcBuf, MutableHandleFunction fun)
{
JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
AssertHeapIsIdle(cx);
@ -4724,32 +4727,32 @@ JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOption
if (name) {
funAtom = Atomize(cx, name, strlen(name));
if (!funAtom)
return nullptr;
return false;
}
AutoNameVector formals(cx);
for (unsigned i = 0; i < nargs; i++) {
RootedAtom argAtom(cx, Atomize(cx, argnames[i], strlen(argnames[i])));
if (!argAtom || !formals.append(argAtom->asPropertyName()))
return nullptr;
return false;
}
RootedFunction fun(cx, NewFunction(cx, NullPtr(), nullptr, 0, JSFunction::INTERPRETED, obj,
funAtom, JSFunction::FinalizeKind, TenuredObject));
fun.set(NewFunction(cx, NullPtr(), nullptr, 0, JSFunction::INTERPRETED, obj,
funAtom, JSFunction::FinalizeKind, TenuredObject));
if (!fun)
return nullptr;
return false;
if (!frontend::CompileFunctionBody(cx, &fun, options, formals, srcBuf))
return nullptr;
if (!frontend::CompileFunctionBody(cx, fun, options, formals, srcBuf))
return false;
if (obj && funAtom && options.defineOnScope) {
Rooted<jsid> id(cx, AtomToId(funAtom));
RootedValue value(cx, ObjectValue(*fun));
if (!JSObject::defineGeneric(cx, obj, id, value, nullptr, nullptr, JSPROP_ENUMERATE))
return nullptr;
return false;
}
return fun;
return true;
}
JS_PUBLIC_API(JSFunction *)
@ -4757,8 +4760,11 @@ JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOption
const char *name, unsigned nargs, const char *const *argnames,
const jschar *chars, size_t length)
{
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
return JS::CompileFunction(cx, obj, options, name, nargs, argnames, srcBuf);
RootedFunction fun(cx);
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
if (!JS::CompileFunction(cx, obj, options, name, nargs, argnames, srcBuf, &fun))
return nullptr;
return fun;
}
JS_PUBLIC_API(JSFunction *)

View File

@ -3760,6 +3760,13 @@ class MOZ_STACK_CLASS JS_FRIEND_API(CompileOptions) : public ReadOnlyCompileOpti
void operator=(const CompileOptions &rhs) MOZ_DELETE;
};
/*
* |script| will always be set. On failure, it will be set to nullptr.
*/
extern JS_PUBLIC_API(bool)
Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
SourceBufferHolder &srcBuf, JS::MutableHandleScript script);
extern JS_PUBLIC_API(JSScript *)
Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
const char *bytes, size_t length);
@ -3768,10 +3775,6 @@ extern JS_PUBLIC_API(JSScript *)
Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
const jschar *chars, size_t length);
extern JS_PUBLIC_API(JSScript *)
Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
SourceBufferHolder &srcBuf);
extern JS_PUBLIC_API(JSScript *)
Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, FILE *file);
@ -3805,6 +3808,11 @@ CompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options,
extern JS_PUBLIC_API(JSScript *)
FinishOffThreadScript(JSContext *maybecx, JSRuntime *rt, void *token);
extern JS_PUBLIC_API(bool)
CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
const char *name, unsigned nargs, const char *const *argnames,
SourceBufferHolder &srcBuf, JS::MutableHandleFunction fun);
extern JS_PUBLIC_API(JSFunction *)
CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
const char *name, unsigned nargs, const char *const *argnames,
@ -3815,11 +3823,6 @@ CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOption
const char *name, unsigned nargs, const char *const *argnames,
const jschar *chars, size_t length);
extern JS_PUBLIC_API(JSFunction *)
CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
const char *name, unsigned nargs, const char *const *argnames,
SourceBufferHolder &srcBuf);
} /* namespace JS */
extern JS_PUBLIC_API(JSString *)

View File

@ -95,13 +95,13 @@ nsresult
mozJSSubScriptLoader::ReadScript(nsIURI *uri, JSContext *cx, JSObject *targetObjArg,
const nsAString &charset, const char *uriStr,
nsIIOService *serv, nsIPrincipal *principal,
bool reuseGlobal, JSScript **scriptp,
JSFunction **functionp)
bool reuseGlobal, JS::MutableHandleScript script,
JS::MutableHandleFunction function)
{
RootedObject target_obj(cx, targetObjArg);
*scriptp = nullptr;
*functionp = nullptr;
script.set(nullptr);
function.set(nullptr);
// Instead of calling NS_OpenURI, we create the channel ourselves and call
// SetContentType, to avoid expensive MIME type lookups (bug 632490).
@ -155,22 +155,23 @@ mozJSSubScriptLoader::ReadScript(nsIURI *uri, JSContext *cx, JSObject *targetObj
}
if (!reuseGlobal) {
*scriptp = JS::Compile(cx, target_obj, options, srcBuf);
JS::Compile(cx, target_obj, options, srcBuf, script);
} else {
*functionp = JS::CompileFunction(cx, target_obj, options,
nullptr, 0, nullptr,
srcBuf);
JS::CompileFunction(cx, target_obj, options,
nullptr, 0, nullptr,
srcBuf,
function);
}
} else {
// We only use lazy source when no special encoding is specified because
// the lazy source loader doesn't know the encoding.
if (!reuseGlobal) {
options.setSourceIsLazy(true);
*scriptp = JS::Compile(cx, target_obj, options, buf.get(), len);
script.set(JS::Compile(cx, target_obj, options, buf.get(), len));
} else {
*functionp = JS::CompileFunction(cx, target_obj, options,
function.set(JS::CompileFunction(cx, target_obj, options,
nullptr, 0, nullptr, buf.get(),
len);
len));
}
}
@ -333,7 +334,7 @@ mozJSSubScriptLoader::DoLoadSubScriptWithOptions(const nsAString &url,
if (!script) {
rv = ReadScript(uri, cx, targetObj, options.charset,
static_cast<const char*>(uriStr.get()), serv,
principal, reusingGlobal, script.address(), function.address());
principal, reusingGlobal, &script, &function);
writeScript = !!script;
}

View File

@ -36,8 +36,8 @@ private:
nsresult ReadScript(nsIURI *uri, JSContext *cx, JSObject *target_obj,
const nsAString &charset, const char *uriStr,
nsIIOService *serv, nsIPrincipal *principal,
bool reuseGlobal, JSScript **scriptp,
JSFunction **functionp);
bool reuseGlobal, JS::MutableHandleScript script,
JS::MutableHandleFunction function);
nsresult DoLoadSubScriptWithOptions(const nsAString &url,
LoadSubScriptOptions &options,