From ec21555d3a3308bdfd78690a771347077959848c Mon Sep 17 00:00:00 2001 From: flop Date: Wed, 13 May 2026 13:40:50 +0200 Subject: [PATCH] feat: updated parser --- ts/src/parser.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/ts/src/parser.ts b/ts/src/parser.ts index ac62c39..536609a 100644 --- a/ts/src/parser.ts +++ b/ts/src/parser.ts @@ -20,7 +20,7 @@ export class MonoDisplayParser { // File header (12 bytes) const magic = r.readUint32(); - if (magic !== MONOFORMAT_MAGIC_HEADER) throw new Error(`Bad magic 0x${magic.toString(16)} — expected 0x632B7EAF`); + if (magic !== MONOFORMAT_MAGIC_HEADER) throw new Error(`Bad magic 0x${magic.toString(16)} - expected 0x632B7EAF`); const version = r.readUint32(); if (version === 0 || version > 1) throw new Error(`Unsupported version ${version}`); @@ -36,18 +36,19 @@ export class MonoDisplayParser { const sectionStart = r.offset; // start of section DATA const dataSize = sectionSize - 4; + const sectionEnd = sectionStart + dataSize; switch (sectionType) { case SectionType.ElementsAlways: - sections.push(this.#parseElementsSection(r, SectionType.ElementsAlways, false)); + sections.push(this.#parseElementsSection(r, SectionType.ElementsAlways, false, sectionEnd)); break; case SectionType.ElementsTimespan: - sections.push(this.#parseElementsSection(r, SectionType.ElementsTimespan, true)); + sections.push(this.#parseElementsSection(r, SectionType.ElementsTimespan, true, sectionEnd)); break; case SectionType.CustomFont: sections.push(this.#parseCustomFont(r, dataSize)); break; default: - // Unknown — skip + // Unknown - skip break; } @@ -70,6 +71,7 @@ export class MonoDisplayParser { r: BinaryReader, type: SectionType.ElementsAlways | SectionType.ElementsTimespan, hasTimestamp: boolean, + sectionEnd: number, ): MonoFormatElementsAlways | MonoFormatElementsTimespan { const flags = this.#parseFlags(r.readUint16()); const numElements = r.readUint16(); @@ -82,8 +84,11 @@ export class MonoDisplayParser { const elements: MonoFormatElement[] = []; for (let i = 0; i < numElements; i++) { + // Stop if fewer than 2 bytes remain in section (can't read element type) + if (r.offset + 2 > sectionEnd) break; const el = this.#parseElement(r); - if (el) elements.push(el); + if (el === null) break; // unknown type - can't determine size, stop + elements.push(el); } if (hasTimestamp) { @@ -112,7 +117,7 @@ export class MonoDisplayParser { case ElementType.ClippedText: return this.#parseClippedText(r, elementStart); case ElementType.HScrollText: return this.#parseHScrollText(r, elementStart); default: - // Unknown element type — cannot safely skip without knowing size; stop parsing section elements + // Unknown element type - cannot safely skip without knowing size; stop parsing section elements return null; } }