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

  1. Treat the archive as non-conforming; obtain a compliant copy or extract it with a tolerant external tool first.
  2. Hex-dump the reserve size at offset 36 (two bytes, LE) and confirm whether it truly exceeds 60000.
  3. If produced by an in-house packer, clamp/limit the header reserve to <= 60000 bytes as the spec requires.
  4. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/5ceb3c30f9ff55be. Report an issue: GitHub.