Bug 1539261, part 2 - Mark various JSStructuredCloneData methods MOZ_MUST_USE. r=sfink
authorAndrew McCreight <continuation@gmail.com>
Wed, 27 Mar 2019 20:41:17 +0000
changeset 466454 ebcc9bb7c50aa1f28ca7888cf10f7772a56c9db4
parent 466453 054cbaead3039d477667f2a0ef400e44015543c8
child 466455 8ad6e540906c9d0501ada6a6754e5a5195860118
push id35768
push useropoprus@mozilla.com
push dateThu, 28 Mar 2019 09:55:54 +0000
treeherdermozilla-central@c045dd97faf2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1539261
milestone68.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 1539261, part 2 - Mark various JSStructuredCloneData methods MOZ_MUST_USE. r=sfink Also, fix up various places that call these methods. Depends on D24991 Differential Revision: https://phabricator.services.mozilla.com/D24992
dom/base/nsStructuredCloneContainer.cpp
dom/ipc/StructuredCloneData.h
ipc/glue/IPCMessageUtils.h
js/public/StructuredClone.h
js/src/builtin/TestingFunctions.cpp
js/src/fuzz-tests/testStructuredCloneReader.cpp
--- a/dom/base/nsStructuredCloneContainer.cpp
+++ b/dom/base/nsStructuredCloneContainer.cpp
@@ -125,17 +125,19 @@ nsStructuredCloneContainer::GetDataAsBas
   if (HasClonedDOMObjects()) {
     return NS_ERROR_FAILURE;
   }
 
   auto iter = Data().Start();
   size_t size = Data().Size();
   nsAutoCString binaryData;
   binaryData.SetLength(size);
