Skip to content

Commit

Permalink
Add strict type checking for Uint8Array/ArrayBuffer (#5849)
Browse files Browse the repository at this point in the history
* Add strict type checking for Uint8Array/ArrayBuffer and fix errors
* Avoid copying by creating new Uint8Array with TypedArray view as input
  • Loading branch information
robwalch authored Dec 3, 2024
1 parent 733e48c commit c2c4921
Show file tree
Hide file tree
Showing 10 changed files with 30 additions and 16 deletions.
3 changes: 3 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ module.exports = {
},
overrides: [
{
parserOptions: {
project: ['./tsconfig.json'],
},
files: ['*.ts'],
rules: {
'no-unused-vars': 0,
Expand Down
2 changes: 1 addition & 1 deletion src/controller/audio-stream-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ class AudioStreamController
if (this.initPTS[frag.cc] !== undefined) {
this.waitingData = null;
this.state = State.FRAG_LOADING;
const payload = cache.flush();
const payload = cache.flush().buffer;
const data: FragLoadedData = {
frag,
part,
Expand Down
12 changes: 6 additions & 6 deletions src/controller/eme-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ class EMEController extends Logger implements ComponentAPI {
this.generateRequestWithPreferredKeySession(
keySessionContext,
scheme,
decryptdata.pssh,
decryptdata.pssh.buffer,
'expired',
);
} else {
Expand Down Expand Up @@ -449,10 +449,11 @@ class EMEController extends Logger implements ComponentAPI {
const keySessionContextPromise = (this.keyIdToKeySessionPromise[keyId] =
keyContextPromise.then((keySessionContext) => {
const scheme = 'cenc';
const initData = decryptdata.pssh ? decryptdata.pssh.buffer : null;
return this.generateRequestWithPreferredKeySession(
keySessionContext,
scheme,
decryptdata.pssh,
initData,
'playlist-key',
);
}));
Expand Down Expand Up @@ -545,7 +546,7 @@ class EMEController extends Logger implements ComponentAPI {
const json = bin2str(new Uint8Array(initData));
try {
const sinf = base64Decode(JSON.parse(json).sinf);
const tenc = parseSinf(new Uint8Array(sinf));
const tenc = parseSinf(sinf);
if (!tenc) {
throw new Error(
`'schm' box missing or not cbcs/cenc with schi > tenc`,
Expand Down Expand Up @@ -730,9 +731,8 @@ class EMEController extends Logger implements ComponentAPI {
);
}
initDataType = mappedInitData.initDataType;
initData = context.decryptdata.pssh = mappedInitData.initData
? new Uint8Array(mappedInitData.initData)
: null;
initData = mappedInitData.initData ? mappedInitData.initData : null;
context.decryptdata.pssh = initData ? new Uint8Array(initData) : null;
} catch (error) {
this.warn(error.message);
if (this.hls?.config.debug) {
Expand Down
2 changes: 1 addition & 1 deletion src/controller/timeline-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ export class TimelineController implements ComponentAPI {
const hls = this.hls;
// Parse the WebVTT file contents.
const payloadWebVTT = frag.initSegment?.data
? appendUint8Array(frag.initSegment.data, new Uint8Array(payload))
? appendUint8Array(frag.initSegment.data, new Uint8Array(payload)).buffer
: payload;
parseWebVTT(
payloadWebVTT,
Expand Down
3 changes: 2 additions & 1 deletion src/crypt/decrypter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ export default class Decrypter {
): Promise<ArrayBuffer> {
if (this.useSoftware) {
return new Promise((resolve, reject) => {
this.softwareDecrypt(new Uint8Array(data), key, iv, aesMode);
const dataView = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
this.softwareDecrypt(dataView, key, iv, aesMode);
const decryptResult = this.flush();
if (decryptResult) {
resolve(decryptResult.buffer);
Expand Down
2 changes: 1 addition & 1 deletion src/demux/chunk-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default class ChunkCache {

flush(): Uint8Array {
const { chunks, dataLength } = this;
let result;
let result: Uint8Array;
if (!chunks.length) {
return new Uint8Array(0);
} else if (chunks.length === 1) {
Expand Down
5 changes: 3 additions & 2 deletions src/demux/transmuxer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ export default class Transmuxer {
// For Low-Latency HLS Parts, decrypt in place, since part parsing is expected on push progress
const loadingParts = chunkMeta.part > -1;
if (loadingParts) {
decryptedData = decrypter.flush();
const data = decrypter.flush();
decryptedData = data ? data.buffer : data;
}
if (!decryptedData) {
stats.executeEnd = now();
Expand Down Expand Up @@ -248,7 +249,7 @@ export default class Transmuxer {
if (decryptedData) {
// Push always returns a TransmuxerResult if decryptdata is null
transmuxResults.push(
this.push(decryptedData, null, chunkMeta) as TransmuxerResult,
this.push(decryptedData.buffer, null, chunkMeta) as TransmuxerResult,
);
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/types/buffer.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
declare global {
interface ArrayBuffer {
' buffer_kind'?: 'array';
}
interface Uint8Array {
' buffer_kind'?: 'uint8';
}
}

export type SourceBufferName = 'video' | 'audio' | 'audiovideo';

/* eslint-disable no-restricted-globals */
Expand Down
6 changes: 3 additions & 3 deletions src/utils/fetch-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ class FetchLoader implements Loader<LoaderContext> {
.then((data) => {
if (data.done) {
if (chunkCache.dataLength) {
onProgress(stats, context, chunkCache.flush(), response);
onProgress(stats, context, chunkCache.flush().buffer, response);
}

return Promise.resolve(new ArrayBuffer(0));
Expand All @@ -251,12 +251,12 @@ class FetchLoader implements Loader<LoaderContext> {
chunkCache.push(chunk);
if (chunkCache.dataLength >= highWaterMark) {
// flush in order to join the typed arrays
onProgress(stats, context, chunkCache.flush(), response);
onProgress(stats, context, chunkCache.flush().buffer, response);
}
} else {
// If there's nothing cached already, and the chache is large enough
// just emit the progress event
onProgress(stats, context, chunk, response);
onProgress(stats, context, chunk.buffer, response);
}
return pump();
})
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/demuxer/transmuxer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ describe('TransmuxerInterface tests', function () {
newFrag.level = 2;
newFrag.start = 1000;
const part = null;
const data = new Uint8Array(new ArrayBuffer(8));
const data = new ArrayBuffer(8);
const initSegmentData = new Uint8Array(0);
const audioCodec = '';
const videoCodec = '';
Expand Down

0 comments on commit c2c4921

Please sign in to comment.