[sandbox] Fix another deserializer issues when the sandbox is enabled

When a detached JSDataView is deserialized, it's backing ArrayBuffer
backing store is empty (i.e. the EmptyBackingStoreBuffer() pointer).
Previously, the JSDataView's data_pointer would then be set to
EmptyBackingStoreBuffer() + byte_offset(), which is not a valid backing
store pointer as it points outside of the sandbox. Instead, which this
CL the data_pointer is now simply set to EmptyBackingStoreBuffer().

Bug: v8:10391
Change-Id: Ic7d144f2f20d5ec99438d2b3bf33735fbf8d5fc6
Cq-Include-Trybots: luci.v8.try:v8_linux64_heap_sandbox_dbg_ng,v8_linux_arm64_sim_heap_sandbox_dbg_ng
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3717987
Commit-Queue: Samuel Groß <saelo@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81348}
This commit is contained in:
Samuel Groß 2022-06-22 14:21:56 +02:00 committed by V8 LUCI CQ
parent eea893d594
commit d22b3c9651

View File

@ -373,23 +373,31 @@ void Deserializer<IsolateT>::PostProcessNewJSReceiver(
auto data_view = JSDataView::cast(raw_obj);
auto buffer = JSArrayBuffer::cast(data_view.buffer());
void* backing_store = EmptyBackingStoreBuffer();
// At this point, the backing store may already have been set if this is an
// empty ArrayBuffer (see the IsJSArrayBuffer case below). In that case,
// the backing store ref/index is no longer valid so explicitly check here
// if the buffer is empty before using the store index.
if (buffer.backing_store() != EmptyBackingStoreBuffer()) {
uint32_t store_index = buffer.GetBackingStoreRefForDeserialization();
if (store_index != kEmptyBackingStoreRefSentinel) {
// The backing store of the JSArrayBuffer has not been correctly
// restored yet, as that may trigger GC. The backing_store field
// currently contains a numbered reference to an already deserialized
// backing store.
backing_store = backing_stores_[store_index]->buffer_start();
if (buffer.was_detached()) {
// Directly set the data pointer to point to the EmptyBackingStoreBuffer.
// Otherwise, we might end up setting it to EmptyBackingStoreBuffer() +
// byte_offset() which would result in an invalid pointer.
data_view.set_data_pointer(main_thread_isolate(),
EmptyBackingStoreBuffer());
} else {
// At this point, the backing store may already have been set if this is
// an empty ArrayBuffer (see the IsJSArrayBuffer case below). In that
// case, the backing store ref/index is no longer valid so explicitly
// check here if the buffer is empty before using the store index.
if (buffer.backing_store() != EmptyBackingStoreBuffer()) {
uint32_t store_index = buffer.GetBackingStoreRefForDeserialization();
if (store_index != kEmptyBackingStoreRefSentinel) {
// The backing store of the JSArrayBuffer has not been correctly
// restored yet, as that may trigger GC. The backing_store field
// currently contains a numbered reference to an already deserialized
// backing store.
backing_store = backing_stores_[store_index]->buffer_start();
}
}
data_view.set_data_pointer(
main_thread_isolate(),
reinterpret_cast<uint8_t*>(backing_store) + data_view.byte_offset());
}
data_view.set_data_pointer(
main_thread_isolate(),
reinterpret_cast<uint8_t*>(backing_store) + data_view.byte_offset());
} else if (InstanceTypeChecker::IsJSTypedArray(instance_type)) {
auto typed_array = JSTypedArray::cast(raw_obj);
// Fixup typed array pointers.