diff options
author | Kenta Moriuchi <moriken@kimamass.com> | 2024-01-04 13:12:38 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-04 09:42:38 +0530 |
commit | b2cd254c35b6b1b128beea0eacdb8e814d91e003 (patch) | |
tree | d55fa5910e32d8a664aff5b680e07debea93181e /ext/web/06_streams.js | |
parent | 48556748577ba46db5f9212d14a0fcaa90d632f6 (diff) |
fix: strict type check for cross realms (#21669)
Deno v1.39 introduces `vm.runInNewContext`. This may cause problems when
using `Object.prototype.isPrototypeOf` to check built-in types.
```js
import vm from "node:vm";
const err = new Error();
const crossErr = vm.runInNewContext(`new Error()`);
console.assert( !(crossErr instanceof Error) );
console.assert( Object.getPrototypeOf(err) !== Object.getPrototypeOf(crossErr) );
```
This PR changes to check using internal slots solves them.
---
current:
```
> import vm from "node:vm";
undefined
> vm.runInNewContext(`new Error("message")`)
Error {}
> vm.runInNewContext(`new Date("2018-12-10T02:26:59.002Z")`)
Date {}
```
this PR:
```
> import vm from "node:vm";
undefined
> vm.runInNewContext(`new Error("message")`)
Error: message
at <anonymous>:1:1
> vm.runInNewContext(`new Date("2018-12-10T02:26:59.002Z")`)
2018-12-10T02:26:59.002Z
```
---------
Co-authored-by: Bartek IwaĆczuk <biwanczuk@gmail.com>
Diffstat (limited to 'ext/web/06_streams.js')
-rw-r--r-- | ext/web/06_streams.js | 104 |
1 files changed, 51 insertions, 53 deletions
diff --git a/ext/web/06_streams.js b/ext/web/06_streams.js index 65f6ac05e..49c1eb41c 100644 --- a/ext/web/06_streams.js +++ b/ext/web/06_streams.js @@ -36,7 +36,6 @@ import { const { ArrayBuffer, ArrayBufferIsView, - ArrayBufferPrototype, ArrayBufferPrototypeGetByteLength, ArrayBufferPrototypeSlice, ArrayPrototypeMap, @@ -96,6 +95,12 @@ const { WeakMapPrototypeSet, queueMicrotask, } = primordials; +const { + isAnyArrayBuffer, + isArrayBuffer, + isSharedArrayBuffer, + isTypedArray, +} = core; import { createFilteredInspectProxy } from "ext:deno_console/01_console.js"; import { assert, AssertionError } from "ext:deno_web/00_infra.js"; @@ -272,8 +277,7 @@ class Queue { * @returns {boolean} */ function isDetachedBuffer(O) { - // deno-lint-ignore prefer-primordials - if (ObjectPrototypeIsPrototypeOf(SharedArrayBuffer.prototype, O)) { + if (isSharedArrayBuffer(O)) { return false; } return ArrayBufferPrototypeGetByteLength(O) === 0 && @@ -286,11 +290,7 @@ function isDetachedBuffer(O) { */ function canTransferArrayBuffer(O) { assert(typeof O === "object"); - assert( - ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, O) || - // deno-lint-ignore prefer-primordials - ObjectPrototypeIsPrototypeOf(SharedArrayBuffer.prototype, O), - ); + assert(isAnyArrayBuffer(O)); if (isDetachedBuffer(O)) { return false; } @@ -311,8 +311,7 @@ function transferArrayBuffer(O) { * @returns {number} */ function getArrayBufferByteLength(O) { - // deno-lint-ignore prefer-primordials - if (ObjectPrototypeIsPrototypeOf(SharedArrayBuffer.prototype, O)) { + if (isSharedArrayBuffer(O)) { // TODO(petamoriken): use primordials // deno-lint-ignore prefer-primordials return O.byteLength; @@ -328,8 +327,7 @@ function getArrayBufferByteLength(O) { function cloneAsUint8Array(O) { assert(typeof O === "object"); assert(ArrayBufferIsView(O)); - if (TypedArrayPrototypeGetSymbolToStringTag(O) !== undefined) { - // TypedArray + if (isTypedArray(O)) { return TypedArrayPrototypeSlice( new Uint8Array( TypedArrayPrototypeGetBuffer(/** @type {Uint8Array} */ (O)), @@ -338,7 +336,6 @@ function cloneAsUint8Array(O) { ), ); } else { - // DataView return TypedArrayPrototypeSlice( new Uint8Array( DataViewPrototypeGetBuffer(/** @type {DataView} */ (O)), @@ -1340,15 +1337,7 @@ function readableByteStreamControllerEnqueue(controller, chunk) { } let buffer, byteLength, byteOffset; - if (TypedArrayPrototypeGetSymbolToStringTag(chunk) === undefined) { - buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (chunk)); - byteLength = DataViewPrototypeGetByteLength( - /** @type {DataView} */ (chunk), - ); - byteOffset = DataViewPrototypeGetByteOffset( - /** @type {DataView} */ (chunk), - ); - } else { + if (isTypedArray(chunk)) { buffer = TypedArrayPrototypeGetBuffer(/** @type {Uint8Array}} */ (chunk)); byteLength = TypedArrayPrototypeGetByteLength( /** @type {Uint8Array} */ (chunk), @@ -1356,6 +1345,14 @@ function readableByteStreamControllerEnqueue(controller, chunk) { byteOffset = TypedArrayPrototypeGetByteOffset( /** @type {Uint8Array} */ (chunk), ); + } else { + buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (chunk)); + byteLength = DataViewPrototypeGetByteLength( + /** @type {DataView} */ (chunk), + ); + byteOffset = DataViewPrototypeGetByteOffset( + /** @type {DataView} */ (chunk), + ); } if (isDetachedBuffer(buffer)) { @@ -1461,7 +1458,7 @@ function readableByteStreamControllerEnqueueClonedChunkToQueue( ) { let cloneResult; try { - if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, buffer)) { + if (isArrayBuffer(buffer)) { cloneResult = ArrayBufferPrototypeSlice( buffer, byteOffset, @@ -2292,11 +2289,7 @@ function readableByteStreamControllerRespondWithNewView(controller, view) { assert(controller[_pendingPullIntos].length !== 0); let buffer, byteLength, byteOffset; - if (TypedArrayPrototypeGetSymbolToStringTag(view) === undefined) { - buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (view)); - byteLength = DataViewPrototypeGetByteLength(/** @type {DataView} */ (view)); - byteOffset = DataViewPrototypeGetByteOffset(/** @type {DataView} */ (view)); - } else { + if (isTypedArray(view)) { buffer = TypedArrayPrototypeGetBuffer(/** @type {Uint8Array}} */ (view)); byteLength = TypedArrayPrototypeGetByteLength( /** @type {Uint8Array} */ (view), @@ -2304,7 +2297,12 @@ function readableByteStreamControllerRespondWithNewView(controller, view) { byteOffset = TypedArrayPrototypeGetByteOffset( /** @type {Uint8Array} */ (view), ); + } else { + buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (view)); + byteLength = DataViewPrototypeGetByteLength(/** @type {DataView} */ (view)); + byteOffset = DataViewPrototypeGetByteOffset(/** @type {DataView} */ (view)); } + assert(!isDetachedBuffer(buffer)); const firstDescriptor = controller[_pendingPullIntos][0]; const state = controller[_stream][_state]; @@ -3364,14 +3362,14 @@ function readableByteStreamTee(stream) { } if (chunk !== undefined) { let byteLength; - if (TypedArrayPrototypeGetSymbolToStringTag(chunk) === undefined) { - byteLength = DataViewPrototypeGetByteLength( - /** @type {DataView} */ (chunk), - ); - } else { + if (isTypedArray(chunk)) { byteLength = TypedArrayPrototypeGetByteLength( /** @type {Uint8Array} */ (chunk), ); + } else { + byteLength = DataViewPrototypeGetByteLength( + /** @type {DataView} */ (chunk), + ); } assert(byteLength === 0); if (!byobCanceled) { @@ -5581,16 +5579,16 @@ class ReadableStreamBYOBReader { } let buffer, byteLength; - if (TypedArrayPrototypeGetSymbolToStringTag(view) === undefined) { - buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (view)); - byteLength = DataViewPrototypeGetByteLength( - /** @type {DataView} */ (view), - ); - } else { + if (isTypedArray(view)) { buffer = TypedArrayPrototypeGetBuffer(/** @type {Uint8Array} */ (view)); byteLength = TypedArrayPrototypeGetByteLength( /** @type {Uint8Array} */ (view), ); + } else { + buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (view)); + byteLength = DataViewPrototypeGetByteLength( + /** @type {DataView} */ (view), + ); } if (byteLength === 0) { return PromiseReject( @@ -5613,7 +5611,7 @@ class ReadableStreamBYOBReader { if (options.min === 0) { return PromiseReject(new TypeError("options.min must be non-zero")); } - if (TypedArrayPrototypeGetSymbolToStringTag(view) !== undefined) { + if (isTypedArray(view)) { if (options.min > TypedArrayPrototypeGetLength(view)) { return PromiseReject( new RangeError("options.min must be smaller or equal to view's size"), @@ -5745,12 +5743,12 @@ class ReadableStreamBYOBRequest { } let buffer, byteLength; - if (TypedArrayPrototypeGetSymbolToStringTag(this[_view]) === undefined) { - buffer = DataViewPrototypeGetBuffer(this[_view]); - byteLength = DataViewPrototypeGetByteLength(this[_view]); - } else { + if (isTypedArray(this[_view])) { buffer = TypedArrayPrototypeGetBuffer(this[_view]); byteLength = TypedArrayPrototypeGetByteLength(this[_view]); + } else { + buffer = DataViewPrototypeGetBuffer(this[_view]); + byteLength = DataViewPrototypeGetByteLength(this[_view]); } if (isDetachedBuffer(buffer)) { throw new TypeError( @@ -5774,10 +5772,10 @@ class ReadableStreamBYOBRequest { } let buffer; - if (TypedArrayPrototypeGetSymbolToStringTag(view) === undefined) { - buffer = DataViewPrototypeGetBuffer(view); - } else { + if (isTypedArray(view)) { buffer = TypedArrayPrototypeGetBuffer(view); + } else { + buffer = DataViewPrototypeGetBuffer(view); } if (isDetachedBuffer(buffer)) { throw new TypeError( @@ -5864,16 +5862,16 @@ class ReadableByteStreamController { const arg1 = "Argument 1"; chunk = webidl.converters.ArrayBufferView(chunk, prefix, arg1); let buffer, byteLength; - if (TypedArrayPrototypeGetSymbolToStringTag(chunk) === undefined) { - buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (chunk)); - byteLength = DataViewPrototypeGetByteLength( - /** @type {DataView} */ (chunk), - ); - } else { + if (isTypedArray(chunk)) { buffer = TypedArrayPrototypeGetBuffer(/** @type {Uint8Array} */ (chunk)); byteLength = TypedArrayPrototypeGetByteLength( /** @type {Uint8Array} */ (chunk), ); + } else { + buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (chunk)); + byteLength = DataViewPrototypeGetByteLength( + /** @type {DataView} */ (chunk), + ); } if (byteLength === 0) { throw webidl.makeException( |