From 155befb0a0e240adc331fe4b8b1967e344e5b0df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Tyczy=C5=84ski?= Date: Tue, 31 Oct 2023 14:41:25 +0100 Subject: [PATCH] fix: ban new Uint16Array(buffer) (#5838) Due to typo, banned call has been executed. Fixes typo and adds support to `Uint16Array` in `BufferUtils`. --- build/conformance.textproto | 2 +- lib/util/buffer_utils.js | 30 ++++++++++++++++++++++++++---- lib/util/fairplay_utils.js | 2 +- test/util/buffer_utils_unit.js | 2 +- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/build/conformance.textproto b/build/conformance.textproto index bd0202fbd..1698220e3 100644 --- a/build/conformance.textproto +++ b/build/conformance.textproto @@ -120,7 +120,7 @@ requirement: { "function template(a) { new Uint8ClampedArray(a) }" value: "/** @param {BufferSource} a */" - "function template(a) { new Unt16Array(a) }" + "function template(a) { new Uint16Array(a) }" value: "/** @param {BufferSource} a */" "function template(a) { new Int16Array(a) }" diff --git a/lib/util/buffer_utils.js b/lib/util/buffer_utils.js index 3b0c538de..55682752c 100644 --- a/lib/util/buffer_utils.js +++ b/lib/util/buffer_utils.js @@ -110,6 +110,23 @@ shaka.util.BufferUtils = class { return shaka.util.BufferUtils.view_(data, offset, length, Uint8Array); } + /** + * Creates a new Uint16Array view on the same buffer. This clamps the values + * to be within the same view (i.e. you can't use this to move past the end + * of the view, even if the underlying buffer is larger). However, you can + * pass a negative offset to access the data before the view. + * + * @param {BufferSource} data + * @param {number=} offset The offset from the beginning of this data's view + * to start the new view at. + * @param {number=} length The byte length of the new view. + * @return {!Uint16Array} + * @export + */ + static toUint16(data, offset = 0, length = Infinity) { + return shaka.util.BufferUtils.view_(data, offset, length, Uint16Array); + } + /** * Creates a DataView over the given buffer. * @@ -135,15 +152,20 @@ shaka.util.BufferUtils = class { */ static view_(data, offset, length, Type) { const buffer = shaka.util.BufferUtils.unsafeGetArrayBuffer_(data); + let bytesPerElement = 1; + if ('BYTES_PER_ELEMENT' in Type) { + bytesPerElement = Type.BYTES_PER_ELEMENT; + } // Absolute end of the |data| view within |buffer|. /** @suppress {strictMissingProperties} */ - const dataEnd = (data.byteOffset || 0) + data.byteLength; + const dataEnd = ((data.byteOffset || 0) + data.byteLength) / + bytesPerElement; // Absolute start of the result within |buffer|. /** @suppress {strictMissingProperties} */ - const rawStart = (data.byteOffset || 0) + offset; - const start = Math.max(0, Math.min(rawStart, dataEnd)); + const rawStart = ((data.byteOffset || 0) + offset) / bytesPerElement; + const start = Math.floor(Math.max(0, Math.min(rawStart, dataEnd))); // Absolute end of the result within |buffer|. - const end = Math.min(start + Math.max(length, 0), dataEnd); + const end = Math.floor(Math.min(start + Math.max(length, 0), dataEnd)); return new Type(buffer, start, end - start); } }; diff --git a/lib/util/fairplay_utils.js b/lib/util/fairplay_utils.js index dcc016b5a..4e0529fd9 100644 --- a/lib/util/fairplay_utils.js +++ b/lib/util/fairplay_utils.js @@ -205,7 +205,7 @@ shaka.util.FairPlayUtils = class { const stringToArray = (string) => { // 2 bytes for each char const buffer = new ArrayBuffer(string.length * 2); - const array = new Uint16Array(buffer); + const array = shaka.util.BufferUtils.toUint16(buffer); for (let i = 0, strLen = string.length; i < strLen; i++) { array[i] = string.charCodeAt(i); } diff --git a/test/util/buffer_utils_unit.js b/test/util/buffer_utils_unit.js index a43f60d4b..e477cbe46 100644 --- a/test/util/buffer_utils_unit.js +++ b/test/util/buffer_utils_unit.js @@ -42,7 +42,7 @@ describe('BufferUtils', () => { it('compares with same buffer', () => { const a = new Uint8Array([0, 1, 2, 3]); - const b = new Uint16Array(a.buffer); + const b = BufferUtils.toUint16(a); expect(BufferUtils.equal(a, b)).toBe(true); });