[rab/gsab] Fix flag mismatch in serialized data
Bug: v8:11111,chromium:1339648 Change-Id: I3b472f74f37a4e1514ce20635b16970e95a36e15 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3735162 Reviewed-by: Shu-yu Guo <syg@chromium.org> Commit-Queue: Marja Hölttä <marja@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/main@{#81598}
This commit is contained in:
parent
3f7c53b017
commit
3483b970eb
@ -65,6 +65,17 @@ static const uint32_t kLatestVersion = 15;
|
||||
static_assert(kLatestVersion == v8::CurrentValueSerializerFormatVersion(),
|
||||
"Exported format version must match latest version.");
|
||||
|
||||
namespace {
|
||||
// For serializing JSArrayBufferView flags. Instead of serializing /
|
||||
// deserializing the flags directly, we serialize them bit by bit. This is for
|
||||
// ensuring backwards compatilibity in the case where the representation
|
||||
// changes. Note that the ValueSerializer data can be stored on disk.
|
||||
using JSArrayBufferViewIsLengthTracking = base::BitField<bool, 0, 1>;
|
||||
using JSArrayBufferViewIsBackedByRab =
|
||||
JSArrayBufferViewIsLengthTracking::Next<bool, 1>;
|
||||
|
||||
} // namespace
|
||||
|
||||
template <typename T>
|
||||
static size_t BytesNeededForVarint(T value) {
|
||||
static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
|
||||
@ -934,6 +945,8 @@ Maybe<bool> ValueSerializer::WriteJSArrayBuffer(
|
||||
if (byte_length > std::numeric_limits<uint32_t>::max()) {
|
||||
return ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer);
|
||||
}
|
||||
// TODO(v8:11111): Support RAB / GSAB. The wire version will need to be
|
||||
// bumped.
|
||||
WriteTag(SerializationTag::kArrayBuffer);
|
||||
WriteVarint<uint32_t>(byte_length);
|
||||
WriteRawBytes(array_buffer->backing_store(), byte_length);
|
||||
@ -962,7 +975,10 @@ Maybe<bool> ValueSerializer::WriteJSArrayBufferView(JSArrayBufferView view) {
|
||||
WriteVarint(static_cast<uint8_t>(tag));
|
||||
WriteVarint(static_cast<uint32_t>(view.byte_offset()));
|
||||
WriteVarint(static_cast<uint32_t>(view.byte_length()));
|
||||
WriteVarint(static_cast<uint32_t>(view.bit_field()));
|
||||
uint32_t flags =
|
||||
JSArrayBufferViewIsLengthTracking::encode(view.is_length_tracking()) |
|
||||
JSArrayBufferViewIsBackedByRab::encode(view.is_backed_by_rab());
|
||||
WriteVarint(flags);
|
||||
return ThrowIfOutOfMemory();
|
||||
}
|
||||
|
||||
@ -2003,7 +2019,7 @@ MaybeHandle<JSArrayBuffer> ValueDeserializer::ReadTransferredJSArrayBuffer() {
|
||||
|
||||
MaybeHandle<JSArrayBufferView> ValueDeserializer::ReadJSArrayBufferView(
|
||||
Handle<JSArrayBuffer> buffer) {
|
||||
uint32_t buffer_byte_length = static_cast<uint32_t>(buffer->byte_length());
|
||||
uint32_t buffer_byte_length = static_cast<uint32_t>(buffer->GetByteLength());
|
||||
uint8_t tag = 0;
|
||||
uint32_t byte_offset = 0;
|
||||
uint32_t byte_length = 0;
|
||||
@ -2028,7 +2044,9 @@ MaybeHandle<JSArrayBufferView> ValueDeserializer::ReadJSArrayBufferView(
|
||||
Handle<JSDataView> data_view =
|
||||
isolate_->factory()->NewJSDataView(buffer, byte_offset, byte_length);
|
||||
AddObjectWithID(id, data_view);
|
||||
data_view->set_bit_field(flags);
|
||||
if (!ValidateAndSetJSArrayBufferViewFlags(*data_view, *buffer, flags)) {
|
||||
return MaybeHandle<JSArrayBufferView>();
|
||||
}
|
||||
return data_view;
|
||||
}
|
||||
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
|
||||
@ -2045,11 +2063,39 @@ MaybeHandle<JSArrayBufferView> ValueDeserializer::ReadJSArrayBufferView(
|
||||
}
|
||||
Handle<JSTypedArray> typed_array = isolate_->factory()->NewJSTypedArray(
|
||||
external_array_type, buffer, byte_offset, byte_length / element_size);
|
||||
typed_array->set_bit_field(flags);
|
||||
if (!ValidateAndSetJSArrayBufferViewFlags(*typed_array, *buffer, flags)) {
|
||||
return MaybeHandle<JSArrayBufferView>();
|
||||
}
|
||||
AddObjectWithID(id, typed_array);
|
||||
return typed_array;
|
||||
}
|
||||
|
||||
bool ValueDeserializer::ValidateAndSetJSArrayBufferViewFlags(
|
||||
JSArrayBufferView view, JSArrayBuffer buffer, uint32_t serialized_flags) {
|
||||
bool is_length_tracking =
|
||||
JSArrayBufferViewIsLengthTracking::decode(serialized_flags);
|
||||
bool is_backed_by_rab =
|
||||
JSArrayBufferViewIsBackedByRab::decode(serialized_flags);
|
||||
|
||||
// TODO(marja): When the version number is bumped the next time, check that
|
||||
// serialized_flags doesn't contain spurious 1-bits.
|
||||
|
||||
if (is_backed_by_rab || is_length_tracking) {
|
||||
if (!FLAG_harmony_rab_gsab) {
|
||||
return false;
|
||||
}
|
||||
if (!buffer.is_resizable()) {
|
||||
return false;
|
||||
}
|
||||
if (is_backed_by_rab && buffer.is_shared()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
view.set_is_length_tracking(is_length_tracking);
|
||||
view.set_is_backed_by_rab(is_backed_by_rab);
|
||||
return true;
|
||||
}
|
||||
|
||||
MaybeHandle<Object> ValueDeserializer::ReadJSError() {
|
||||
uint32_t id = next_id_++;
|
||||
|
||||
|
@ -300,6 +300,9 @@ class ValueDeserializer {
|
||||
V8_WARN_UNUSED_RESULT;
|
||||
MaybeHandle<JSArrayBufferView> ReadJSArrayBufferView(
|
||||
Handle<JSArrayBuffer> buffer) V8_WARN_UNUSED_RESULT;
|
||||
bool ValidateAndSetJSArrayBufferViewFlags(
|
||||
JSArrayBufferView view, JSArrayBuffer buffer,
|
||||
uint32_t serialized_flags) V8_WARN_UNUSED_RESULT;
|
||||
MaybeHandle<Object> ReadJSError() V8_WARN_UNUSED_RESULT;
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
MaybeHandle<JSObject> ReadWasmModuleTransfer() V8_WARN_UNUSED_RESULT;
|
||||
|
17
test/mjsunit/rab-gsab-valueserializer.js
Normal file
17
test/mjsunit/rab-gsab-valueserializer.js
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --harmony-rab-gsab
|
||||
|
||||
"use strict";
|
||||
|
||||
(function FlagMismatch() {
|
||||
// Length tracking TA, buffer not resizable.
|
||||
const data1 = new Uint8Array([255, 15, 66, 4, 3, 5, 7, 11, 86, 66, 1, 2, 1]);
|
||||
assertThrows(() => { d8.serializer.deserialize(data1.buffer); });
|
||||
|
||||
// RAB backed TA, buffer not resizable.
|
||||
const data2 = new Uint8Array([255, 15, 66, 4, 3, 5, 7, 11, 86, 66, 1, 2, 2]);
|
||||
assertThrows(() => { d8.serializer.deserialize(data2.buffer); });
|
||||
})();
|
Loading…
Reference in New Issue
Block a user