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

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: Reverting some behavior changes 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 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 void SerializedScriptValueWriter::writeArrayBuffer(const DOMArrayBuffer& arrayBu ffer) 245 void SerializedScriptValueWriter::writeArrayBuffer(const DOMArrayBuffer& arrayBu ffer)
246 { 246 {
247 append(ArrayBufferTag); 247 append(ArrayBufferTag);
248 doWriteArrayBuffer(arrayBuffer); 248 doWriteArrayBuffer(arrayBuffer);
249 } 249 }
250 250
251 void SerializedScriptValueWriter::writeArrayBufferView(const DOMArrayBufferView& arrayBufferView) 251 void SerializedScriptValueWriter::writeArrayBufferView(const DOMArrayBufferView& arrayBufferView)
252 { 252 {
253 append(ArrayBufferViewTag); 253 append(ArrayBufferViewTag);
254 #if ENABLE(ASSERT) 254 #if ENABLE(ASSERT)
255 ASSERT(static_cast<const uint8_t*>(arrayBufferView.bufferBase()->data()) + a rrayBufferView.byteOffset() == 255 ASSERT(static_cast<const uint8_t*>(arrayBufferView.bufferBaseOrNull()->data( )) + arrayBufferView.byteOffset() ==
256 static_cast<const uint8_t*>(arrayBufferView.baseAddress())); 256 static_cast<const uint8_t*>(arrayBufferView.baseAddress()));
257 #endif 257 #endif
258 DOMArrayBufferView::ViewType type = arrayBufferView.type(); 258 DOMArrayBufferView::ViewType type = arrayBufferView.type();
259 259
260 switch (type) { 260 switch (type) {
261 case DOMArrayBufferView::TypeInt8: 261 case DOMArrayBufferView::TypeInt8:
262 append(ByteArrayTag); 262 append(ByteArrayTag);
263 break; 263 break;
264 case DOMArrayBufferView::TypeUint8Clamped: 264 case DOMArrayBufferView::TypeUint8Clamped:
265 append(UnsignedByteClampedArrayTag); 265 append(UnsignedByteClampedArrayTag);
(...skipping 730 matching lines...) Expand 10 before | Expand all | Expand 10 after
996 { 996 {
997 v8::Local<v8::RegExp> regExp = value.As<v8::RegExp>(); 997 v8::Local<v8::RegExp> regExp = value.As<v8::RegExp>();
998 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags()); 998 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags());
999 } 999 }
1000 1000
1001 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyArrayBuffer View(v8::Local<v8::Object> object, ScriptValueSerializer::StateBase* next) 1001 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyArrayBuffer View(v8::Local<v8::Object> object, ScriptValueSerializer::StateBase* next)
1002 { 1002 {
1003 ASSERT(!object.IsEmpty()); 1003 ASSERT(!object.IsEmpty());
1004 DOMArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object); 1004 DOMArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object);
1005 if (!arrayBufferView) 1005 if (!arrayBufferView)
1006 return 0; 1006 return nullptr;
1007 if (!arrayBufferView->bufferBase()) 1007 if (!arrayBufferView->bufferBaseOrNull())
1008 return handleError(DataCloneError, "An ArrayBuffer could not be cloned." , next); 1008 return handleError(DataCloneError, "An ArrayBuffer could not be cloned." , next);
1009 v8::Local<v8::Value> underlyingBuffer = toV8(arrayBufferView->bufferBase(), m_scriptState->context()->Global(), isolate()); 1009 v8::Local<v8::Value> underlyingBuffer = toV8(arrayBufferView->bufferBaseOrNu ll(), m_scriptState->context()->Global(), isolate());
1010 if (underlyingBuffer.IsEmpty()) 1010 if (underlyingBuffer.IsEmpty())
1011 return handleError(DataCloneError, "An ArrayBuffer could not be cloned." , next); 1011 return handleError(DataCloneError, "An ArrayBuffer could not be cloned." , next);
1012 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next); 1012 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next);
1013 if (stateOut) 1013 if (stateOut)
1014 return stateOut; 1014 return stateOut;
1015 m_writer.writeArrayBufferView(*arrayBufferView); 1015 m_writer.writeArrayBufferView(*arrayBufferView);
1016 // This should be safe: we serialize something that we know to be a wrapper (see 1016 // This should be safe: we serialize something that we know to be a wrapper (see
1017 // the toV8 call above), so the call to doSerializeArrayBuffer should neithe r 1017 // the toV8 call above), so the call to doSerializeArrayBuffer should neithe r
1018 // cause the system stack to overflow nor should it have potential to reach 1018 // cause the system stack to overflow nor should it have potential to reach
1019 // this ArrayBufferView again. 1019 // this ArrayBufferView again.
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after
1573 uint32_t height; 1573 uint32_t height;
1574 uint32_t pixelDataLength; 1574 uint32_t pixelDataLength;
1575 if (!doReadUint32(&width)) 1575 if (!doReadUint32(&width))
1576 return false; 1576 return false;
1577 if (!doReadUint32(&height)) 1577 if (!doReadUint32(&height))
1578 return false; 1578 return false;
1579 if (!doReadUint32(&pixelDataLength)) 1579 if (!doReadUint32(&pixelDataLength))
1580 return false; 1580 return false;
1581 if (m_position + pixelDataLength > m_length) 1581 if (m_position + pixelDataLength > m_length)
1582 return false; 1582 return false;
1583 ImageData* imageData = ImageData::create(IntSize(width, height)); 1583 NonThrowableExceptionState exceptionState;
haraken 2015/10/29 16:24:34 Why can't we use a normal ExecptionState?
Justin Novosad 2015/10/29 18:26:02 Added an explanatory comment.
1584 ImageData* imageData = ImageData::create(IntSize(width, height), exceptionSt ate);
1585 if (exceptionState.hadException())
1586 return false;
1584 DOMUint8ClampedArray* pixelArray = imageData->data(); 1587 DOMUint8ClampedArray* pixelArray = imageData->data();
1585 ASSERT(pixelArray); 1588 ASSERT(pixelArray);
1586 ASSERT(pixelArray->length() >= pixelDataLength); 1589 ASSERT(pixelArray->length() >= pixelDataLength);
1587 memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength); 1590 memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength);
1588 m_position += pixelDataLength; 1591 m_position += pixelDataLength;
1589 *value = toV8(imageData, m_scriptState->context()->Global(), isolate()); 1592 *value = toV8(imageData, m_scriptState->context()->Global(), isolate());
1590 return !value->IsEmpty(); 1593 return !value->IsEmpty();
1591 } 1594 }
1592 1595
1593 bool SerializedScriptValueReader::readCompositorProxy(v8::Local<v8::Value>* valu e) 1596 bool SerializedScriptValueReader::readCompositorProxy(v8::Local<v8::Value>* valu e)
1594 { 1597 {
1595 uint32_t attributes; 1598 uint32_t attributes;
1596 uint64_t element; 1599 uint64_t element;
1597 if (!doReadUint64(&element)) 1600 if (!doReadUint64(&element))
1598 return false; 1601 return false;
1599 if (!doReadUint32(&attributes)) 1602 if (!doReadUint32(&attributes))
1600 return false; 1603 return false;
1601 1604
1602 CompositorProxy* compositorProxy = CompositorProxy::create(element, attribut es); 1605 CompositorProxy* compositorProxy = CompositorProxy::create(element, attribut es);
1603 *value = toV8(compositorProxy, m_scriptState->context()->Global(), isolate() ); 1606 *value = toV8(compositorProxy, m_scriptState->context()->Global(), isolate() );
1604 return !value->IsEmpty(); 1607 return !value->IsEmpty();
1605 } 1608 }
1606 1609
1607 PassRefPtr<DOMArrayBuffer> SerializedScriptValueReader::doReadArrayBuffer() 1610 PassRefPtr<DOMArrayBuffer> SerializedScriptValueReader::doReadArrayBufferOrNull( )
1608 { 1611 {
1609 uint32_t byteLength; 1612 uint32_t byteLength;
1610 if (!doReadUint32(&byteLength)) 1613 if (!doReadUint32(&byteLength))
1611 return nullptr; 1614 return nullptr;
1612 if (m_position + byteLength > m_length) 1615 if (m_position + byteLength > m_length)
1613 return nullptr; 1616 return nullptr;
1614 const void* bufferStart = m_buffer + m_position; 1617 const void* bufferStart = m_buffer + m_position;
1615 m_position += byteLength; 1618 m_position += byteLength;
1616 return DOMArrayBuffer::create(bufferStart, byteLength); 1619 return DOMArrayBuffer::createOrNull(bufferStart, byteLength);
1617 } 1620 }
1618 1621
1619 bool SerializedScriptValueReader::readArrayBuffer(v8::Local<v8::Value>* value) 1622 bool SerializedScriptValueReader::readArrayBuffer(v8::Local<v8::Value>* value)
1620 { 1623 {
1621 RefPtr<DOMArrayBuffer> arrayBuffer = doReadArrayBuffer(); 1624 RefPtr<DOMArrayBuffer> arrayBuffer = doReadArrayBufferOrNull();
1622 if (!arrayBuffer) 1625 // FIXME(crbug.com/536816): Instead of the following assert, we should consi der doing:
haraken 2015/10/29 16:24:34 FIXME => TODO(junov)
1623 return false; 1626 // if (!arrayBuffer)
1627 // return false;
1628 // To do that, we need to make sure that call sites would react correctly
1629 // in this case, with the value not having been set.
1630 RELEASE_ASSERT(arrayBuffer); // This is essentially an out of memory crash
1624 *value = toV8(arrayBuffer.release(), m_scriptState->context()->Global(), iso late()); 1631 *value = toV8(arrayBuffer.release(), m_scriptState->context()->Global(), iso late());
1625 return !value->IsEmpty(); 1632 return !value->IsEmpty();
1626 } 1633 }
1627 1634
1628 bool SerializedScriptValueReader::readArrayBufferView(v8::Local<v8::Value>* valu e, ScriptValueCompositeCreator& creator) 1635 bool SerializedScriptValueReader::readArrayBufferView(v8::Local<v8::Value>* valu e, ScriptValueCompositeCreator& creator)
1629 { 1636 {
1630 ArrayBufferViewSubTag subTag; 1637 ArrayBufferViewSubTag subTag;
1631 uint32_t byteOffset; 1638 uint32_t byteOffset;
1632 uint32_t byteLength; 1639 uint32_t byteLength;
1633 RefPtr<DOMArrayBufferBase> arrayBuffer; 1640 RefPtr<DOMArrayBufferBase> arrayBuffer;
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after
2216 return false; 2223 return false;
2217 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeRefe renceStack.size() - 1]; 2224 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeRefe renceStack.size() - 1];
2218 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() - 1); 2225 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() - 1);
2219 if (objectReference >= m_objectPool.size()) 2226 if (objectReference >= m_objectPool.size())
2220 return false; 2227 return false;
2221 *object = m_objectPool[objectReference]; 2228 *object = m_objectPool[objectReference];
2222 return true; 2229 return true;
2223 } 2230 }
2224 2231
2225 } // namespace blink 2232 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698