can1357/oh-my-pi · error · ArchiveError
LZH uses sizes too large to read safely
Error message
LZH uses sizes too large to read safely
What it means
u64 combines two 32-bit little-endian words into a JS number; if the result exceeds Number.MAX_SAFE_INTEGER, sizes can no longer be compared or used for allocation safely. The library throws rather than proceeding with an imprecise size.
Source
Thrown at packages/utils/src/ar/lzh.ts:292
function crc16WithZeroRange(bytes: Uint8Array, zeroStart: number, zeroEnd: number): number {
if (zeroStart < 0) return crc16Arc(bytes);
let value = crc16Arc(bytes.subarray(0, zeroStart));
value = crc16Arc(ZERO_CRC16_BYTES.subarray(0, zeroEnd - zeroStart), value);
return crc16Arc(bytes.subarray(zeroEnd), value);
}
function u16(bytes: Uint8Array, offset: number): number {
return bytes[offset]! | (bytes[offset + 1]! << 8);
}
function u32(bytes: Uint8Array, offset: number): number {
return (bytes[offset]! | (bytes[offset + 1]! << 8) | (bytes[offset + 2]! << 16) | (bytes[offset + 3]! << 24)) >>> 0;
}
function u64(bytes: Uint8Array, offset: number): number {
const value = u32(bytes, offset) + u32(bytes, offset + 4) * 0x100000000;
if (!Number.isSafeInteger(value)) throw new ArchiveError("LZH uses sizes too large to read safely");
return value;
}
function assertRange(bytes: Uint8Array, start: number, end: number, what: string): void {
if (
!Number.isSafeInteger(start) ||
!Number.isSafeInteger(end) ||
start < 0 ||
end < start ||
end > bytes.byteLength
) {
throw new ArchiveError(`Invalid LZH archive: truncated ${what}`);
}
}
function decodeLegacy(bytes: Uint8Array): string {
let end = bytes.indexOf(0);
if (end < 0) end = bytes.byteLength;View on GitHub (pinned to 9690622007)
Solutions
- Check the extended-header offset/length parsing before the u64 read
- Re-validate the archive (CRC) and re-download
- Treat as corrupt: catch ArchiveError and skip the entry
Defensive patterns
Strategy: try-catch
Validate before calling
// Reject implausible sizes before header processing
if (packed.length < 12) throw new Error("archive too small for extended header"); Try / catch
try {
const entries = readArchive(packed);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes("too large")) {
// header offsets are likely wrong or the file is corrupt
return null;
}
throw err;
} Prevention
- Verify extended-header chain offsets before reading 64-bit size fields
- Check archive integrity (CRC) first
- Treat absurd sizes as corruption, not valid input
When it happens
Trigger: processExtendedHeader reading a 64-bit size field (common in modern LZH extended headers) whose value exceeds ~9 PB — practically always corrupt/misaligned data rather than a genuine size.
Common situations: Extended-header parsing at a wrong offset so garbage is read as the high 32 bits; fuzzed archives; very old archives misinterpreted as 64-bit sizes.
Related errors
- Invalid ${label} Huffman table: oversubscribed codes
- Invalid ${label} Huffman table: incomplete codes
- Invalid ${label} Huffman table: prefix collision
- Invalid ${label} Huffman table: duplicate code
- Invalid ${this.#label} Huffman code
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/920b670ca2837493.
Report an issue: GitHub.