From 4819bf67552ade2da35123459a674a063fd9af73 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Fri, 26 Sep 2025 10:01:20 +0200 Subject: [PATCH] Fix udta string box being read when the field was non-string, fix out of bounds string read (fixes #150) --- package-lock.json | 12 ++++++------ package.json | 2 +- packages/mp3-encoder/package.json | 2 +- src/isobmff/isobmff-demuxer.ts | 17 +++-------------- src/isobmff/isobmff-reader.ts | 4 +++- src/reader.ts | 8 +++++++- 6 files changed, 21 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4b74941..4eb8c70 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediabunny", - "version": "1.20.0", + "version": "1.20.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mediabunny", - "version": "1.20.0", + "version": "1.20.1", "license": "MPL-2.0", "workspaces": [ "packages/*" @@ -7749,9 +7749,9 @@ } }, "node_modules/mediabunny": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.19.1.tgz", - "integrity": "sha512-nyaxskRhj7w634RZ/D0+xbc//nclDVBM1eG9hrrPL/lEG4PW1pBSRHsgPRXQX/PvUXNfJTYQsTl0SYFCrch9PA==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.20.0.tgz", + "integrity": "sha512-5IQYSiFd1fkx/GQEu/hHF08eolDjJnJ/qdOVRdal54kqHPpN3MILFRVJoJ+CkczYVfuGAHkgs/qYtrUcWEvStA==", "license": "MPL-2.0", "peer": true, "workspaces": [ @@ -12242,7 +12242,7 @@ }, "packages/mp3-encoder": { "name": "@mediabunny/mp3-encoder", - "version": "1.20.0", + "version": "1.20.1", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" diff --git a/package.json b/package.json index 0bc543a..b4c2b3c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mediabunny", "author": "Vanilagy", - "version": "1.20.0", + "version": "1.20.1", "description": "Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.", "type": "module", "workspaces": [ diff --git a/packages/mp3-encoder/package.json b/packages/mp3-encoder/package.json index 274cd6d..b26480c 100644 --- a/packages/mp3-encoder/package.json +++ b/packages/mp3-encoder/package.json @@ -1,7 +1,7 @@ { "name": "@mediabunny/mp3-encoder", "author": "Vanilagy", - "version": "1.20.0", + "version": "1.20.1", "description": "MP3 encoder extension for Mediabunny, based on LAME.", "main": "./dist/bundles/mediabunny-mp3-encoder.mjs", "module": "./dist/bundles/mediabunny-mp3-encoder.mjs", diff --git a/src/isobmff/isobmff-demuxer.ts b/src/isobmff/isobmff-demuxer.ts index 16aa9a5..903e41f 100644 --- a/src/isobmff/isobmff-demuxer.ts +++ b/src/isobmff/isobmff-demuxer.ts @@ -90,19 +90,6 @@ import { } from '../reader'; import { MetadataTags, RichImageData } from '../tags'; -// https://exiftool.org/TagNames/QuickTime.html -const UDTA_STRING_KEYS = new Set([ - '@day', '@mak', '@mod', '@swr', '@xyz', 'CAME', 'CNCV', 'CNFV', 'CNMN', 'FIRM', 'FOV\0', 'GoPr', 'LENS', 'PXMN', - 'SIGM', 'SNum', 'TAGS', 'albm', 'albr', 'angl', 'auth', 'ccid', 'cdis', 'clfn', 'clid', 'clsf', 'cmid', 'cmnm', - 'coll', 'cprt', 'cver', 'cvru', 'date', 'dscp', 'fsid', 'gnre', 'hinv', 'icnu', 'info', 'infu', 'kgtt', 'loci', - 'lrcu', 'mcvr', 'name', 'perf', 'pmcc', 'reel', 'rtng', 'scen', 'shot', 'slno', 'thmb', 'titl', 'tnam', 'urat', - 'uuid', 'vndr', 'yrrc', '©ART', '©TIM', '©TSC', '©TSZ', '©alb', '©arg', '©ark', '©cmt', '©cok', '©com', '©cpy', - '©day', '©dir', '©ed1', '©ed2', '©ed3', '©ed4', '©ed5', '©ed6', '©ed7', '©ed8', '©ed9', '©enc', '©fmt', '©fpt', - '©frl', '©fyw', '©gen', '©gpt', '©grl', '©grp', '©gyw', '©inf', '©isr', '©lab', '©lal', '©lyr', '©mak', '©mal', - '©mdl', '©mod', '©nam', '©pdk', '©phg', '©prd', '©prf', '©prk', '©prl', '©req', '©snk', '©snm', '©src', '©swf', - '©swk', '©swr', '©too', '©trk', '©wrt', '©xsp', '©xyz', '©ysp', '©zsp', -]); - type InternalTrack = { id: number; demuxer: IsobmffDemuxer; @@ -2065,7 +2052,9 @@ export class IsobmffDemuxer extends Demuxer { const startPos = slice.filePos; this.metadataTags.raw ??= {}; - if (UDTA_STRING_KEYS.has(boxInfo.name)) { + if (boxInfo.name[0] === '©') { + // https://mp4workshop.com/about + // Box name starting with © indicates "international text" this.metadataTags.raw[boxInfo.name] ??= readMetadataStringShort(slice); } else { this.metadataTags.raw[boxInfo.name] ??= readBytes(slice, boxInfo.contentSize); diff --git a/src/isobmff/isobmff-reader.ts b/src/isobmff/isobmff-reader.ts index 584a0a8..f3090a1 100644 --- a/src/isobmff/isobmff-reader.ts +++ b/src/isobmff/isobmff-reader.ts @@ -57,8 +57,10 @@ export const readIsomVariableInteger = (slice: FileSlice) => { }; export const readMetadataStringShort = (slice: FileSlice) => { - const stringLength = readU16Be(slice); + let stringLength = readU16Be(slice); slice.skip(2); // Language + + stringLength = Math.min(stringLength, slice.remainingLength); return textDecoder.decode(readBytes(slice, stringLength)); }; diff --git a/src/reader.ts b/src/reader.ts index 6c30f3c..ebcda44 100644 --- a/src/reader.ts +++ b/src/reader.ts @@ -129,6 +129,11 @@ export class FileSlice { this.bufferPos = value - this.offset; } + /** The number of bytes left from the current pos to the end of the slice. */ + get remainingLength() { + return Math.max(this.end - this.filePos, 0); + } + skip(byteCount: number) { this.bufferPos += byteCount; } @@ -153,7 +158,8 @@ const checkIsInRange = (slice: FileSlice, bytesToRead: number) => { if (slice.filePos < slice.start || slice.filePos + bytesToRead > slice.end) { throw new RangeError( `Tried reading [${slice.filePos}, ${slice.filePos + bytesToRead}), but slice is` - + ` [${slice.start}, ${slice.end}).`, + + ` [${slice.start}, ${slice.end}). This is likely an internal error, please report it alongside the file` + + ` that caused it.`, ); } };