Skip to content

Commit 2f0223b

Browse files
committed
lib: reject SharedArrayBuffer in web APIs per spec
Signed-off-by: Ali Hassan <ali-hassan27@outlook.com>
1 parent bf1aebc commit 2f0223b

File tree

7 files changed

+324
-25
lines changed

7 files changed

+324
-25
lines changed

lib/internal/blob.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ const {
4545
const {
4646
isAnyArrayBuffer,
4747
isArrayBufferView,
48+
isSharedArrayBuffer,
4849
} = require('internal/util/types');
4950

5051
const {
@@ -109,6 +110,21 @@ function getSource(source, endings) {
109110
if (isBlob(source))
110111
return [source.size, source[kHandle]];
111112

113+
if (isSharedArrayBuffer(source)) {
114+
throw new ERR_INVALID_ARG_TYPE(
115+
'source',
116+
['ArrayBuffer', 'TypedArray', 'DataView', 'Blob', 'string'],
117+
source,
118+
);
119+
}
120+
if (isArrayBufferView(source) && isSharedArrayBuffer(source.buffer)) {
121+
throw new ERR_INVALID_ARG_VALUE(
122+
'source',
123+
source,
124+
'must not be backed by a SharedArrayBuffer',
125+
);
126+
}
127+
112128
if (isAnyArrayBuffer(source)) {
113129
source = new Uint8Array(source);
114130
} else if (!isArrayBufferView(source)) {

lib/internal/crypto/webidl.js

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const {
3131
} = primordials;
3232

3333
const {
34+
converters: sharedConverters,
3435
makeException,
3536
createEnumConverter,
3637
createSequenceConverter,
@@ -43,11 +44,10 @@ const {
4344
} = require('internal/util');
4445
const { CryptoKey } = require('internal/crypto/webcrypto');
4546
const {
46-
getDataViewOrTypedArrayBuffer,
4747
validateMaxBufferLength,
4848
kNamedCurveAliases,
4949
} = require('internal/crypto/util');
50-
const { isArrayBuffer, isSharedArrayBuffer } = require('internal/util/types');
50+
const { isSharedArrayBuffer } = require('internal/util/types');
5151

5252
// https://tc39.es/ecma262/#sec-tonumber
5353
function toNumber(value, opts = kEmptyObject) {
@@ -193,8 +193,6 @@ converters.object = (V, opts) => {
193193
return V;
194194
};
195195

196-
const isNonSharedArrayBuffer = isArrayBuffer;
197-
198196
/**
199197
* @param {string | object} V - The hash algorithm identifier (string or object).
200198
* @param {string} label - The dictionary name for the error message.
@@ -223,25 +221,7 @@ converters.Uint8Array = (V, opts = kEmptyObject) => {
223221
return V;
224222
};
225223

226-
converters.BufferSource = (V, opts = kEmptyObject) => {
227-
if (ArrayBufferIsView(V)) {
228-
if (isSharedArrayBuffer(getDataViewOrTypedArrayBuffer(V))) {
229-
throw makeException(
230-
'is a view on a SharedArrayBuffer, which is not allowed.',
231-
opts);
232-
}
233-
234-
return V;
235-
}
236-
237-
if (!isNonSharedArrayBuffer(V)) {
238-
throw makeException(
239-
'is not instance of ArrayBuffer, Buffer, TypedArray, or DataView.',
240-
opts);
241-
}
242-
243-
return V;
244-
};
224+
converters.BufferSource = sharedConverters.BufferSource;
245225

246226
converters['sequence<DOMString>'] = createSequenceConverter(
247227
converters.DOMString);

lib/internal/webidl.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
'use strict';
22

33
const {
4+
ArrayBufferIsView,
45
ArrayPrototypePush,
56
ArrayPrototypeToSorted,
7+
DataViewPrototypeGetBuffer,
68
MathAbs,
79
MathMax,
810
MathMin,
@@ -19,6 +21,7 @@ const {
1921
Symbol,
2022
SymbolIterator,
2123
TypeError,
24+
TypedArrayPrototypeGetBuffer,
2225
} = primordials;
2326

2427
const {
@@ -28,6 +31,11 @@ const {
2831
},
2932
} = require('internal/errors');
3033
const { kEmptyObject } = require('internal/util');
34+
const {
35+
isArrayBuffer,
36+
isDataView,
37+
isSharedArrayBuffer,
38+
} = require('internal/util/types');
3139

3240
const converters = { __proto__: null };
3341

@@ -382,6 +390,47 @@ function createInterfaceConverter(name, I) {
382390
};
383391
}
384392

393+
function getDataViewOrTypedArrayBuffer(V) {
394+
return isDataView(V) ?
395+
DataViewPrototypeGetBuffer(V) : TypedArrayPrototypeGetBuffer(V);
396+
}
397+
398+
// https://webidl.spec.whatwg.org/#ArrayBufferView
399+
converters.ArrayBufferView = (V, opts = kEmptyObject) => {
400+
if (!ArrayBufferIsView(V)) {
401+
throw makeException(
402+
'is not an ArrayBufferView.',
403+
opts);
404+
}
405+
if (isSharedArrayBuffer(getDataViewOrTypedArrayBuffer(V))) {
406+
throw makeException(
407+
'is a view on a SharedArrayBuffer, which is not allowed.',
408+
opts);
409+
}
410+
411+
return V;
412+
};
413+
414+
// https://webidl.spec.whatwg.org/#BufferSource
415+
converters.BufferSource = (V, opts = kEmptyObject) => {
416+
if (ArrayBufferIsView(V)) {
417+
if (isSharedArrayBuffer(getDataViewOrTypedArrayBuffer(V))) {
418+
throw makeException(
419+
'is a view on a SharedArrayBuffer, which is not allowed.',
420+
opts);
421+
}
422+
423+
return V;
424+
}
425+
426+
if (!isArrayBuffer(V)) {
427+
throw makeException(
428+
'is not instance of ArrayBuffer, Buffer, TypedArray, or DataView.',
429+
opts);
430+
}
431+
432+
return V;
433+
};
385434

386435
module.exports = {
387436
type,

lib/internal/webstreams/compression.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const {
2626
const {
2727
codes: {
2828
ERR_INVALID_ARG_TYPE,
29+
ERR_INVALID_ARG_VALUE,
2930
},
3031
} = require('internal/errors');
3132

@@ -40,13 +41,20 @@ function lazyZlib() {
4041
// Per the Compression Streams spec, chunks must be BufferSource
4142
// (ArrayBuffer or ArrayBufferView not backed by SharedArrayBuffer).
4243
function validateBufferSourceChunk(chunk) {
43-
if (isArrayBufferView(chunk) && isSharedArrayBuffer(chunk.buffer)) {
44+
if (isSharedArrayBuffer(chunk)) {
4445
throw new ERR_INVALID_ARG_TYPE(
4546
'chunk',
4647
['ArrayBuffer', 'Buffer', 'TypedArray', 'DataView'],
4748
chunk,
4849
);
4950
}
51+
if (isArrayBufferView(chunk) && isSharedArrayBuffer(chunk.buffer)) {
52+
throw new ERR_INVALID_ARG_VALUE(
53+
'chunk',
54+
chunk,
55+
'must not be backed by a SharedArrayBuffer',
56+
);
57+
}
5058
}
5159

5260
const formatConverter = createEnumConverter('CompressionFormat', [

lib/internal/webstreams/readablestream.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ const {
4848
const {
4949
isArrayBufferView,
5050
isDataView,
51+
isSharedArrayBuffer,
5152
} = require('internal/util/types');
5253

5354
const {
@@ -988,6 +989,15 @@ class ReadableStreamBYOBReader {
988989

989990
const viewByteLength = ArrayBufferViewGetByteLength(view);
990991
const viewBuffer = ArrayBufferViewGetBuffer(view);
992+
993+
if (isSharedArrayBuffer(viewBuffer)) {
994+
throw new ERR_INVALID_ARG_VALUE(
995+
'view',
996+
view,
997+
'must not be backed by a SharedArrayBuffer',
998+
);
999+
}
1000+
9911001
const viewBufferByteLength = ArrayBufferPrototypeGetByteLength(viewBuffer);
9921002

9931003
if (viewByteLength === 0 || viewBufferByteLength === 0) {
@@ -1197,6 +1207,15 @@ class ReadableByteStreamController {
11971207
validateBuffer(chunk);
11981208
const chunkByteLength = ArrayBufferViewGetByteLength(chunk);
11991209
const chunkBuffer = ArrayBufferViewGetBuffer(chunk);
1210+
1211+
if (isSharedArrayBuffer(chunkBuffer)) {
1212+
throw new ERR_INVALID_ARG_VALUE(
1213+
'chunk',
1214+
chunk,
1215+
'must not be backed by a SharedArrayBuffer',
1216+
);
1217+
}
1218+
12001219
const chunkBufferByteLength = ArrayBufferPrototypeGetByteLength(chunkBuffer);
12011220
if (chunkByteLength === 0 || chunkBufferByteLength === 0) {
12021221
throw new ERR_INVALID_STATE.TypeError(

0 commit comments

Comments
 (0)