Skip to content

Commit

Permalink
fix: Forbid usage of instanceof ArrayBuffer (#7653)
Browse files Browse the repository at this point in the history
Fixes #6279
  • Loading branch information
tykus160 authored Nov 26, 2024
1 parent 79b1536 commit 55b7bd0
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 13 deletions.
42 changes: 42 additions & 0 deletions build/eslint-plugin-shaka-rules/buffersource-no-instanceof.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*! @license
* Shaka Player
* Copyright 2016 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

module.exports = {
meta: {
type: 'suggestion',
docs: {
description: 'Disallows usage of instanceof on BufferSource objects',
category: 'Best Practices',
recommended: false,
},
schema: [],
},
create: (ctx) => ({
BinaryExpression: (node) => {
const buffers = [
'ArrayBuffer',
'DataView',
'Uint8Array',
'Uint8ClampedArray',
'Int8Array',
'Uint16Array',
'Int16Array',
'Uint32Array',
'Int32Array',
'Float32Array',
'Float64Array',
];
if (node.operator === 'instanceof' && node.right.type === 'Identifier' &&
buffers.includes(node.right.name)) {
ctx.report({
node,
message: `Do not use instanceof ${node.right.name}, consider using ` +
'ArrayBuffer.isView() if possible',
});
}
},
}),
};
1 change: 1 addition & 0 deletions build/eslint-plugin-shaka-rules/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module.exports = {
const RULES = [
'arg-comment-spacing',
'array-no-instanceof',
'buffersource-no-instanceof',
'private',
];
for (const rule of RULES) {
Expand Down
6 changes: 4 additions & 2 deletions lib/cast/cast_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,12 @@ shaka.cast.CastUtils = class {
return shaka.cast.CastUtils.unpackTimeRanges_(value);
}

if (value instanceof Uint8Array) {
if (ArrayBuffer.isView(value) &&
/** @type {TypedArray} */(value).BYTES_PER_ELEMENT === 1) {
// Some of our code cares about Uint8Arrays actually being Uint8Arrays,
// so this gives them special treatment.
return shaka.cast.CastUtils.unpackUint8Array_(value);
return shaka.cast.CastUtils.unpackUint8Array_(
/** @type {!Uint8Array} */(value));
}

if (typeof value == 'number') {
Expand Down
1 change: 1 addition & 0 deletions lib/net/http_xhr_plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ shaka.net.HttpXHRPlugin = class {
};
xhr.onload = (event) => {
const headers = shaka.net.HttpXHRPlugin.headersToGenericObject_(xhr);
// eslint-disable-next-line shaka-rules/buffersource-no-instanceof
goog.asserts.assert(xhr.response instanceof ArrayBuffer,
'XHR should have a response by now!');
const xhrResponse = xhr.response;
Expand Down
18 changes: 10 additions & 8 deletions lib/util/buffer_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ shaka.util.BufferUtils = class {
* @private
*/
static unsafeGetArrayBuffer_(view) {
if (view instanceof ArrayBuffer) {
return view;
if (!ArrayBuffer.isView(view)) {
return /** @type {!ArrayBuffer} */(view);
} else {
return view.buffer;
return /** @type {!ArrayBufferView} */(view).buffer;
}
}

Expand All @@ -79,17 +79,19 @@ shaka.util.BufferUtils = class {
* @export
*/
static toArrayBuffer(view) {
if (view instanceof ArrayBuffer) {
return view;
if (!ArrayBuffer.isView(view)) {
return /** @type {!ArrayBuffer} */(view);
} else {
if (view.byteOffset == 0 && view.byteLength == view.buffer.byteLength) {
const aView = /** @type {!ArrayBufferView} */(view);
if (aView.byteOffset == 0 &&
aView.byteLength == aView.buffer.byteLength) {
// This is a TypedArray over the whole buffer.
return view.buffer;
return aView.buffer;
}
// This is a "view" on the buffer. Create a new buffer that only contains
// the data. Note that since this isn't an ArrayBuffer, the "new" call
// will allocate a new buffer to hold the copy.
return new Uint8Array(view).buffer;
return new Uint8Array(aView).buffer;
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/util/object_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ shaka.util.ObjectUtils = class {

// This covers Uint8Array and friends, even without a TypedArray
// base-class constructor.
const isTypedArray = val.buffer instanceof ArrayBuffer;
const isTypedArray = ArrayBuffer.isView(val);
if (isTypedArray) {
return val;
}
Expand Down
5 changes: 3 additions & 2 deletions lib/util/uint8array_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,9 @@ shaka.util.Uint8ArrayUtils = class {

for (let i = 0; i < varArgs.length; ++i) {
const value = varArgs[i];
if (value instanceof Uint8Array) {
result.set(value, offset);
if (ArrayBuffer.isView(value) &&
/** @type {TypedArray} */ (value).BYTES_PER_ELEMENT === 1) {
result.set(/** @type {!Uint8Array} */(value), offset);
} else {
result.set(BufferUtils.toUint8(value), offset);
}
Expand Down
1 change: 1 addition & 0 deletions test/test/util/canned_idb.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ shaka.test.CannedIDB = class {
* @private
*/
static replacer_(dummyArrayBuffers, key, value) {
// eslint-disable-next-line shaka-rules/buffersource-no-instanceof
if (value instanceof ArrayBuffer) {
/** @type {string} */
let data;
Expand Down

0 comments on commit 55b7bd0

Please sign in to comment.