diff --git a/dom/base/nsStructuredCloneContainer.cpp b/dom/base/nsStructuredCloneContainer.cpp index 27111666c41f..970b1ce695a1 100644 --- a/dom/base/nsStructuredCloneContainer.cpp +++ b/dom/base/nsStructuredCloneContainer.cpp @@ -130,7 +130,9 @@ nsStructuredCloneContainer::GetDataAsBase64(nsAString& aOut) { 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))) { diff --git a/dom/ipc/StructuredCloneData.h b/dom/ipc/StructuredCloneData.h index c140d3076293..bac00e9aa473 100644 --- a/dom/ipc/StructuredCloneData.h +++ b/dom/ipc/StructuredCloneData.h @@ -52,7 +52,7 @@ class SharedJSAllocatedData final { static already_AddRefed 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 sharedData = new SharedJSAllocatedData(std::move(buf)); return sharedData.forget(); @@ -61,7 +61,7 @@ class SharedJSAllocatedData final { static already_AddRefed CreateFromExternalData( const JSStructuredCloneData& aData) { JSStructuredCloneData buf(aData.scope()); - buf.Append(aData); + NS_ENSURE_TRUE(buf.Append(aData), nullptr); RefPtr sharedData = new SharedJSAllocatedData(std::move(buf)); return sharedData.forget(); diff --git a/ipc/glue/IPCMessageUtils.h b/ipc/glue/IPCMessageUtils.h index 9d0768381310..aeff61c75844 100644 --- a/ipc/glue/IPCMessageUtils.h +++ b/ipc/glue/IPCMessageUtils.h @@ -84,7 +84,7 @@ struct SerializedStructuredCloneBuffer final { 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; } diff --git a/js/public/StructuredClone.h b/js/public/StructuredClone.h index f6dbc2c501ac..847afe001076 100644 --- a/js/public/StructuredClone.h +++ b/js/public/StructuredClone.h @@ -439,7 +439,7 @@ class MOZ_NON_MEMMOVABLE JS_PUBLIC_API JSStructuredCloneData { ownTransferables_ = policy; } - bool Init(size_t initialCapacity = 0) { + MOZ_MUST_USE bool Init(size_t initialCapacity = 0) { return bufList_.Init(0, initialCapacity); } @@ -458,23 +458,24 @@ class MOZ_NON_MEMMOVABLE JS_PUBLIC_API JSStructuredCloneData { 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(); @@ -524,7 +525,7 @@ class MOZ_NON_MEMMOVABLE JS_PUBLIC_API JSStructuredCloneData { } // 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); }); diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index c1ec55c282fb..d9a6344ce429 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -2944,7 +2944,10 @@ class CloneBufferObject : public NativeObject { 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; @@ -2976,7 +2979,10 @@ class CloneBufferObject : public NativeObject { 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); diff --git a/js/src/fuzz-tests/testStructuredCloneReader.cpp b/js/src/fuzz-tests/testStructuredCloneReader.cpp index 0f8e92f15b8a..2bb5d9e4285b 100644 --- a/js/src/fuzz-tests/testStructuredCloneReader.cpp +++ b/js/src/fuzz-tests/testStructuredCloneReader.cpp @@ -44,9 +44,15 @@ static int testStructuredCloneReaderFuzz(const uint8_t* buf, size_t size) { } // 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,