Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

Unified Diff: third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp

Issue 1414553002: Fix out-of-memory crashes related to ArrayBuffer allocation Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase+more tweaks Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
index 3bd0390146d9043f971387b6fb751005509455e8..79285e41f117480eff066a2c886f08be46c2b08e 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
@@ -251,8 +251,12 @@ void SerializedScriptValueWriter::writeArrayBufferView(const DOMArrayBufferView&
{
append(ArrayBufferViewTag);
#if ENABLE(ASSERT)
- ASSERT(static_cast<const uint8_t*>(arrayBufferView.bufferBase()->data()) + arrayBufferView.byteOffset() ==
- static_cast<const uint8_t*>(arrayBufferView.baseAddress()));
+ {
+ ReftPtr<DOMArrayBuffer> buffer = arrayBufferView.bufferBaseOrNull();
+ ASSERT(buffer);
+ ASSERT(static_cast<const uint8_t*>(buffer->data()) + arrayBufferView.byteOffset() ==
+ static_cast<const uint8_t*>(arrayBufferView.baseAddress()));
+ }
#endif
DOMArrayBufferView::ViewType type = arrayBufferView.type();
@@ -976,7 +980,7 @@ ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyArrayBuffer
ASSERT(!object.IsEmpty());
DOMArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object);
if (!arrayBufferView)
- return 0;
+ return nullptr;
if (!arrayBufferView->bufferBase())
return handleError(DataCloneError, "An ArrayBuffer could not be cloned.", next);
v8::Local<v8::Value> underlyingBuffer = toV8(arrayBufferView->bufferBase(), m_scriptState->context()->Global(), isolate());
@@ -1532,7 +1536,22 @@ bool SerializedScriptValueReader::readImageData(v8::Local<v8::Value>* value)
return false;
if (m_position + pixelDataLength > m_length)
return false;
- ImageData* imageData = ImageData::create(IntSize(width, height));
+ // TODO(junov): crbug.com/536816
+ // Here we use a NonThorwableExceptionState in order to fail silently
+ // when ImageData allocation fails. It needs to be ascertained whether
+ // the call sites that depend on value deserialization agree with
+ // re-throwing a RangeError exception from here, which is what happens
+ // when the ArrayBuffer encapsulated in the ImageData fails to be
+ // allocated, as per the ECMAScript spec:
+ // http://ecma-international.org/ecma-262/6.0/#sec-createbytedatablock
+ // Before we decide to propagate the exception down to the script
+ // execution context, all the APIs that depend on this routine would
+ // need to have specifications stating that exceptions thrown by sub
+ // routines involved in the deserialization process are re-thrown.
+ NonThrowableExceptionState exceptionState;
+ ImageData* imageData = ImageData::create(IntSize(width, height), exceptionState);
+ if (exceptionState.hadException())
+ return false;
DOMUint8ClampedArray* pixelArray = imageData->data();
ASSERT(pixelArray);
ASSERT(pixelArray->length() >= pixelDataLength);
@@ -1565,14 +1584,16 @@ PassRefPtr<DOMArrayBuffer> SerializedScriptValueReader::doReadArrayBuffer()
return nullptr;
const void* bufferStart = m_buffer + m_position;
m_position += byteLength;
- return DOMArrayBuffer::create(bufferStart, byteLength);
+ // TODO(junov): crbug.com/536816
+ // Should use createOrNull to avoid crashing.
+ // To do that, we need to make sure that call sites of readArrayBuffer
+ // would react correctly in this case, with 'value' not having been set.
+ return DOMArrayBuffer::deprecatedCreateOrCrash(bufferStart, byteLength);
}
bool SerializedScriptValueReader::readArrayBuffer(v8::Local<v8::Value>* value)
{
RefPtr<DOMArrayBuffer> arrayBuffer = doReadArrayBuffer();
- if (!arrayBuffer)
- return false;
*value = toV8(arrayBuffer.release(), m_scriptState->context()->Global(), isolate());
return !value->IsEmpty();
}

Powered by Google App Engine
This is Rietveld 408576698