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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "config.h" 5 #include "config.h"
6 #include "bindings/core/v8/ScriptValueSerializer.h" 6 #include "bindings/core/v8/ScriptValueSerializer.h"
7 7
8 #include "bindings/core/v8/V8ArrayBuffer.h" 8 #include "bindings/core/v8/V8ArrayBuffer.h"
9 #include "bindings/core/v8/V8ArrayBufferView.h" 9 #include "bindings/core/v8/V8ArrayBufferView.h"
10 #include "bindings/core/v8/V8Blob.h" 10 #include "bindings/core/v8/V8Blob.h"
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 void SerializedScriptValueWriter::writeArrayBuffer(const DOMArrayBuffer& arrayBu ffer) 244 void SerializedScriptValueWriter::writeArrayBuffer(const DOMArrayBuffer& arrayBu ffer)
245 { 245 {
246 append(ArrayBufferTag); 246 append(ArrayBufferTag);
247 doWriteArrayBuffer(arrayBuffer); 247 doWriteArrayBuffer(arrayBuffer);
248 } 248 }
249 249
250 void SerializedScriptValueWriter::writeArrayBufferView(const DOMArrayBufferView& arrayBufferView) 250 void SerializedScriptValueWriter::writeArrayBufferView(const DOMArrayBufferView& arrayBufferView)
251 { 251 {
252 append(ArrayBufferViewTag); 252 append(ArrayBufferViewTag);
253 #if ENABLE(ASSERT) 253 #if ENABLE(ASSERT)
254 ASSERT(static_cast<const uint8_t*>(arrayBufferView.bufferBase()->data()) + a rrayBufferView.byteOffset() == 254 {
255 static_cast<const uint8_t*>(arrayBufferView.baseAddress())); 255 ReftPtr<DOMArrayBuffer> buffer = arrayBufferView.bufferBaseOrNull();
256 ASSERT(buffer);
257 ASSERT(static_cast<const uint8_t*>(buffer->data()) + arrayBufferView.byt eOffset() ==
258 static_cast<const uint8_t*>(arrayBufferView.baseAddress()));
259 }
256 #endif 260 #endif
257 DOMArrayBufferView::ViewType type = arrayBufferView.type(); 261 DOMArrayBufferView::ViewType type = arrayBufferView.type();
258 262
259 switch (type) { 263 switch (type) {
260 case DOMArrayBufferView::TypeInt8: 264 case DOMArrayBufferView::TypeInt8:
261 append(ByteArrayTag); 265 append(ByteArrayTag);
262 break; 266 break;
263 case DOMArrayBufferView::TypeUint8Clamped: 267 case DOMArrayBufferView::TypeUint8Clamped:
264 append(UnsignedByteClampedArrayTag); 268 append(UnsignedByteClampedArrayTag);
265 break; 269 break;
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after
969 { 973 {
970 v8::Local<v8::RegExp> regExp = value.As<v8::RegExp>(); 974 v8::Local<v8::RegExp> regExp = value.As<v8::RegExp>();
971 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags()); 975 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags());
972 } 976 }
973 977
974 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyArrayBuffer View(v8::Local<v8::Object> object, ScriptValueSerializer::StateBase* next) 978 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyArrayBuffer View(v8::Local<v8::Object> object, ScriptValueSerializer::StateBase* next)
975 { 979 {
976 ASSERT(!object.IsEmpty()); 980 ASSERT(!object.IsEmpty());
977 DOMArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object); 981 DOMArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object);
978 if (!arrayBufferView) 982 if (!arrayBufferView)
979 return 0; 983 return nullptr;
980 if (!arrayBufferView->bufferBase()) 984 if (!arrayBufferView->bufferBase())
981 return handleError(DataCloneError, "An ArrayBuffer could not be cloned." , next); 985 return handleError(DataCloneError, "An ArrayBuffer could not be cloned." , next);
982 v8::Local<v8::Value> underlyingBuffer = toV8(arrayBufferView->bufferBase(), m_scriptState->context()->Global(), isolate()); 986 v8::Local<v8::Value> underlyingBuffer = toV8(arrayBufferView->bufferBase(), m_scriptState->context()->Global(), isolate());
983 if (underlyingBuffer.IsEmpty()) 987 if (underlyingBuffer.IsEmpty())
984 return handleError(DataCloneError, "An ArrayBuffer could not be cloned." , next); 988 return handleError(DataCloneError, "An ArrayBuffer could not be cloned." , next);
985 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next); 989 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next);
986 if (stateOut) 990 if (stateOut)
987 return stateOut; 991 return stateOut;
988 m_writer.writeArrayBufferView(*arrayBufferView); 992 m_writer.writeArrayBufferView(*arrayBufferView);
989 // This should be safe: we serialize something that we know to be a wrapper (see 993 // This should be safe: we serialize something that we know to be a wrapper (see
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after
1525 uint32_t height; 1529 uint32_t height;
1526 uint32_t pixelDataLength; 1530 uint32_t pixelDataLength;
1527 if (!doReadUint32(&width)) 1531 if (!doReadUint32(&width))
1528 return false; 1532 return false;
1529 if (!doReadUint32(&height)) 1533 if (!doReadUint32(&height))
1530 return false; 1534 return false;
1531 if (!doReadUint32(&pixelDataLength)) 1535 if (!doReadUint32(&pixelDataLength))
1532 return false; 1536 return false;
1533 if (m_position + pixelDataLength > m_length) 1537 if (m_position + pixelDataLength > m_length)
1534 return false; 1538 return false;
1535 ImageData* imageData = ImageData::create(IntSize(width, height)); 1539 // TODO(junov): crbug.com/536816
1540 // Here we use a NonThorwableExceptionState in order to fail silently
1541 // when ImageData allocation fails. It needs to be ascertained whether
1542 // the call sites that depend on value deserialization agree with
1543 // re-throwing a RangeError exception from here, which is what happens
1544 // when the ArrayBuffer encapsulated in the ImageData fails to be
1545 // allocated, as per the ECMAScript spec:
1546 // http://ecma-international.org/ecma-262/6.0/#sec-createbytedatablock
1547 // Before we decide to propagate the exception down to the script
1548 // execution context, all the APIs that depend on this routine would
1549 // need to have specifications stating that exceptions thrown by sub
1550 // routines involved in the deserialization process are re-thrown.
1551 NonThrowableExceptionState exceptionState;
1552 ImageData* imageData = ImageData::create(IntSize(width, height), exceptionSt ate);
1553 if (exceptionState.hadException())
1554 return false;
1536 DOMUint8ClampedArray* pixelArray = imageData->data(); 1555 DOMUint8ClampedArray* pixelArray = imageData->data();
1537 ASSERT(pixelArray); 1556 ASSERT(pixelArray);
1538 ASSERT(pixelArray->length() >= pixelDataLength); 1557 ASSERT(pixelArray->length() >= pixelDataLength);
1539 memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength); 1558 memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength);
1540 m_position += pixelDataLength; 1559 m_position += pixelDataLength;
1541 *value = toV8(imageData, m_scriptState->context()->Global(), isolate()); 1560 *value = toV8(imageData, m_scriptState->context()->Global(), isolate());
1542 return !value->IsEmpty(); 1561 return !value->IsEmpty();
1543 } 1562 }
1544 1563
1545 bool SerializedScriptValueReader::readCompositorProxy(v8::Local<v8::Value>* valu e) 1564 bool SerializedScriptValueReader::readCompositorProxy(v8::Local<v8::Value>* valu e)
(...skipping 12 matching lines...) Expand all
1558 1577
1559 PassRefPtr<DOMArrayBuffer> SerializedScriptValueReader::doReadArrayBuffer() 1578 PassRefPtr<DOMArrayBuffer> SerializedScriptValueReader::doReadArrayBuffer()
1560 { 1579 {
1561 uint32_t byteLength; 1580 uint32_t byteLength;
1562 if (!doReadUint32(&byteLength)) 1581 if (!doReadUint32(&byteLength))
1563 return nullptr; 1582 return nullptr;
1564 if (m_position + byteLength > m_length) 1583 if (m_position + byteLength > m_length)
1565 return nullptr; 1584 return nullptr;
1566 const void* bufferStart = m_buffer + m_position; 1585 const void* bufferStart = m_buffer + m_position;
1567 m_position += byteLength; 1586 m_position += byteLength;
1568 return DOMArrayBuffer::create(bufferStart, byteLength); 1587 // TODO(junov): crbug.com/536816
1588 // Should use createOrNull to avoid crashing.
1589 // To do that, we need to make sure that call sites of readArrayBuffer
1590 // would react correctly in this case, with 'value' not having been set.
1591 return DOMArrayBuffer::deprecatedCreateOrCrash(bufferStart, byteLength);
1569 } 1592 }
1570 1593
1571 bool SerializedScriptValueReader::readArrayBuffer(v8::Local<v8::Value>* value) 1594 bool SerializedScriptValueReader::readArrayBuffer(v8::Local<v8::Value>* value)
1572 { 1595 {
1573 RefPtr<DOMArrayBuffer> arrayBuffer = doReadArrayBuffer(); 1596 RefPtr<DOMArrayBuffer> arrayBuffer = doReadArrayBuffer();
1574 if (!arrayBuffer)
1575 return false;
1576 *value = toV8(arrayBuffer.release(), m_scriptState->context()->Global(), iso late()); 1597 *value = toV8(arrayBuffer.release(), m_scriptState->context()->Global(), iso late());
1577 return !value->IsEmpty(); 1598 return !value->IsEmpty();
1578 } 1599 }
1579 1600
1580 bool SerializedScriptValueReader::readArrayBufferView(v8::Local<v8::Value>* valu e, ScriptValueCompositeCreator& creator) 1601 bool SerializedScriptValueReader::readArrayBufferView(v8::Local<v8::Value>* valu e, ScriptValueCompositeCreator& creator)
1581 { 1602 {
1582 ArrayBufferViewSubTag subTag; 1603 ArrayBufferViewSubTag subTag;
1583 uint32_t byteOffset; 1604 uint32_t byteOffset;
1584 uint32_t byteLength; 1605 uint32_t byteLength;
1585 RefPtr<DOMArrayBufferBase> arrayBuffer; 1606 RefPtr<DOMArrayBufferBase> arrayBuffer;
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after
2157 return false; 2178 return false;
2158 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeRefe renceStack.size() - 1]; 2179 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeRefe renceStack.size() - 1];
2159 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() - 1); 2180 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() - 1);
2160 if (objectReference >= m_objectPool.size()) 2181 if (objectReference >= m_objectPool.size())
2161 return false; 2182 return false;
2162 *object = m_objectPool[objectReference]; 2183 *object = m_objectPool[objectReference];
2163 return true; 2184 return true;
2164 } 2185 }
2165 2186
2166 } // namespace blink 2187 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698