Add checks for detached ArrayBuffers to ArrayBuffer.prototype.slice
These checks ensure that a TypeError is thrown, per spec, rather than a runtime assert failure. BUG=v8:4964 R=adamk LOG=Y Review-Url: https://codereview.chromium.org/1929123002 Cr-Commit-Position: refs/heads/master@{#35885}
This commit is contained in:
parent
a4fa471a33
commit
3d66e5d1d7
@ -70,7 +70,9 @@ function ArrayBufferSlice(start, end) {
|
||||
throw MakeTypeError(kIncompatibleMethodReceiver,
|
||||
'ArrayBuffer.prototype.slice', result);
|
||||
}
|
||||
// TODO(littledan): Check for a detached ArrayBuffer
|
||||
// Checks for detached source/target ArrayBuffers are done inside of
|
||||
// %ArrayBufferSliceImpl; the reordering of checks does not violate
|
||||
// the spec because all exceptions thrown are TypeErrors.
|
||||
if (result === this) {
|
||||
throw MakeTypeError(kArrayBufferSpeciesThis);
|
||||
}
|
||||
|
@ -117,6 +117,8 @@ class CallSite {
|
||||
T(DebuggerType, "Debugger: Parameters have wrong types.") \
|
||||
T(DeclarationMissingInitializer, "Missing initializer in % declaration") \
|
||||
T(DefineDisallowed, "Cannot define property:%, object is not extensible.") \
|
||||
T(DetachedOperation, \
|
||||
"Cannot perform % on a detached ArrayBuffer") \
|
||||
T(DuplicateTemplateProperty, "Object template has duplicate property '%'") \
|
||||
T(ExtendsValueGenerator, \
|
||||
"Class extends value % may not be a generator function") \
|
||||
|
@ -28,6 +28,14 @@ RUNTIME_FUNCTION(Runtime_ArrayBufferSliceImpl) {
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1);
|
||||
CONVERT_NUMBER_ARG_HANDLE_CHECKED(first, 2);
|
||||
CONVERT_NUMBER_ARG_HANDLE_CHECKED(new_length, 3);
|
||||
|
||||
if (source->was_neutered() || target->was_neutered()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewTypeError(MessageTemplate::kDetachedOperation,
|
||||
isolate->factory()->NewStringFromAsciiChecked(
|
||||
"ArrayBuffer.prototype.slice")));
|
||||
}
|
||||
|
||||
RUNTIME_ASSERT(!source.is_identical_to(target));
|
||||
size_t start = 0, target_length = 0;
|
||||
RUNTIME_ASSERT(TryNumberToSize(isolate, *first, &start));
|
||||
|
@ -119,7 +119,7 @@ bytecodes: [
|
||||
B(TestEqualStrict), R(12),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), U16(129),
|
||||
B(Wide), B(LdaSmi), U16(130),
|
||||
B(Star), R(12),
|
||||
B(LdaConstant), U8(8),
|
||||
B(Star), R(13),
|
||||
@ -302,7 +302,7 @@ bytecodes: [
|
||||
B(TestEqualStrict), R(13),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), U16(129),
|
||||
B(Wide), B(LdaSmi), U16(130),
|
||||
B(Star), R(13),
|
||||
B(LdaConstant), U8(8),
|
||||
B(Star), R(14),
|
||||
@ -499,7 +499,7 @@ bytecodes: [
|
||||
B(TestEqualStrict), R(12),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), U16(129),
|
||||
B(Wide), B(LdaSmi), U16(130),
|
||||
B(Star), R(12),
|
||||
B(LdaConstant), U8(8),
|
||||
B(Star), R(13),
|
||||
@ -686,7 +686,7 @@ bytecodes: [
|
||||
B(TestEqualStrict), R(11),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), U16(129),
|
||||
B(Wide), B(LdaSmi), U16(130),
|
||||
B(Star), R(11),
|
||||
B(LdaConstant), U8(10),
|
||||
B(Star), R(12),
|
||||
|
@ -501,7 +501,7 @@ bytecodes: [
|
||||
B(TestEqualStrict), R(10),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), U16(129),
|
||||
B(Wide), B(LdaSmi), U16(130),
|
||||
B(Star), R(10),
|
||||
B(LdaConstant), U8(14),
|
||||
B(Star), R(11),
|
||||
|
@ -724,7 +724,7 @@ bytecodes: [
|
||||
B(InvokeIntrinsic), U16(Runtime::k_IsJSReceiver), R(3), U8(1),
|
||||
B(JumpIfToBooleanFalse), U8(4),
|
||||
B(Jump), U8(16),
|
||||
B(LdaSmi), U8(60),
|
||||
B(LdaSmi), U8(61),
|
||||
B(Star), R(3),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star), R(4),
|
||||
|
@ -41,19 +41,21 @@ assertThrows(function() {
|
||||
|
||||
|
||||
var buffer5 = new ArrayBuffer(100 * 1024);
|
||||
var buffer6 = buffer5.slice({valueOf : function() {
|
||||
%ArrayBufferNeuter(buffer5);
|
||||
return 0;
|
||||
}}, 100 * 1024 * 1024);
|
||||
assertEquals(0, buffer6.byteLength);
|
||||
assertThrows(function() {
|
||||
buffer5.slice({valueOf : function() {
|
||||
%ArrayBufferNeuter(buffer5);
|
||||
return 0;
|
||||
}}, 100 * 1024 * 1024);
|
||||
}, TypeError);
|
||||
|
||||
|
||||
var buffer7 = new ArrayBuffer(100 * 1024 * 1024);
|
||||
var buffer8 = buffer7.slice(0, {valueOf : function() {
|
||||
%ArrayBufferNeuter(buffer7);
|
||||
return 100 * 1024 * 1024;
|
||||
}});
|
||||
assertEquals(0, buffer8.byteLength);
|
||||
assertThrows(function() {
|
||||
buffer7.slice(0, {valueOf : function() {
|
||||
%ArrayBufferNeuter(buffer7);
|
||||
return 100 * 1024 * 1024;
|
||||
}});
|
||||
}, TypeError);
|
||||
|
||||
var buffer9 = new ArrayBuffer(1024);
|
||||
var array9 = new Uint8Array(buffer9);
|
||||
|
22
test/mjsunit/regress/regress-4964.js
Normal file
22
test/mjsunit/regress/regress-4964.js
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2016 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: --allow-natives-syntax
|
||||
|
||||
// Neutered source
|
||||
var ab = new ArrayBuffer(10);
|
||||
ab.constructor = { get [Symbol.species]() { %ArrayBufferNeuter(ab); return ArrayBuffer; } };
|
||||
assertThrows(() => ab.slice(0), TypeError);
|
||||
|
||||
// Neutered target
|
||||
class NeuteredArrayBuffer extends ArrayBuffer {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
%ArrayBufferNeuter(this);
|
||||
}
|
||||
}
|
||||
|
||||
var ab2 = new ArrayBuffer(10);
|
||||
ab2.constructor = NeuteredArrayBuffer;
|
||||
assertThrows(() => ab2.slice(0), TypeError);
|
Loading…
Reference in New Issue
Block a user