Bug 655921 - Check for Function being forbidden before creating the function private which would ordinarily be returned. Also create that function private with an explicitly specified parent, that being the Function function's global object. r=mrbkap
authorJeff Walden <jwalden@mit.edu>
Tue, 10 May 2011 14:56:49 -0700
changeset 69939 6408576c8e08977702ed406cd3583f30e0dcc613
parent 69938 993f0935af4ca6629737f6f24f799a168fb54ee8
child 69940 8af92dba248083b17c0c2c3621cbc2df789ac010
push id20142
push usercleary@mozilla.com
push dateMon, 23 May 2011 07:31:35 +0000
treeherdermozilla-central@0f9347d40121 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs655921
milestone6.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 655921 - Check for Function being forbidden before creating the function private which would ordinarily be returned. Also create that function private with an explicitly specified parent, that being the Function function's global object. r=mrbkap
js/src/jsfun.cpp
js/src/jsobjinlines.h
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -2431,47 +2431,38 @@ OnBadFormal(JSContext *cx, TokenKind tt)
     return false;
 }
 
 static JSBool
 Function(JSContext *cx, uintN argc, Value *vp)
 {
     CallArgs call = CallArgsFromVp(argc, vp);
 
-    JS::Anchor<JSObject *> obj(NewFunction(cx, NULL));
+    /* Block this call if security callbacks forbid it. */
+    GlobalObject *global = call.callee().getGlobal();
+    if (!global->isEvalAllowed(cx)) {
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_FUNCTION);
+        return false;
+    }
+
+    JS::Anchor<JSObject *> obj(NewFunction(cx, *global));
     if (!obj.get())
         return false;
 
-    JSObject &calleeParent = *call.callee().getParent();
-
     /*
      * NB: (new Function) is not lexically closed by its caller, it's just an
      * anonymous function in the top-level scope that its constructor inhabits.
      * Thus 'var x = 42; f = new Function("return x"); print(f())' prints 42,
      * and so would a call to f from another top-level's script or function.
-     *
-     * In older versions, before call objects, a new Function was adopted by
-     * its running context's globalObject, which might be different from the
-     * top-level reachable from scopeChain (in HTML frames, e.g.).
      */
     JSFunction *fun = js_NewFunction(cx, obj.get(), NULL, 0, JSFUN_LAMBDA | JSFUN_INTERPRETED,
-                                     &calleeParent, cx->runtime->atomState.anonymousAtom);
+                                     global, cx->runtime->atomState.anonymousAtom);
     if (!fun)
         return false;
 
-    /*
-     * CSP check: whether new Function() is allowed at all.
-     * Report errors via CSP is done in the script security manager.
-     * js_CheckContentSecurityPolicy is defined in jsobj.cpp
-     */
-    if (!js_CheckContentSecurityPolicy(cx, &calleeParent)) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_FUNCTION);
-        return false;
-    }
-
     EmptyShape *emptyCallShape = EmptyShape::getEmptyCallShape(cx);
     if (!emptyCallShape)
         return false;
     AutoShapeRooter shapeRoot(cx, emptyCallShape);
 
     Bindings bindings(cx, emptyCallShape);
     AutoBindingsRooter root(cx, bindings);
 
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -1250,16 +1250,26 @@ NewObject(JSContext *cx, js::Class *clas
 
 out:
     Probes::createObject(cx, obj);
     return obj;
 }
 } /* namespace detail */
 
 static JS_ALWAYS_INLINE JSObject *
+NewFunction(JSContext *cx, js::GlobalObject &global)
+{
+    JSObject *proto;
+    if (!js_GetClassPrototype(cx, &global, JSProto_Function, &proto))
+        return NULL;
+    return detail::NewObject<WithProto::Given, true>(cx, &js_FunctionClass, proto, &global,
+                                                     gc::FINALIZE_OBJECT2);
+}
+
+static JS_ALWAYS_INLINE JSObject *
 NewFunction(JSContext *cx, JSObject *parent)
 {
     return detail::NewObject<WithProto::Class, true>(cx, &js_FunctionClass, NULL, parent,
                                                      gc::FINALIZE_OBJECT2);
 }
 
 template <WithProto::e withProto>
 static JS_ALWAYS_INLINE JSObject *