Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 ASSERT(static_cast<const uint8_t*>(arrayBufferView.bufferBaseOrNull()->data( )) + arrayBufferView.byteOffset() == |
|
haraken
2015/10/29 18:58:37
arrayBufferView.bufferBaseOrNull() can return null
Justin Novosad
2015/11/05 00:17:51
Done.
| |
| 255 static_cast<const uint8_t*>(arrayBufferView.baseAddress())); | 255 static_cast<const uint8_t*>(arrayBufferView.baseAddress())); |
| 256 #endif | 256 #endif |
| 257 DOMArrayBufferView::ViewType type = arrayBufferView.type(); | 257 DOMArrayBufferView::ViewType type = arrayBufferView.type(); |
| 258 | 258 |
| 259 switch (type) { | 259 switch (type) { |
| 260 case DOMArrayBufferView::TypeInt8: | 260 case DOMArrayBufferView::TypeInt8: |
| 261 append(ByteArrayTag); | 261 append(ByteArrayTag); |
| 262 break; | 262 break; |
| 263 case DOMArrayBufferView::TypeUint8Clamped: | 263 case DOMArrayBufferView::TypeUint8Clamped: |
| 264 append(UnsignedByteClampedArrayTag); | 264 append(UnsignedByteClampedArrayTag); |
| (...skipping 704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 969 { | 969 { |
| 970 v8::Local<v8::RegExp> regExp = value.As<v8::RegExp>(); | 970 v8::Local<v8::RegExp> regExp = value.As<v8::RegExp>(); |
| 971 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags()); | 971 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags()); |
| 972 } | 972 } |
| 973 | 973 |
| 974 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyArrayBuffer View(v8::Local<v8::Object> object, ScriptValueSerializer::StateBase* next) | 974 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyArrayBuffer View(v8::Local<v8::Object> object, ScriptValueSerializer::StateBase* next) |
| 975 { | 975 { |
| 976 ASSERT(!object.IsEmpty()); | 976 ASSERT(!object.IsEmpty()); |
| 977 DOMArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object); | 977 DOMArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object); |
| 978 if (!arrayBufferView) | 978 if (!arrayBufferView) |
| 979 return 0; | 979 return nullptr; |
| 980 if (!arrayBufferView->bufferBase()) | 980 if (!arrayBufferView->bufferBaseOrNull()) |
| 981 return handleError(DataCloneError, "An ArrayBuffer could not be cloned." , next); | 981 return handleError(DataCloneError, "An ArrayBuffer could not be cloned." , next); |
| 982 v8::Local<v8::Value> underlyingBuffer = toV8(arrayBufferView->bufferBase(), m_scriptState->context()->Global(), isolate()); | 982 v8::Local<v8::Value> underlyingBuffer = toV8(arrayBufferView->bufferBaseOrNu ll(), m_scriptState->context()->Global(), isolate()); |
| 983 if (underlyingBuffer.IsEmpty()) | 983 if (underlyingBuffer.IsEmpty()) |
| 984 return handleError(DataCloneError, "An ArrayBuffer could not be cloned." , next); | 984 return handleError(DataCloneError, "An ArrayBuffer could not be cloned." , next); |
| 985 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next); | 985 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next); |
| 986 if (stateOut) | 986 if (stateOut) |
| 987 return stateOut; | 987 return stateOut; |
| 988 m_writer.writeArrayBufferView(*arrayBufferView); | 988 m_writer.writeArrayBufferView(*arrayBufferView); |
| 989 // This should be safe: we serialize something that we know to be a wrapper (see | 989 // This should be safe: we serialize something that we know to be a wrapper (see |
| 990 // the toV8 call above), so the call to doSerializeArrayBuffer should neithe r | 990 // the toV8 call above), so the call to doSerializeArrayBuffer should neithe r |
| 991 // cause the system stack to overflow nor should it have potential to reach | 991 // cause the system stack to overflow nor should it have potential to reach |
| 992 // this ArrayBufferView again. | 992 // this ArrayBufferView again. |
| (...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1525 uint32_t height; | 1525 uint32_t height; |
| 1526 uint32_t pixelDataLength; | 1526 uint32_t pixelDataLength; |
| 1527 if (!doReadUint32(&width)) | 1527 if (!doReadUint32(&width)) |
| 1528 return false; | 1528 return false; |
| 1529 if (!doReadUint32(&height)) | 1529 if (!doReadUint32(&height)) |
| 1530 return false; | 1530 return false; |
| 1531 if (!doReadUint32(&pixelDataLength)) | 1531 if (!doReadUint32(&pixelDataLength)) |
| 1532 return false; | 1532 return false; |
| 1533 if (m_position + pixelDataLength > m_length) | 1533 if (m_position + pixelDataLength > m_length) |
| 1534 return false; | 1534 return false; |
| 1535 ImageData* imageData = ImageData::create(IntSize(width, height)); | 1535 // TODO(junov): crbug.com/536816 |
| 1536 // Here we use a NonThorwableExceptionState in order to fail silently | |
| 1537 // when ImageData allocation fails. It needs to be ascertained whether | |
| 1538 // the call sites that depend on value deserialization agree with | |
| 1539 // re-throwing a RangeError exception from here, which is what happens | |
| 1540 // when the ArrayBuffer encapsulated in the ImageData fails to be | |
| 1541 // allocated, as per the ECMAScript spec: | |
| 1542 // http://ecma-international.org/ecma-262/6.0/#sec-createbytedatablock | |
| 1543 // Before we decide to propagate the exception down to the script | |
| 1544 // execution context, all the APIs that depend on this routine would | |
| 1545 // need to have specifications stating that exceptions thrown by sub | |
| 1546 // routines involved in the deserialization process are re-thrown. | |
| 1547 NonThrowableExceptionState exceptionState; | |
| 1548 ImageData* imageData = ImageData::create(IntSize(width, height), exceptionSt ate); | |
| 1549 if (exceptionState.hadException()) | |
| 1550 return false; | |
| 1536 DOMUint8ClampedArray* pixelArray = imageData->data(); | 1551 DOMUint8ClampedArray* pixelArray = imageData->data(); |
| 1537 ASSERT(pixelArray); | 1552 ASSERT(pixelArray); |
| 1538 ASSERT(pixelArray->length() >= pixelDataLength); | 1553 ASSERT(pixelArray->length() >= pixelDataLength); |
| 1539 memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength); | 1554 memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength); |
| 1540 m_position += pixelDataLength; | 1555 m_position += pixelDataLength; |
| 1541 *value = toV8(imageData, m_scriptState->context()->Global(), isolate()); | 1556 *value = toV8(imageData, m_scriptState->context()->Global(), isolate()); |
| 1542 return !value->IsEmpty(); | 1557 return !value->IsEmpty(); |
| 1543 } | 1558 } |
| 1544 | 1559 |
| 1545 bool SerializedScriptValueReader::readCompositorProxy(v8::Local<v8::Value>* valu e) | 1560 bool SerializedScriptValueReader::readCompositorProxy(v8::Local<v8::Value>* valu e) |
| 1546 { | 1561 { |
| 1547 uint32_t attributes; | 1562 uint32_t attributes; |
| 1548 uint64_t element; | 1563 uint64_t element; |
| 1549 if (!doReadUint64(&element)) | 1564 if (!doReadUint64(&element)) |
| 1550 return false; | 1565 return false; |
| 1551 if (!doReadUint32(&attributes)) | 1566 if (!doReadUint32(&attributes)) |
| 1552 return false; | 1567 return false; |
| 1553 | 1568 |
| 1554 CompositorProxy* compositorProxy = CompositorProxy::create(element, attribut es); | 1569 CompositorProxy* compositorProxy = CompositorProxy::create(element, attribut es); |
| 1555 *value = toV8(compositorProxy, m_scriptState->context()->Global(), isolate() ); | 1570 *value = toV8(compositorProxy, m_scriptState->context()->Global(), isolate() ); |
| 1556 return !value->IsEmpty(); | 1571 return !value->IsEmpty(); |
| 1557 } | 1572 } |
| 1558 | 1573 |
| 1559 PassRefPtr<DOMArrayBuffer> SerializedScriptValueReader::doReadArrayBuffer() | 1574 PassRefPtr<DOMArrayBuffer> SerializedScriptValueReader::doReadArrayBufferOrNull( ) |
| 1560 { | 1575 { |
| 1561 uint32_t byteLength; | 1576 uint32_t byteLength; |
| 1562 if (!doReadUint32(&byteLength)) | 1577 if (!doReadUint32(&byteLength)) |
| 1563 return nullptr; | 1578 return nullptr; |
| 1564 if (m_position + byteLength > m_length) | 1579 if (m_position + byteLength > m_length) |
| 1565 return nullptr; | 1580 return nullptr; |
| 1566 const void* bufferStart = m_buffer + m_position; | 1581 const void* bufferStart = m_buffer + m_position; |
| 1567 m_position += byteLength; | 1582 m_position += byteLength; |
| 1568 return DOMArrayBuffer::create(bufferStart, byteLength); | 1583 return DOMArrayBuffer::createOrNull(bufferStart, byteLength); |
| 1569 } | 1584 } |
| 1570 | 1585 |
| 1571 bool SerializedScriptValueReader::readArrayBuffer(v8::Local<v8::Value>* value) | 1586 bool SerializedScriptValueReader::readArrayBuffer(v8::Local<v8::Value>* value) |
| 1572 { | 1587 { |
| 1573 RefPtr<DOMArrayBuffer> arrayBuffer = doReadArrayBuffer(); | 1588 RefPtr<DOMArrayBuffer> arrayBuffer = doReadArrayBufferOrNull(); |
| 1574 if (!arrayBuffer) | 1589 // TODO(junov): crbug.com/536816 Instead of the following assert, we should consider doing: |
| 1575 return false; | 1590 // if (!arrayBuffer) |
| 1591 // return false; | |
| 1592 // To do that, we need to make sure that call sites would react correctly | |
| 1593 // in this case, with the value not having been set. | |
| 1594 RELEASE_ASSERT(arrayBuffer); // This is essentially an out of memory crash | |
|
haraken
2015/10/29 18:58:37
You've added a bunch of RELEASE_ASSERT(arrayBuffer
Justin Novosad
2015/11/05 00:17:51
Done. Turns out that I made a mistake about this c
| |
| 1576 *value = toV8(arrayBuffer.release(), m_scriptState->context()->Global(), iso late()); | 1595 *value = toV8(arrayBuffer.release(), m_scriptState->context()->Global(), iso late()); |
| 1577 return !value->IsEmpty(); | 1596 return !value->IsEmpty(); |
| 1578 } | 1597 } |
| 1579 | 1598 |
| 1580 bool SerializedScriptValueReader::readArrayBufferView(v8::Local<v8::Value>* valu e, ScriptValueCompositeCreator& creator) | 1599 bool SerializedScriptValueReader::readArrayBufferView(v8::Local<v8::Value>* valu e, ScriptValueCompositeCreator& creator) |
| 1581 { | 1600 { |
| 1582 ArrayBufferViewSubTag subTag; | 1601 ArrayBufferViewSubTag subTag; |
| 1583 uint32_t byteOffset; | 1602 uint32_t byteOffset; |
| 1584 uint32_t byteLength; | 1603 uint32_t byteLength; |
| 1585 RefPtr<DOMArrayBufferBase> arrayBuffer; | 1604 RefPtr<DOMArrayBufferBase> arrayBuffer; |
| (...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2157 return false; | 2176 return false; |
| 2158 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeRefe renceStack.size() - 1]; | 2177 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeRefe renceStack.size() - 1]; |
| 2159 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() - 1); | 2178 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() - 1); |
| 2160 if (objectReference >= m_objectPool.size()) | 2179 if (objectReference >= m_objectPool.size()) |
| 2161 return false; | 2180 return false; |
| 2162 *object = m_objectPool[objectReference]; | 2181 *object = m_objectPool[objectReference]; |
| 2163 return true; | 2182 return true; |
| 2164 } | 2183 } |
| 2165 | 2184 |
| 2166 } // namespace blink | 2185 } // namespace blink |
| OLD | NEW |