can1357/oh-my-pi · error · ArchiveError

Invalid CAB archive: CFFOLDER table is out of bounds

Error message

Invalid CAB archive: CFFOLDER table is out of bounds

What it means

The library computes where the CFFOLDER table ends: folderTableOffset (fixed header + optional reserve) + folderCount * folderRecordSize (8 + folder reserve). It requires this end to be a safe integer, to fit within the declared cabinet size, and not to run past the CFFILE table offset. Otherwise the folder table would overlap other structures or read past the file, so it throws.

Source

Thrown at packages/utils/src/ar/cab.ts:285

		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,
			parameter: type >>> 8,
			requiredSize: 0,
		});
	}
	for (const description of descriptions) {
		if (description.dataStart < folderTableEnd || description.dataStart > cabinetSize) {

View on GitHub (pinned to 9690622007)

Solutions

  1. Validate the cabinet with cabextract/7-Zip to confirm the header layout is inconsistent, then re-obtain the file.
  2. Check cFolders (offset 26), cbCFHeader reserve (offset 36 area) and coffFiles (offset 16) against each other with a hex dump.
  3. If you write CAB files, compute the folder-table end before placing the CFFILE table and ensure it fits inside cbCabinet.
  4. Reduce folder counts in generated archives; enormous folder counts usually indicate a writer bug or an attack input.
Defensive patterns

Strategy: validation

Validate before calling

const buf = new Uint8Array(await Bun.file(path).arrayBuffer());
const u32 = (o: number) => (buf[o]! | (buf[o + 1]! << 8) | (buf[o + 2]! << 16) | (buf[o + 3]! << 24)) >>> 0;
const u16 = (o: number) => buf[o]! | (buf[o + 1]! << 8);
const cbCabinet = u32(8), coffFiles = u32(16);
const folderCount = u16(26);
const flags = u16(30);
let folderTableOffset = 36;
if (flags & 0x0004) folderTableOffset += 4 + u16(36);
const end = folderTableOffset + folderCount * 8; // assumes no folder reserve
if (end > cbCabinet || end > coffFiles) throw new Error("CAB folder table would overflow the cabinet");

Try / catch

try {
	const entries = await readCab(source);
} catch (err) {
	if (err instanceof ArchiveError && err.message.includes("CFFOLDER table is out of bounds")) {
		logger.warn("Skipping CAB with inconsistent folder table", { path });
		return null;
	}
	throw err;
}

Prevention

When it happens

Trigger: Calling readCab() on a CAB whose folder count, folder reserve size, header reserve size, or offsets are inconsistent — e.g. folderCount * (8 + folderReserveSize) overflows to a non-safe integer, or the table extends beyond cbCabinet or coffFiles.

Common situations: Fuzzed archives with huge folder counts, corrupted files where the folder count or reserve fields were altered, and buggy writers that place the CFFILE table before the folder table ends.

Related errors


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