Skip to content

Commit 75d39e2

Browse files
committed
add patch c5ff7c4
1 parent c9d826c commit 75d39e2

1 file changed

Lines changed: 131 additions & 0 deletions

File tree

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
From c5ff7c4d6cdea06d0319609875c41eaa77b70db0 Mon Sep 17 00:00:00 2001
2+
From: Chengzhong Wu <[email protected]>
3+
Date: Tue, 13 Jan 2026 11:25:43 -0500
4+
Subject: [PATCH] [builtins] disallow ArrayBuffer transfer with a detach key
5+
MIME-Version: 1.0
6+
Content-Type: text/plain; charset=UTF-8
7+
Content-Transfer-Encoding: 8bit
8+
9+
This allows embedder to disallow `ArrayBuffer.prototype.transfer()` on
10+
an arraybuffer that is not detachable. This also fix the check on
11+
`ArrayBufferCopyAndDetach` step 8 of `ArrayBuffer.prototype.transfer`.
12+
13+
Refs: https://github.com/nodejs/node/issues/61362
14+
Refs: https://tc39.es/ecma262/#sec-arraybuffercopyanddetach
15+
Change-Id: I3c6e156a8fad007fd100218d8b16aed5c4e1db68
16+
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7454288
17+
Commit-Queue: Chengzhong Wu <[email protected]>
18+
Reviewed-by: Olivier Flückiger <[email protected]>
19+
Cr-Commit-Position: refs/heads/main@{#104697}
20+
---
21+
src/builtins/builtins-arraybuffer.cc | 3 +-
22+
.../array-buffer-transfer-detach-key.js | 22 ++++++++++
23+
test/unittests/BUILD.gn | 1 +
24+
.../unittests/api/v8-array-buffer-unittest.cc | 40 +++++++++++++++++++
25+
4 files changed, 65 insertions(+), 1 deletion(-)
26+
create mode 100644 test/mjsunit/array-buffer-transfer-detach-key.js
27+
create mode 100644 test/unittests/api/v8-array-buffer-unittest.cc
28+
29+
diff --git a/src/builtins/builtins-arraybuffer.cc b/src/builtins/builtins-arraybuffer.cc
30+
index b0495c8c28b..198e76ae46e 100644
31+
--- a/src/builtins/builtins-arraybuffer.cc
32+
+++ b/src/builtins/builtins-arraybuffer.cc
33+
@@ -715,7 +715,8 @@ Tagged<Object> ArrayBufferTransfer(Isolate* isolate,
34+
// 8. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a
35+
// TypeError exception.
36+
37+
- if (!array_buffer->is_detachable()) {
38+
+ if (!IsUndefined(array_buffer->detach_key()) ||
39+
+ !array_buffer->is_detachable()) {
40+
THROW_NEW_ERROR_RETURN_FAILURE(
41+
isolate,
42+
NewTypeError(MessageTemplate::kDataCloneErrorNonDetachableArrayBuffer));
43+
diff --git a/test/mjsunit/array-buffer-transfer-detach-key.js b/test/mjsunit/array-buffer-transfer-detach-key.js
44+
new file mode 100644
45+
index 00000000000..3c262fa8843
46+
--- /dev/null
47+
+++ b/test/mjsunit/array-buffer-transfer-detach-key.js
48+
@@ -0,0 +1,22 @@
49+
+// Copyright 2026 the V8 project authors. All rights reserved.
50+
+// Use of this source code is governed by a BSD-style license that can be
51+
+// found in the LICENSE file.
52+
+//
53+
+// Flags: --allow-natives-syntax
54+
+
55+
+function TestTransferSucceeds() {
56+
+ const ab = new ArrayBuffer(100);
57+
+ %ArrayBufferSetDetachKey(ab, undefined);
58+
+ ab.transfer();
59+
+ assertEquals(0, ab.byteLength); // Detached.
60+
+}
61+
+
62+
+function TestTransferFails() {
63+
+ const ab = new ArrayBuffer(100);
64+
+ %ArrayBufferSetDetachKey(ab, Symbol());
65+
+ assertThrows(() => { ab.transfer(); }, TypeError);
66+
+ assertEquals(100, ab.byteLength); // Not detached.
67+
+}
68+
+
69+
+TestTransferSucceeds();
70+
+TestTransferFails();
71+
diff --git a/test/unittests/BUILD.gn b/test/unittests/BUILD.gn
72+
index 3ff6c69fbfb..a107a5945b4 100644
73+
--- a/test/unittests/BUILD.gn
74+
+++ b/test/unittests/BUILD.gn
75+
@@ -263,6 +263,7 @@ v8_source_set("v8_unittests_sources") {
76+
"api/remote-object-unittest.cc",
77+
"api/resource-constraints-unittest.cc",
78+
"api/smi-tagging-unittest.cc",
79+
+ "api/v8-array-buffer-unittest.cc",
80+
"api/v8-array-unittest.cc",
81+
"api/v8-maybe-unittest.cc",
82+
"api/v8-memory-span-unittest.cc",
83+
diff --git a/test/unittests/api/v8-array-buffer-unittest.cc b/test/unittests/api/v8-array-buffer-unittest.cc
84+
new file mode 100644
85+
index 00000000000..4aaec1617f6
86+
--- /dev/null
87+
+++ b/test/unittests/api/v8-array-buffer-unittest.cc
88+
@@ -0,0 +1,40 @@
89+
+// Copyright 2026 the V8 project authors. All rights reserved.
90+
+// Use of this source code is governed by a BSD-style license that can be
91+
+// found in the LICENSE file.
92+
+
93+
+#include "include/v8-array-buffer.h"
94+
+
95+
+#include "test/unittests/test-utils.h"
96+
+#include "testing/gtest/include/gtest/gtest.h"
97+
+
98+
+namespace v8 {
99+
+namespace {
100+
+
101+
+using ArrayBufferTest = TestWithContext;
102+
+
103+
+TEST_F(ArrayBufferTest, TransferWithDetachKey) {
104+
+ Local<ArrayBuffer> ab = ArrayBuffer::New(isolate(), 1);
105+
+ Local<Value> key = Symbol::New(isolate());
106+
+ ab->SetDetachKey(key);
107+
+ Local<Object> global = context()->Global();
108+
+ Local<String> property_name =
109+
+ String::NewFromUtf8Literal(isolate(), "test_ab");
110+
+ global->Set(context(), property_name, ab).ToChecked();
111+
+
112+
+ {
113+
+ TryCatch try_catch(isolate());
114+
+ CHECK(TryRunJS("globalThis.test_ab.transfer()").IsEmpty());
115+
+ }
116+
+
117+
+ // Didnot transfer.
118+
+ EXPECT_EQ(ab->ByteLength(), 1u);
119+
+
120+
+ ab->SetDetachKey(Undefined(isolate()));
121+
+ RunJS("globalThis.test_ab.transfer()");
122+
+
123+
+ // Transferred.
124+
+ EXPECT_EQ(ab->ByteLength(), 0u);
125+
+}
126+
+
127+
+} // namespace
128+
+} // namespace v8
129+
--
130+
2.52.0
131+

0 commit comments

Comments
 (0)