Bug 449657 - JS_SealObject fails on Array objects (r=mrbkap, a=sayrer).
authorBrendan Eich <brendan@mozilla.org>
Sun, 07 Dec 2008 00:03:12 -0800
changeset 24897 e7403f2cbd61516d54982dc155f54483ea4e5d87
parent 24896 aa493c1be6e01a75d9f540c4074ddd0051fcae89
child 24898 b3b5e2a64382bb6c2ff24d363a6ab1177d0d826f
push id1267
push userrsayre@mozilla.com
push dateSun, 19 Apr 2009 02:47:24 +0000
reviewersmrbkap, sayrer
bugs449657
milestone1.9.1b4pre
Bug 449657 - JS_SealObject fails on Array objects (r=mrbkap, a=sayrer).
js/src/jsapi.cpp
js/src/jsobj.cpp
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -832,17 +832,17 @@ JS_DestroyRuntime(JSRuntime *rt)
 #ifdef DEBUG
     /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
     if (!JS_CLIST_IS_EMPTY(&rt->contextList)) {
         JSContext *cx, *iter = NULL;
         uintN cxcount = 0;
         while ((cx = js_ContextIterator(rt, JS_TRUE, &iter)) != NULL) {
             fprintf(stderr,
 "JS API usage error: found live context at %p\n",
-                    cx);
+                    (void *) cx);
             cxcount++;
         }
         fprintf(stderr,
 "JS API usage error: %u context%s left in runtime upon JS_DestroyRuntime.\n",
                 cxcount, (cxcount == 1) ? "" : "s");
     }
 #endif
 
@@ -2925,16 +2925,19 @@ JS_NewObjectWithGivenProto(JSContext *cx
 JS_PUBLIC_API(JSBool)
 JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep)
 {
     JSScope *scope;
     JSIdArray *ida;
     uint32 nslots, i;
     jsval v;
 
+    if (OBJ_IS_DENSE_ARRAY(cx, obj) && !js_MakeArraySlow(cx, obj))
+        return JS_FALSE;
+
     if (!OBJ_IS_NATIVE(obj)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_CANT_SEAL_OBJECT,
                              OBJ_GET_CLASS(cx, obj)->name);
         return JS_FALSE;
     }
 
     scope = OBJ_SCOPE(obj);
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -4349,16 +4349,25 @@ js_SetPropertyHelper(JSContext *cx, JSOb
     uintN attrs, flags;
     intN shortid;
     JSClass *clasp;
     JSPropertyOp getter, setter;
 
     /* Convert string indices to integers if appropriate. */
     CHECK_FOR_STRING_INDEX(id);
 
+    /*
+     * We peek at OBJ_SCOPE(obj) without locking obj. Any race means a failure
+     * to seal before sharing, which is inherently ambiguous.
+     */
+    if (SCOPE_IS_SEALED(OBJ_SCOPE(obj)) && OBJ_SCOPE(obj)->object == obj) {
+        flags = JSREPORT_ERROR;
+        goto read_only_error;
+    }
+
     shape = OBJ_SHAPE(obj);
     protoIndex = js_LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags,
                                             &pobj, &prop);
     if (protoIndex < 0)
         return JS_FALSE;
 
     if (prop && !OBJ_IS_NATIVE(pobj)) {
         OBJ_DROP_PROPERTY(cx, pobj, prop);
@@ -4386,17 +4395,17 @@ js_SetPropertyHelper(JSContext *cx, JSOb
          * Set scope for use below.  It was locked by js_LookupProperty, and
          * we know pobj owns it (i.e., scope->object == pobj).  Therefore we
          * optimize JS_UNLOCK_OBJ(cx, pobj) into JS_UNLOCK_SCOPE(cx, scope).
          */
         scope = OBJ_SCOPE(pobj);
 
         attrs = sprop->attrs;
         if ((attrs & JSPROP_READONLY) ||
-            (SCOPE_IS_SEALED(scope) && pobj == obj)) {
+            (SCOPE_IS_SEALED(scope) && (attrs & JSPROP_SHARED))) {
             JS_UNLOCK_SCOPE(cx, scope);
 
             /*
              * Here, we'll either return true or goto read_only_error, which
              * reports a strict warning or throws an error.  So we redefine
              * the |flags| local variable to be JSREPORT_* flags to pass to
              * JS_ReportErrorFlagsAndNumberUC at label read_only_error.  We
              * must likewise re-task flags further below for the other 'goto
@@ -4473,21 +4482,16 @@ js_SetPropertyHelper(JSContext *cx, JSOb
         }
 #ifdef __GNUC__ /* suppress bogus gcc warnings */
     } else {
         scope = NULL;
 #endif
     }
 
     if (!sprop) {
-        if (SCOPE_IS_SEALED(OBJ_SCOPE(obj)) && OBJ_SCOPE(obj)->object == obj) {
-            flags = JSREPORT_ERROR;
-            goto read_only_error;
-        }
-
         /*
          * Purge the property cache of now-shadowed id in obj's scope chain.
          * Do this early, before locking obj to avoid nesting locks.
          */
         js_PurgeScopeChain(cx, obj, id);
 
         /* Find or make a property descriptor with the right heritage. */
         JS_LOCK_OBJ(cx, obj);