Skip to content

Commit 2209d95

Browse files
committed
deps: V8: cherry-pick c5ff7c4d6cde
Original commit message: [builtins] disallow ArrayBuffer transfer with a detach key This allows embedder to disallow `ArrayBuffer.prototype.transfer()` on an arraybuffer that is not detachable. This also fix the check on `ArrayBufferCopyAndDetach` step 8 of `ArrayBuffer.prototype.transfer`. Refs: #61362 Refs: https://tc39.es/ecma262/#sec-arraybuffercopyanddetach Change-Id: I3c6e156a8fad007fd100218d8b16aed5c4e1db68 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7454288 Commit-Queue: Chengzhong Wu <cwu631@bloomberg.net> Reviewed-by: Olivier Flückiger <olivf@chromium.org> Cr-Commit-Position: refs/heads/main@{#104697} Refs: v8/v8@c5ff7c4
1 parent b5bda89 commit 2209d95

File tree

5 files changed

+66
-2
lines changed

5 files changed

+66
-2
lines changed

common.gypi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838

3939
# Reset this number to 0 on major V8 upgrades.
4040
# Increment by one for each non-official patch applied to deps/v8.
41-
'v8_embedder_string': '-node.10',
41+
'v8_embedder_string': '-node.11',
4242

4343
##### V8 defaults for Node.js #####
4444

deps/v8/src/builtins/builtins-arraybuffer.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,8 @@ Tagged<Object> ArrayBufferTransfer(Isolate* isolate,
638638
// 8. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a
639639
// TypeError exception.
640640

641-
if (!array_buffer->is_detachable()) {
641+
if (!IsUndefined(array_buffer->detach_key()) ||
642+
!array_buffer->is_detachable()) {
642643
THROW_NEW_ERROR_RETURN_FAILURE(
643644
isolate,
644645
NewTypeError(MessageTemplate::kDataCloneErrorNonDetachableArrayBuffer));
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2026 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
//
5+
// Flags: --allow-natives-syntax
6+
7+
function TestTransferSucceeds() {
8+
const ab = new ArrayBuffer(100);
9+
%ArrayBufferSetDetachKey(ab, undefined);
10+
ab.transfer();
11+
assertEquals(0, ab.byteLength); // Detached.
12+
}
13+
14+
function TestTransferFails() {
15+
const ab = new ArrayBuffer(100);
16+
%ArrayBufferSetDetachKey(ab, Symbol());
17+
assertThrows(() => { ab.transfer(); }, TypeError);
18+
assertEquals(100, ab.byteLength); // Not detached.
19+
}
20+
21+
TestTransferSucceeds();
22+
TestTransferFails();

deps/v8/test/unittests/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ v8_source_set("v8_unittests_sources") {
263263
"api/remote-object-unittest.cc",
264264
"api/resource-constraints-unittest.cc",
265265
"api/smi-tagging-unittest.cc",
266+
"api/v8-array-buffer-unittest.cc",
266267
"api/v8-array-unittest.cc",
267268
"api/v8-maybe-unittest.cc",
268269
"api/v8-memory-span-unittest.cc",
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2026 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "include/v8-array-buffer.h"
6+
7+
#include "test/unittests/test-utils.h"
8+
#include "testing/gtest/include/gtest/gtest.h"
9+
10+
namespace v8 {
11+
namespace {
12+
13+
using ArrayBufferTest = TestWithContext;
14+
15+
TEST_F(ArrayBufferTest, TransferWithDetachKey) {
16+
Local<ArrayBuffer> ab = ArrayBuffer::New(isolate(), 1);
17+
Local<Value> key = Symbol::New(isolate());
18+
ab->SetDetachKey(key);
19+
Local<Object> global = context()->Global();
20+
Local<String> property_name =
21+
String::NewFromUtf8Literal(isolate(), "test_ab");
22+
global->Set(context(), property_name, ab).ToChecked();
23+
24+
{
25+
TryCatch try_catch(isolate());
26+
CHECK(TryRunJS("globalThis.test_ab.transfer()").IsEmpty());
27+
}
28+
29+
// Didnot transfer.
30+
EXPECT_EQ(ab->ByteLength(), 1u);
31+
32+
ab->SetDetachKey(Undefined(isolate()));
33+
RunJS("globalThis.test_ab.transfer()");
34+
35+
// Transferred.
36+
EXPECT_EQ(ab->ByteLength(), 0u);
37+
}
38+
39+
} // namespace
40+
} // namespace v8

0 commit comments

Comments
 (0)