Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a3ac445

Browse filesBrowse files
daeyeonruyadorno
authored andcommitted
stream: fix isDetachedBuffer validations
Signed-off-by: Daeyeon Jeong daeyeon.dev@gmail.com PR-URL: #44114 Refs: #43866 Reviewed-By: LiviaMedeiros <livia@cirno.name> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent bce8041 commit a3ac445
Copy full SHA for a3ac445

File tree

Expand file treeCollapse file tree

3 files changed

+57
-21
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

3 files changed

+57
-21
lines changed
Open diff view settings
Collapse file

‎lib/internal/webstreams/readablestream.js‎

Copy file name to clipboardExpand all lines: lib/internal/webstreams/readablestream.js
+17-18Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ const {
5959
} = require('v8');
6060

6161
const {
62+
validateBuffer,
6263
validateObject,
6364
} = require('internal/validators');
6465

@@ -101,6 +102,7 @@ const {
101102
extractHighWaterMark,
102103
extractSizeAlgorithm,
103104
lazyTransfer,
105+
isDetachedBuffer,
104106
isViewedArrayBufferDetached,
105107
isBrandCheck,
106108
resetQueue,
@@ -658,11 +660,13 @@ class ReadableStreamBYOBRequest {
658660
const viewBuffer = ArrayBufferViewGetBuffer(view);
659661
const viewBufferByteLength = ArrayBufferGetByteLength(viewBuffer);
660662

661-
if (viewByteLength === 0 || viewBufferByteLength === 0) {
662-
throw new ERR_INVALID_STATE.TypeError(
663-
'View ArrayBuffer is zero-length or detached');
663+
if (isDetachedBuffer(viewBuffer)) {
664+
throw new ERR_INVALID_STATE.TypeError('Viewed ArrayBuffer is detached');
664665
}
665666

667+
assert(viewByteLength > 0);
668+
assert(viewBufferByteLength > 0);
669+
666670
readableByteStreamControllerRespond(controller, bytesWritten);
667671
}
668672

@@ -681,6 +685,8 @@ class ReadableStreamBYOBRequest {
681685
'This BYOB request has been invalidated');
682686
}
683687

688+
validateBuffer(view, 'view');
689+
684690
if (isViewedArrayBufferDetached(view)) {
685691
throw new ERR_INVALID_STATE.TypeError('Viewed ArrayBuffer is detached');
686692
}
@@ -894,15 +900,19 @@ class ReadableStreamBYOBReader {
894900
],
895901
view));
896902
}
903+
897904
const viewByteLength = ArrayBufferViewGetByteLength(view);
898905
const viewBuffer = ArrayBufferViewGetBuffer(view);
899906
const viewBufferByteLength = ArrayBufferGetByteLength(viewBuffer);
900907

901908
if (viewByteLength === 0 || viewBufferByteLength === 0) {
902909
return PromiseReject(
903910
new ERR_INVALID_STATE.TypeError(
904-
'View ArrayBuffer is zero-length or detached'));
911+
'View or Viewed ArrayBuffer is zero-length or detached',
912+
),
913+
);
905914
}
915+
906916
// Supposed to assert here that the view's buffer is not
907917
// detached, but there's no API available to use to check that.
908918
if (this[kState].stream === undefined) {
@@ -2298,11 +2308,10 @@ function readableByteStreamControllerEnqueue(
22982308
if (pendingPullIntos.length) {
22992309
const firstPendingPullInto = pendingPullIntos[0];
23002310

2301-
const pendingBufferByteLength =
2302-
ArrayBufferGetByteLength(firstPendingPullInto.buffer);
2303-
if (pendingBufferByteLength === 0) {
2311+
if (isDetachedBuffer(firstPendingPullInto.buffer)) {
23042312
throw new ERR_INVALID_STATE.TypeError(
2305-
'Destination ArrayBuffer is zero-length or detached');
2313+
'Destination ArrayBuffer is detached',
2314+
);
23062315
}
23072316

23082317
firstPendingPullInto.buffer =
@@ -2501,16 +2510,6 @@ function readableByteStreamControllerRespondWithNewView(controller, view) {
25012510
const desc = pendingPullIntos[0];
25022511
assert(stream[kState].state !== 'errored');
25032512

2504-
if (!isArrayBufferView(view)) {
2505-
throw new ERR_INVALID_ARG_TYPE(
2506-
'view',
2507-
[
2508-
'Buffer',
2509-
'TypedArray',
2510-
'DataView',
2511-
],
2512-
view);
2513-
}
25142513
const viewByteLength = ArrayBufferViewGetByteLength(view);
25152514
const viewByteOffset = ArrayBufferViewGetByteOffset(view);
25162515
const viewBuffer = ArrayBufferViewGetBuffer(view);
Collapse file

‎lib/internal/webstreams/util.js‎

Copy file name to clipboardExpand all lines: lib/internal/webstreams/util.js
+6-3Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,13 @@ function transferArrayBuffer(buffer) {
129129
return res;
130130
}
131131

132-
function isArrayBufferDetached(buffer) {
132+
function isDetachedBuffer(buffer) {
133133
if (ArrayBufferGetByteLength(buffer) === 0) {
134+
// TODO(daeyeon): Consider using C++ builtin to improve performance.
134135
try {
135136
new Uint8Array(buffer);
136-
} catch {
137+
} catch (error) {
138+
assert(error.name === 'TypeError');
137139
return true;
138140
}
139141
}
@@ -143,7 +145,7 @@ function isArrayBufferDetached(buffer) {
143145
function isViewedArrayBufferDetached(view) {
144146
return (
145147
ArrayBufferViewGetByteLength(view) === 0 &&
146-
isArrayBufferDetached(ArrayBufferViewGetBuffer(view))
148+
isDetachedBuffer(ArrayBufferViewGetBuffer(view))
147149
);
148150
}
149151

@@ -243,6 +245,7 @@ module.exports = {
243245
extractSizeAlgorithm,
244246
lazyTransfer,
245247
isBrandCheck,
248+
isDetachedBuffer,
246249
isPromisePending,
247250
isViewedArrayBufferDetached,
248251
peekQueueValue,
Collapse file

‎test/parallel/test-whatwg-readablebytestream-bad-buffers-and-views.js‎

Copy file name to clipboardExpand all lines: test/parallel/test-whatwg-readablebytestream-bad-buffers-and-views.js
+34Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,38 @@ let pass = 0;
5151
reader.read(new Uint8Array([4, 5, 6]));
5252
}
5353

54+
{
55+
const stream = new ReadableStream({
56+
start(c) {
57+
c.enqueue(new Uint8Array([1, 2, 3]));
58+
},
59+
type: 'bytes',
60+
});
61+
const reader = stream.getReader({ mode: 'byob' });
62+
const view = new Uint8Array();
63+
assert
64+
.rejects(reader.read(view), {
65+
code: 'ERR_INVALID_STATE',
66+
name: 'TypeError',
67+
})
68+
.then(common.mustCall());
69+
}
70+
71+
{
72+
const stream = new ReadableStream({
73+
start(c) {
74+
c.enqueue(new Uint8Array([1, 2, 3]));
75+
},
76+
type: 'bytes',
77+
});
78+
const reader = stream.getReader({ mode: 'byob' });
79+
const view = new Uint8Array(new ArrayBuffer(10), 0, 0);
80+
assert
81+
.rejects(reader.read(view), {
82+
code: 'ERR_INVALID_STATE',
83+
name: 'TypeError',
84+
})
85+
.then(common.mustCall());
86+
}
87+
5488
process.on('exit', () => assert.strictEqual(pass, 2));

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.