Merge backout.
authorRobert Sayre <sayrer@gmail.com>
Wed, 04 Aug 2010 13:45:02 -0700
changeset 48870 5be15126f539fa02489e9bbb423183642f5a902d
parent 48868 6cc5db7e2fad25e597e40bb77ab8a2a5300248fe (current diff)
parent 48869 f7478476c9a5d4a650d764a967c8dedce7e5883f (diff)
child 48871 1d8d2deb36442e11ebe2d601576be93caa16eb86
push idunknown
push userunknown
push dateunknown
milestone2.0b4pre
Merge backout.
js/src/jsobj.cpp
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -5587,16 +5587,49 @@ js_GetClassPrototype(JSContext *cx, JSOb
                 return true;
             }
         }
     }
 
     return FindClassPrototype(cx, scope, protoKey, protop, clasp);
 }
 
+/*
+ * For shared precompilation of function objects, we support cloning on entry
+ * to an execution context in which the function declaration or expression
+ * should be processed as if it were not precompiled, where the precompiled
+ * function's scope chain does not match the execution context's.  The cloned
+ * function object carries its execution-context scope in its parent slot; it
+ * links to the precompiled function (the "clone-parent") via its proto slot.
+ *
+ * Note that this prototype-based delegation leaves an unchecked access path
+ * from the clone to the clone-parent's 'constructor' property.  If the clone
+ * lives in a less privileged or shared scope than the clone-parent, this is
+ * a security hole, a sharing hazard, or both.  Therefore we check all such
+ * accesses with the following getter/setter pair, which we use when defining
+ * 'constructor' in f.prototype for all function objects f.
+ */
+static JSBool
+CheckCtorGetAccess(JSContext *cx, JSObject *obj, jsid id, Value *vp)
+{
+    JSAtom *atom = cx->runtime->atomState.constructorAtom;
+    JS_ASSERT(id == ATOM_TO_JSID(atom));
+    uintN attrs;
+    return CheckAccess(cx, obj, ATOM_TO_JSID(atom), JSACC_READ, vp, &attrs);
+}
+
+static JSBool
+CheckCtorSetAccess(JSContext *cx, JSObject *obj, jsid id, Value *vp)
+{
+    JSAtom *atom = cx->runtime->atomState.constructorAtom;
+    JS_ASSERT(id == ATOM_TO_JSID(atom));
+    uintN attrs;
+    return CheckAccess(cx, obj, ATOM_TO_JSID(atom), JSACC_WRITE, vp, &attrs);
+}
+
 JSBool
 js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto, uintN attrs)
 {
     /*
      * Use the given attributes for the prototype property of the constructor,
      * as user-defined constructors have a DontDelete prototype (which may be
      * reset), while native or "system" constructors have DontEnum | ReadOnly |
      * DontDelete.
@@ -5606,17 +5639,17 @@ js_SetClassPrototype(JSContext *cx, JSOb
         return JS_FALSE;
     }
 
     /*
      * ECMA says that Object.prototype.constructor, or f.prototype.constructor
      * for a user-defined function f, is DontEnum.
      */
     return proto->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.constructorAtom),
-                                 ObjectOrNullValue(ctor), PropertyStub, PropertyStub, 0);
+                                 ObjectOrNullValue(ctor), CheckCtorGetAccess, CheckCtorSetAccess, 0);
 }
 
 JSBool
 js_PrimitiveToObject(JSContext *cx, Value *vp)
 {
     Value v = *vp;
     JS_ASSERT(v.isPrimitive());