-  Data().ReadBytes(iter, binaryData.BeginWriting(), size);
+  if (!Data().ReadBytes(iter, binaryData.BeginWriting(), size)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
   nsAutoCString base64Data;
   nsresult rv = Base64Encode(binaryData, base64Data);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (!CopyASCIItoUTF16(base64Data, aOut, fallible)) {
     return NS_ERROR_OUT_OF_MEMORY;
--- a/dom/ipc/StructuredCloneData.h
+++ b/dom/ipc/StructuredCloneData.h
@@ -47,26 +47,26 @@ namespace ipc {
 class SharedJSAllocatedData final {
  public:
   explicit SharedJSAllocatedData(JSStructuredCloneData&& aData)
       : mData(std::move(aData)) {}
 
   static already_AddRefed<SharedJSAllocatedData> CreateFromExternalData(
       const char* aData, size_t aDataLength) {
     JSStructuredCloneData buf(JS::StructuredCloneScope::DifferentProcess);
-    buf.AppendBytes(aData, aDataLength);
+    NS_ENSURE_TRUE(buf.AppendBytes(aData, aDataLength), nullptr);
     RefPtr<SharedJSAllocatedData> sharedData =
         new SharedJSAllocatedData(std::move(buf));
     return sharedData.forget();
   }
 
   static already_AddRefed<SharedJSAllocatedData> CreateFromExternalData(
       const JSStructuredCloneData& aData) {
     JSStructuredCloneData buf(aData.scope());
-    buf.Append(aData);
+    NS_ENSURE_TRUE(buf.Append(aData), nullptr);
     RefPtr<SharedJSAllocatedData> sharedData =
         new SharedJSAllocatedData(std::move(buf));
     return sharedData.forget();
   }
 
   NS_INLINE_DECL_REFCOUNTING(SharedJSAllocatedData)
 
   JSStructuredCloneData& Data() { return mData; }
--- a/ipc/glue/IPCMessageUtils.h
+++ b/ipc/glue/IPCMessageUtils.h
@@ -79,17 +79,17 @@ struct SerializedStructuredCloneBuffer f
       : SerializedStructuredCloneBuffer() {
     *this = aOther;
   }
 
   SerializedStructuredCloneBuffer& operator=(
       const SerializedStructuredCloneBuffer& aOther) {
     data.Clear();
     data.initScope(aOther.data.scope());
-    data.Append(aOther.data);
+    MOZ_RELEASE_ASSERT(data.Append(aOther.data), "out of memory");
     return *this;
   }
 
   bool operator==(const SerializedStructuredCloneBuffer& aOther) const {
     // The copy assignment operator and the equality operator are
     // needed by the IPDL generated code. We relied on the copy
     // assignment operator at some places but we never use the
     // equality operator.
--- a/js/public/StructuredClone.h
+++ b/js/public/StructuredClone.h
@@ -434,17 +434,17 @@ class MOZ_NON_MEMMOVABLE JS_PUBLIC_API J
 
   void setCallbacks(const JSStructuredCloneCallbacks* callbacks, void* closure,
                     OwnTransferablePolicy policy) {
     callbacks_ = callbacks;
     closure_ = closure;
     ownTransferables_ = policy;
   }
 
-  bool Init(size_t initialCapacity = 0) {
+  MOZ_MUST_USE bool Init(size_t initialCapacity = 0) {
     return bufList_.Init(0, initialCapacity);
   }
 
   JS::StructuredCloneScope scope() const { return scope_; }
 
   void initScope(JS::StructuredCloneScope scope) {
     MOZ_ASSERT(Size() == 0, "initScope() of nonempty JSStructuredCloneData");
     if (scope_ != JS::StructuredCloneScope::Unassigned) {
@@ -453,33 +453,34 @@ class MOZ_NON_MEMMOVABLE JS_PUBLIC_API J
     }
     scope_ = scope;
   }
 
   size_t Size() const { return bufList_.Size(); }
 
   const Iterator Start() const { return bufList_.Iter(); }
 
-  bool Advance(Iterator& iter, size_t distance) const {
+  MOZ_MUST_USE bool Advance(Iterator& iter, size_t distance) const {
     return iter.AdvanceAcrossSegments(bufList_, distance);
   }
 
-  bool ReadBytes(Iterator& iter, char* buffer, size_t size) const {
+  MOZ_MUST_USE bool ReadBytes(Iterator& iter, char* buffer, size_t size) const {
     return bufList_.ReadBytes(iter, buffer, size);
   }
 
   // Append new data to the end of the buffer.
-  bool AppendBytes(const char* data, size_t size) {
+  MOZ_MUST_USE bool AppendBytes(const char* data, size_t size) {
     MOZ_ASSERT(scope_ != JS::StructuredCloneScope::Unassigned);
     return bufList_.WriteBytes(data, size);
   }
 
   // Update data stored within the existing buffer. There must be at least
   // 'size' bytes between the position of 'iter' and the end of the buffer.
-  bool UpdateBytes(Iterator& iter, const char* data, size_t size) const {
+  MOZ_MUST_USE bool UpdateBytes(Iterator& iter, const char* data,
+                                size_t size) const {
     MOZ_ASSERT(scope_ != JS::StructuredCloneScope::Unassigned);
     while (size > 0) {
       size_t remaining = iter.RemainingInSegment();
       size_t nbytes = std::min(remaining, size);
       memcpy(iter.Data(), data, nbytes);
       data += nbytes;
       size -= nbytes;
       iter.Advance(bufList_, nbytes);
@@ -519,17 +520,17 @@ class MOZ_NON_MEMMOVABLE JS_PUBLIC_API J
         return false;
       }
       iter.Advance(bufList_, iter.RemainingInSegment());
     }
     return true;
   }
 
   // Append the entire contents of other's bufList_ to our own.
-  bool Append(const JSStructuredCloneData& other) {
+  MOZ_MUST_USE bool Append(const JSStructuredCloneData& other) {
     MOZ_ASSERT(scope_ == other.scope());
     return other.ForEachDataChunk(
         [&](const char* data, size_t size) { return AppendBytes(data, size); });
   }
 
   size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) {
     return bufList_.SizeOfExcludingThis(mallocSizeOf);
   }
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -2939,17 +2939,20 @@ class CloneBufferObject : public NativeO
 
     size_t size = data->Size();
     UniqueChars buffer(js_pod_malloc<char>(size));
     if (!buffer) {
       ReportOutOfMemory(cx);
       return false;
     }
     auto iter = data->Start();
-    data->ReadBytes(iter, buffer.get(), size);
+    if (!data->ReadBytes(iter, buffer.get(), size)) {
+      ReportOutOfMemory(cx);
+      return false;
+    }
     JSString* str = JS_NewStringCopyN(cx, buffer.get(), size);
     if (!str) {
       return false;
     }
     args.rval().setString(str);
     return true;
   }
 
@@ -2971,17 +2974,20 @@ class CloneBufferObject : public NativeO
 
     size_t size = data->Size();
     UniqueChars buffer(js_pod_malloc<char>(size));
     if (!buffer) {
       ReportOutOfMemory(cx);
       return false;
     }
     auto iter = data->Start();
-    data->ReadBytes(iter, buffer.get(), size);
+    if (!data->ReadBytes(iter, buffer.get(), size)) {
+      ReportOutOfMemory(cx);
+      return false;
+    }
 
     auto* rawBuffer = buffer.release();
     JSObject* arrayBuffer = JS::NewArrayBufferWithContents(cx, size, rawBuffer);
     if (!arrayBuffer) {
       js_free(rawBuffer);
       return false;
     }
 
--- a/js/src/fuzz-tests/testStructuredCloneReader.cpp
+++ b/js/src/fuzz-tests/testStructuredCloneReader.cpp
@@ -39,19 +39,25 @@ static int testStructuredCloneReaderFuzz
 
   auto clonebuf = MakeUnique<JSStructuredCloneData>(scope);
   if (!clonebuf || !clonebuf->Init(buf_size)) {
     ReportOutOfMemory(gCx);
     return 0;
   }
 
   // Copy buffer then pad with zeroes.
-  clonebuf->AppendBytes((const char*)buf, size);
+  if (!clonebuf->AppendBytes((const char*)buf, size)) {
+    ReportOutOfMemory(gCx);
+    return 0;
+  }
   char padding[kSegmentAlignment] = {0};
-  clonebuf->AppendBytes(padding, buf_size - size);
+  if (!clonebuf->AppendBytes(padding, buf_size - size)) {
+    ReportOutOfMemory(gCx);
+    return 0;
+  }
 
   RootedValue deserialized(gCx);
   if (!JS_ReadStructuredClone(gCx, *clonebuf, JS_STRUCTURED_CLONE_VERSION,
                               scope, &deserialized, nullptr, nullptr)) {
     return 0;
   }
 
   /* If we succeeded in deserializing, we should try to reserialize the data.