can1357/oh-my-pi · error · ArchiveError

Invalid CAB archive: CFFOLDER data offset is out of bounds

Error message

Invalid CAB archive: CFFOLDER data offset is out of bounds

What it means

Each CFFOLDER record declares the offset of its first data block (coffDataStart, relative to the cabinet start). After parsing all folder records, the library requires each folder's data start to lie after the folder table and within the declared cabinet size; an offset outside that window means the folder metadata points at impossible data.

Source

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

	}
	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) {
			throw new ArchiveError("Invalid CAB archive: CFFOLDER data offset is out of bounds");
		}
		for (const candidate of descriptions) {
			if (candidate.dataStart > description.dataStart && candidate.dataStart < description.dataEnd) {
				description.dataEnd = candidate.dataStart;
			}
		}
	}
	const firstDataOffset = descriptions.reduce(
		(minimum, description) => Math.min(minimum, description.dataStart),
		cabinetSize,
	);
	if (fileTableOffset > firstDataOffset)
		throw new ArchiveError("Invalid CAB archive: CFFILE table overlaps folder data");
	assertIndexSize(folderTableEnd + (firstDataOffset - fileTableOffset), options.limits, "CAB index");
	const fileTable = await readExact(source, fileTableOffset, firstDataOffset, cabinetSize);
	const folders = descriptions.map(description => new CabFolder(source, description, dataReserveSize, options.limits));
	const entries: ArchiveIndexEntry[] = [];
	let position = 0;

View on GitHub (pinned to 9690622007)

Solutions

  1. Validate with cabextract to confirm the folder records are inconsistent; replace the archive if so.
  2. Hex-dump each CFFOLDER record and verify coffDataStart falls between the end of the folder table and cbCabinet.
  3. If using a custom writer, compute data-block offsets from the actual bytes emitted (header + reserve + folder table) rather than assumed sizes.
  4. Check for byte-level corruption by comparing checksums against a known-good copy of the cabinet.
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 cbCabinet = u32(8);
// after locating the folder table at folderTableOffset with recordSize 8 + folderReserve:
// for each folder i: const dataStart = u32(folderTableOffset + i * recordSize);
// if (dataStart < folderTableEnd || dataStart > cbCabinet) throw new Error("CFFOLDER data offset out of range");

Try / catch

try {
	const entries = await readCab(source);
} catch (err) {
	if (err instanceof ArchiveError && err.message.includes("CFFOLDER data offset is out of bounds")) {
		throw new Error("CAB folder records point outside the cabinet; archive is corrupt", { cause: err });
	}
	throw err;
}

Prevention

When it happens

Trigger: Calling readCab() on a CAB where a CFFOLDER's coffDataStart (bytes 8-11 of the folder record) is smaller than the end of the folder table or greater than cbCabinet — corruption, a bad writer, or overlapping folder data pointers.

Common situations: Fuzzed archives, partially overwritten files where a folder record's data pointer was damaged, and custom CAB writers that computed data offsets incorrectly (e.g. forgetting the header reserve when laying out blocks).

Related errors


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