Skip to content

Commit eb52863

Browse files
committed
Fix ArrayBuffer immutable-method semantics
sliceToImmutable throws RangeError (not TypeError) when a resizable source shrinks below the resolved end during argument coercion; transferToImmutable coerces newLength before checking detachability so valueOf side effects are observed.
1 parent 249bb27 commit eb52863

2 files changed

Lines changed: 12 additions & 8 deletions

File tree

quickjs.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58227,13 +58227,14 @@ static JSValue js_array_buffer_transfer(JSContext *ctx, JSValueConst this_val,
5822758227
return JS_EXCEPTION;
5822858228
if (abuf->shared)
5822958229
return JS_ThrowTypeError(ctx, "cannot transfer a SharedArrayBuffer");
58230-
if (magic == JS_ARRAY_BUFFER_TRANSFER_TO_IMMUTABLE && abuf->immutable)
58231-
return JS_ThrowTypeErrorImmutableArrayBuffer(ctx);
58230+
// Spec (ArrayBufferCopyAndDetach): the newLength argument must be
58231+
// coerced (its valueOf observed) before the buffer's detachability /
58232+
// immutability is checked, so side effects of coercion are visible.
5823258233
if (argc < 1 || JS_IsUndefined(argv[0]))
5823358234
new_len = abuf->byte_length;
5823458235
else if (JS_ToIndex(ctx, &new_len, argv[0]))
5823558236
return JS_EXCEPTION;
58236-
if (magic != JS_ARRAY_BUFFER_TRANSFER_TO_IMMUTABLE && abuf->immutable)
58237+
if (abuf->immutable)
5823758238
return JS_ThrowTypeErrorImmutableArrayBuffer(ctx);
5823858239
if (abuf->detached)
5823958240
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
@@ -58410,10 +58411,17 @@ static JSValue js_array_buffer_slice(JSContext *ctx,
5841058411
goto fail;
5841158412
}
5841258413
/* must test again because of side effects */
58413-
if (abuf->detached || abuf->byte_length < start + new_len) {
58414+
if (abuf->detached) {
5841458415
JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
5841558416
goto fail;
5841658417
}
58418+
if (abuf->byte_length < start + new_len) {
58419+
if (immutable)
58420+
JS_ThrowRangeError(ctx, "invalid array buffer length");
58421+
else
58422+
JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
58423+
goto fail;
58424+
}
5841758425
memcpy(new_abuf->data, abuf->data + start, new_len);
5841858426
new_abuf->immutable = immutable;
5841958427
return new_obj;

test262_errors.txt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@ test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in-
55
test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in-prefix-update.js:27: SyntaxError: invalid increment/decrement operand
66
test262/test/annexB/language/expressions/assignmenttargettype/callexpression.js:33: SyntaxError: invalid assignment left-hand side
77
test262/test/annexB/language/expressions/assignmenttargettype/cover-callexpression-and-asyncarrowhead.js:20: SyntaxError: invalid assignment left-hand side
8-
test262/test/built-ins/ArrayBuffer/prototype/sliceToImmutable/this-shrinks.js:40: Test262Error: resize below resolved end Expected a RangeError but got a TypeError
9-
test262/test/built-ins/ArrayBuffer/prototype/sliceToImmutable/this-shrinks.js:40: strict mode: Test262Error: resize below resolved end Expected a RangeError but got a TypeError
10-
test262/test/built-ins/ArrayBuffer/prototype/transferToImmutable/this-is-not-detachable.js:35: Test262Error: Actual [] and expected [newLength.valueOf] should have the same contents. [immutable ArrayBuffer] Must read arguments before verifying detachability.
11-
test262/test/built-ins/ArrayBuffer/prototype/transferToImmutable/this-is-not-detachable.js:35: strict mode: Test262Error: Actual [] and expected [newLength.valueOf] should have the same contents. [immutable ArrayBuffer] Must read arguments before verifying detachability.
128
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/iterator-result-poisoned-wrapper.js:64: TypeError: $DONE() not called
139
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/iterator-result-poisoned-wrapper.js:64: strict mode: TypeError: $DONE() not called
1410
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/next-result-poisoned-wrapper.js:69: TypeError: $DONE() not called

0 commit comments

Comments
 (0)