mirror of
https://github.com/denoland/deno.git
synced 2025-09-26 12:19:12 +00:00
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>
This commit is contained in:
parent
4855674857
commit
b2cd254c35
39 changed files with 532 additions and 906 deletions
|
@ -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(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue