Commit 3b64764b authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

Make JSTypedArray::length() and length_value() ignore neutering.

Return the actual length even when the buffer is neutered (we used
to return 0). This avoids confusion and makes the behavior consistent
with byte_offset() and byte_length().

Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
Change-Id: I998f12fa4a428f8555f62e1535247f571ab053f2
Reviewed-on: https://chromium-review.googlesource.com/c/1256768Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56433}
parent 890fd9c8
...@@ -7639,7 +7639,7 @@ size_t v8::ArrayBufferView::ByteLength() { ...@@ -7639,7 +7639,7 @@ size_t v8::ArrayBufferView::ByteLength() {
size_t v8::TypedArray::Length() { size_t v8::TypedArray::Length() {
i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this); i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this);
return obj->length_value(); return obj->WasNeutered() ? 0 : obj->length_value();
} }
static_assert(v8::TypedArray::kMaxLength == i::Smi::kMaxValue, static_assert(v8::TypedArray::kMaxLength == i::Smi::kMaxValue,
......
...@@ -74,6 +74,7 @@ V8_WARN_UNUSED_RESULT Maybe<size_t> ValidateAtomicAccess( ...@@ -74,6 +74,7 @@ V8_WARN_UNUSED_RESULT Maybe<size_t> ValidateAtomicAccess(
size_t access_index; size_t access_index;
if (!TryNumberToSize(*access_index_obj, &access_index) || if (!TryNumberToSize(*access_index_obj, &access_index) ||
typed_array->WasNeutered() ||
access_index >= typed_array->length_value()) { access_index >= typed_array->length_value()) {
isolate->Throw(*isolate->factory()->NewRangeError( isolate->Throw(*isolate->factory()->NewRangeError(
MessageTemplate::kInvalidAtomicAccessIndex)); MessageTemplate::kInvalidAtomicAccessIndex));
......
...@@ -2361,7 +2361,6 @@ JSNativeContextSpecialization::BuildElementAccess( ...@@ -2361,7 +2361,6 @@ JSNativeContextSpecialization::BuildElementAccess(
length = length =
jsgraph()->Constant(static_cast<double>(typed_array->length_value())); jsgraph()->Constant(static_cast<double>(typed_array->length_value()));
// Check if the {receiver}s buffer was neutered.
buffer = jsgraph()->HeapConstant(typed_array->GetBuffer()); buffer = jsgraph()->HeapConstant(typed_array->GetBuffer());
// Load the (known) base and external pointer for the {receiver}. The // Load the (known) base and external pointer for the {receiver}. The
...@@ -2415,7 +2414,8 @@ JSNativeContextSpecialization::BuildElementAccess( ...@@ -2415,7 +2414,8 @@ JSNativeContextSpecialization::BuildElementAccess(
dependencies()->DependOnProtector(PropertyCellRef( dependencies()->DependOnProtector(PropertyCellRef(
js_heap_broker(), factory()->array_buffer_neutering_protector())); js_heap_broker(), factory()->array_buffer_neutering_protector()));
} else { } else {
// Bail out if the {buffer} was neutered. // Deopt if the {buffer} was neutered.
// Note: A neutered buffer leads to megamorphic feedback.
Node* buffer_bit_field = effect = graph()->NewNode( Node* buffer_bit_field = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()), simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()),
buffer, effect, control); buffer, effect, control);
......
...@@ -3178,8 +3178,8 @@ class TypedElementsAccessor ...@@ -3178,8 +3178,8 @@ class TypedElementsAccessor
size_t start, size_t end) { size_t start, size_t end) {
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
DCHECK_EQ(destination->GetElementsKind(), AccessorClass::kind()); DCHECK_EQ(destination->GetElementsKind(), AccessorClass::kind());
DCHECK(!source->WasNeutered()); CHECK(!source->WasNeutered());
DCHECK(!destination->WasNeutered()); CHECK(!destination->WasNeutered());
DCHECK_LE(start, end); DCHECK_LE(start, end);
DCHECK_LE(end, source->length_value()); DCHECK_LE(end, source->length_value());
...@@ -3249,6 +3249,9 @@ class TypedElementsAccessor ...@@ -3249,6 +3249,9 @@ class TypedElementsAccessor
// side-effects, as the source elements will always be a number. // side-effects, as the source elements will always be a number.
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
CHECK(!source->WasNeutered());
CHECK(!destination->WasNeutered());
FixedTypedArrayBase* source_elements = FixedTypedArrayBase* source_elements =
FixedTypedArrayBase::cast(source->elements()); FixedTypedArrayBase::cast(source->elements());
BackingStore* destination_elements = BackingStore* destination_elements =
...@@ -3339,6 +3342,8 @@ class TypedElementsAccessor ...@@ -3339,6 +3342,8 @@ class TypedElementsAccessor
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
DisallowJavascriptExecution no_js(isolate); DisallowJavascriptExecution no_js(isolate);
CHECK(!destination->WasNeutered());
size_t current_length; size_t current_length;
DCHECK(source->length()->IsNumber() && DCHECK(source->length()->IsNumber() &&
TryNumberToSize(source->length(), &current_length) && TryNumberToSize(source->length(), &current_length) &&
...@@ -3459,6 +3464,7 @@ class TypedElementsAccessor ...@@ -3459,6 +3464,7 @@ class TypedElementsAccessor
Handle<JSTypedArray> destination_ta = Handle<JSTypedArray> destination_ta =
Handle<JSTypedArray>::cast(destination); Handle<JSTypedArray>::cast(destination);
DCHECK_LE(offset + length, destination_ta->length_value()); DCHECK_LE(offset + length, destination_ta->length_value());
CHECK(!destination_ta->WasNeutered());
if (length == 0) return *isolate->factory()->undefined_value(); if (length == 0) return *isolate->factory()->undefined_value();
...@@ -3486,7 +3492,6 @@ class TypedElementsAccessor ...@@ -3486,7 +3492,6 @@ class TypedElementsAccessor
// If we have to copy more elements than we have in the source, we need to // If we have to copy more elements than we have in the source, we need to
// do special handling and conversion; that happens in the slow case. // do special handling and conversion; that happens in the slow case.
if (length + offset <= source_ta->length_value()) { if (length + offset <= source_ta->length_value()) {
DCHECK(length == 0 || !source_ta->WasNeutered());
CopyElementsFromTypedArray(*source_ta, *destination_ta, length, offset); CopyElementsFromTypedArray(*source_ta, *destination_ta, length, offset);
return *isolate->factory()->undefined_value(); return *isolate->factory()->undefined_value();
} }
......
...@@ -130,13 +130,11 @@ bool JSArrayBufferView::WasNeutered() const { ...@@ -130,13 +130,11 @@ bool JSArrayBufferView::WasNeutered() const {
} }
Object* JSTypedArray::length() const { Object* JSTypedArray::length() const {
if (WasNeutered()) return Smi::kZero;
return Object::cast(READ_FIELD(this, kLengthOffset)); return Object::cast(READ_FIELD(this, kLengthOffset));
} }
size_t JSTypedArray::length_value() const { size_t JSTypedArray::length_value() const {
if (WasNeutered()) return 0; double val = length()->Number();
double val = Object::cast(READ_FIELD(this, kLengthOffset))->Number();
DCHECK_LE(val, kMaxSafeInteger); // 2^53-1 DCHECK_LE(val, kMaxSafeInteger); // 2^53-1
DCHECK_GE(val, -kMaxSafeInteger); // -2^53+1 DCHECK_GE(val, -kMaxSafeInteger); // -2^53+1
DCHECK_LE(val, std::numeric_limits<size_t>::max()); DCHECK_LE(val, std::numeric_limits<size_t>::max());
......
...@@ -221,9 +221,9 @@ Maybe<bool> JSTypedArray::DefineOwnProperty(Isolate* isolate, ...@@ -221,9 +221,9 @@ Maybe<bool> JSTypedArray::DefineOwnProperty(Isolate* isolate,
NewTypeError(MessageTemplate::kInvalidTypedArrayIndex)); NewTypeError(MessageTemplate::kInvalidTypedArrayIndex));
} }
// 3b iv. Let length be O.[[ArrayLength]]. // 3b iv. Let length be O.[[ArrayLength]].
uint32_t length = o->length()->Number(); size_t length = o->length_value();
// 3b v. If numericIndex ≥ length, return false. // 3b v. If numericIndex ≥ length, return false.
if (index >= length) { if (o->WasNeutered() || index >= length) {
RETURN_FAILURE(isolate, should_throw, RETURN_FAILURE(isolate, should_throw,
NewTypeError(MessageTemplate::kInvalidTypedArrayIndex)); NewTypeError(MessageTemplate::kInvalidTypedArrayIndex));
} }
......
...@@ -23,6 +23,7 @@ RUNTIME_FUNCTION(Runtime_AtomicsNumWaitersForTesting) { ...@@ -23,6 +23,7 @@ RUNTIME_FUNCTION(Runtime_AtomicsNumWaitersForTesting) {
DCHECK_EQ(2, args.length()); DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
CONVERT_SIZE_ARG_CHECKED(index, 1); CONVERT_SIZE_ARG_CHECKED(index, 1);
CHECK(!sta->WasNeutered());
CHECK(sta->GetBuffer()->is_shared()); CHECK(sta->GetBuffer()->is_shared());
CHECK_LT(index, NumberToSize(sta->length())); CHECK_LT(index, NumberToSize(sta->length()));
CHECK_EQ(sta->type(), kExternalInt32Array); CHECK_EQ(sta->type(), kExternalInt32Array);
......
...@@ -163,6 +163,7 @@ RUNTIME_FUNCTION(Runtime_WasmExceptionGetElement) { ...@@ -163,6 +163,7 @@ RUNTIME_FUNCTION(Runtime_WasmExceptionGetElement) {
Handle<JSTypedArray> values = Handle<JSTypedArray>::cast(values_obj); Handle<JSTypedArray> values = Handle<JSTypedArray>::cast(values_obj);
CHECK_EQ(values->type(), kExternalUint16Array); CHECK_EQ(values->type(), kExternalUint16Array);
CONVERT_SMI_ARG_CHECKED(index, 1); CONVERT_SMI_ARG_CHECKED(index, 1);
CHECK(!values->WasNeutered());
CHECK_LT(index, Smi::ToInt(values->length())); CHECK_LT(index, Smi::ToInt(values->length()));
auto* vals = auto* vals =
reinterpret_cast<uint16_t*>(values->GetBuffer()->backing_store()); reinterpret_cast<uint16_t*>(values->GetBuffer()->backing_store());
...@@ -193,6 +194,7 @@ RUNTIME_FUNCTION(Runtime_WasmExceptionSetElement) { ...@@ -193,6 +194,7 @@ RUNTIME_FUNCTION(Runtime_WasmExceptionSetElement) {
Handle<JSTypedArray> values = Handle<JSTypedArray>::cast(values_obj); Handle<JSTypedArray> values = Handle<JSTypedArray>::cast(values_obj);
CHECK_EQ(values->type(), kExternalUint16Array); CHECK_EQ(values->type(), kExternalUint16Array);
CONVERT_SMI_ARG_CHECKED(index, 1); CONVERT_SMI_ARG_CHECKED(index, 1);
CHECK(!values->WasNeutered());
CHECK_LT(index, Smi::ToInt(values->length())); CHECK_LT(index, Smi::ToInt(values->length()));
CONVERT_SMI_ARG_CHECKED(value, 2); CONVERT_SMI_ARG_CHECKED(value, 2);
auto* vals = auto* vals =
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment