can1357/oh-my-pi · error · ArchiveError
Invalid CAB archive: CFHEADER reserve area exceeds 60000 byt
Error message
Invalid CAB archive: CFHEADER reserve area exceeds 60000 bytes
What it means
When CFHEADER flags has 0x0004 set, a reserve area follows the fixed header; its header-reserve length is a 16-bit field (cbCFHeader). The CAB spec limits this to 60000 bytes, and the library enforces that ceiling to bound how far the folder table can be pushed into the file.
Source
Thrown at packages/utils/src/ar/cab.ts:279
const folderCount = readUInt16LE(fixed, 26);
const fileCount = readUInt16LE(fixed, 28);
const flags = readUInt16LE(fixed, 30);
if (flags & 0x0003) throw new ArchiveError("Unsupported multi-volume CAB archive (previous/next cabinet link)");
assertEntryCount(folderCount + fileCount, options.limits);
if (folderCount === 0 && fileCount !== 0)
throw new ArchiveError("Invalid CAB archive: files exist without a folder");
let headerReserveSize = 0;
let folderReserveSize = 0;
let dataReserveSize = 0;
let folderTableOffset = FIXED_HEADER_SIZE;
if (flags & 0x0004) {
const reserveHeader = await readExact(source, FIXED_HEADER_SIZE, FIXED_HEADER_SIZE + 4, cabinetSize);
headerReserveSize = readUInt16LE(reserveHeader, 0);
folderReserveSize = reserveHeader[2]!;
dataReserveSize = reserveHeader[3]!;
if (headerReserveSize > 60_000)
throw new ArchiveError("Invalid CAB archive: CFHEADER reserve area exceeds 60000 bytes");
folderTableOffset += 4 + headerReserveSize;
}
const folderRecordSize = 8 + folderReserveSize;
const folderTableEnd = folderTableOffset + folderCount * folderRecordSize;
if (!Number.isSafeInteger(folderTableEnd) || folderTableEnd > cabinetSize || folderTableEnd > fileTableOffset) {
throw new ArchiveError("Invalid CAB archive: CFFOLDER table is out of bounds");
}
assertIndexSize(folderTableEnd, options.limits, "CAB header");
const header = await readExact(source, 0, folderTableEnd, cabinetSize);
const descriptions: CabFolderDescription[] = [];
for (let index = 0; index < folderCount; index++) {
const offset = folderTableOffset + index * folderRecordSize;
const type = readUInt16LE(header, offset + 6);
descriptions.push({
dataStart: readUInt32LE(header, offset),
dataEnd: cabinetSize,
blockCount: readUInt16LE(header, offset + 4),
method: type & 0x000f,View on GitHub (pinned to 9690622007)
Solutions
- Treat the archive as non-conforming; obtain a compliant copy or extract it with a tolerant external tool first.
- Hex-dump the reserve size at offset 36 (two bytes, LE) and confirm whether it truly exceeds 60000.
- If produced by an in-house packer, clamp/limit the header reserve to <= 60000 bytes as the spec requires.
- If the file uses an InstallShield-style abnormal layout, extract the inner cabinet and read that instead.
Defensive patterns
Strategy: validation
Validate before calling
const buf = new Uint8Array(await Bun.file(path).arrayBuffer());
const flags = buf[30] | (buf[31]! << 8);
if (flags & 0x0004) {
const cbCFHeader = buf[36] | (buf[37]! << 8);
if (cbCFHeader > 60_000) throw new Error(`CAB header reserve ${cbCFHeader} exceeds spec limit of 60000`);
} Try / catch
try {
const entries = await readCab(source);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes("reserve area exceeds 60000")) {
throw new Error("Non-conforming CAB reserve area; use an external extraction tool", { cause: err });
}
throw err;
} Prevention
- Check the reserve size field when flags & 0x0004 is set, before parsing.
- Clamp header reserve to <= 60000 bytes in CAB-producing code.
- For InstallShield-style abnormal layouts, extract the inner cabinet first.
When it happens
Trigger: Calling readCab() on a reserved-area CAB (flags & 0x0004) whose cbCFHeader field exceeds 60000 — essentially only possible in crafted/fuzzed files or archives using the ABNORMAL reserve layout (e.g. someInstallShield variants) that exceed the spec limit.
Common situations: Malformed synthetic archives, fuzz test inputs, and rarely nonstandard packers abusing the reserve area beyond the specification's 60000-byte cap.
Related errors
- Invalid ARJ archive: too many extended headers
- Invalid CAB archive: metadata range is out of bounds
- Unable to read CAB archive: ${error instanceof Error ? error
- Invalid CAB archive: truncated data
- Invalid CAB archive: file name is not valid UTF-8
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/5ceb3c30f9ff55be.
Report an issue: GitHub.