Bug 1264613 - Allow object-to-nonobject serialization. r=baku a=lizzard
authorPip <pipcet@gmail.com>
Tue, 19 Apr 2016 10:26:00 +0200
changeset 332866 21500d655b72b17af8acbc2d72a1305b70110475
parent 332865 9b852d619c4905ec61dedb1aeca3c00e2641456f
child 332867 17fd7b532dcf040a0e9e6c825e47c912a52d4c53
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku, lizzard
bugs1264613
milestone48.0a2
Bug 1264613 - Allow object-to-nonobject serialization. r=baku a=lizzard Fix the Structured Clone API to avoid assigning a numeric back-reference id to objects that are serialized as non-objects; in particular, this fixes incorrect serialization and crashes upon deserialization when a DedicatedWorkerGlobalScope is serialized twice in the same serialization packet.
dom/base/Console.cpp
js/public/StructuredClone.h
js/src/vm/StructuredClone.cpp
--- a/dom/base/Console.cpp
+++ b/dom/base/Console.cpp
@@ -540,16 +540,20 @@ protected:
                                          mClonedData.mBlobs.Length()))) {
         return false;
       }
 
       mClonedData.mBlobs.AppendElement(blob->Impl());
       return true;
     }
 
+    if (!JS_ObjectNotWritten(aWriter, aObj)) {
+      return false;
+    }
+
     JS::Rooted<JS::Value> value(aCx, JS::ObjectOrNullValue(aObj));
     JS::Rooted<JSString*> jsString(aCx, JS::ToString(aCx, value));
     if (NS_WARN_IF(!jsString)) {
       return false;
     }
 
     if (NS_WARN_IF(!JS_WriteString(aWriter, jsString))) {
       return false;
--- a/js/public/StructuredClone.h
+++ b/js/public/StructuredClone.h
@@ -276,9 +276,12 @@ JS_PUBLIC_API(bool)
 JS_WriteBytes(JSStructuredCloneWriter* w, const void* p, size_t len);
 
 JS_PUBLIC_API(bool)
 JS_WriteString(JSStructuredCloneWriter* w, JS::HandleString str);
 
 JS_PUBLIC_API(bool)
 JS_WriteTypedArray(JSStructuredCloneWriter* w, JS::HandleValue v);
 
+JS_PUBLIC_API(bool)
+JS_ObjectNotWritten(JSStructuredCloneWriter* w, JS::HandleObject obj);
+
 #endif  /* js_StructuredClone_h */
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -351,16 +351,17 @@ struct JSStructuredCloneWriter {
     void* closure;
 
     // Set of transferable objects
     RootedValue transferable;
     Rooted<GCHashSet<JSObject*>> transferableObjects;
 
     friend bool JS_WriteString(JSStructuredCloneWriter* w, HandleString str);
     friend bool JS_WriteTypedArray(JSStructuredCloneWriter* w, HandleValue v);
+    friend bool JS_ObjectNotWritten(JSStructuredCloneWriter* w, HandleObject obj);
 };
 
 JS_FRIEND_API(uint64_t)
 js::GetSCOffset(JSStructuredCloneWriter* writer)
 {
     MOZ_ASSERT(writer);
     return writer->output().count() * sizeof(uint64_t);
 }
@@ -1758,17 +1759,17 @@ JSStructuredCloneReader::startRead(Mutab
                         : (JSObject*) NewBuiltinClassInstance<PlainObject>(context());
         if (!obj || !objs.append(ObjectValue(*obj)))
             return false;
         vp.setObject(*obj);
         break;
       }
 
       case SCTAG_BACK_REFERENCE_OBJECT: {
-        if (data >= allObjs.length()) {
+        if (data >= allObjs.length() || !allObjs[data].isObject()) {
             JS_ReportErrorNumber(context(), GetErrorMessage, nullptr,
                                  JSMSG_SC_BAD_SERIALIZED_DATA,
                                  "invalid back reference in input");
             return false;
         }
         vp.set(allObjs[data]);
         return true;
       }
@@ -2417,8 +2418,16 @@ JS_WriteString(JSStructuredCloneWriter* 
 JS_PUBLIC_API(bool)
 JS_WriteTypedArray(JSStructuredCloneWriter* w, HandleValue v)
 {
     MOZ_ASSERT(v.isObject());
     assertSameCompartment(w->context(), v);
     RootedObject obj(w->context(), &v.toObject());
     return w->writeTypedArray(obj);
 }
+
+JS_PUBLIC_API(bool)
+JS_ObjectNotWritten(JSStructuredCloneWriter* w, HandleObject obj)
+{
+    w->memory.remove(w->memory.lookup(obj));
+
+    return true;
+}