{"record":{"id":"9a531398dfa6686e","repo":"can1357/oh-my-pi","slug":"invalid-cab-archive-cffile-table-offset-is-out-of","errorCode":null,"errorMessage":"Invalid CAB archive: CFFILE table offset is out of bounds","messagePattern":"Invalid CAB archive: CFFILE table offset is out of bounds","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/cab.ts","lineNumber":256,"sourceCode":"\t\t}\n\t\treturn folder.slice(this.#offset, end);\n\t}\n}\n\nasync function readCabArchive(source: ByteSource, options: Parameters<FormatReader>[1]): Promise<ArchiveIndexEntry[]> {\n\tif (source.size < FIXED_HEADER_SIZE) throw new ArchiveError(\"Invalid CAB archive: truncated CFHEADER\");\n\tconst fixed = await readExact(source, 0, FIXED_HEADER_SIZE);\n\tif (!hasSignature(fixed)) throw new ArchiveError(`Invalid CAB archive: expected ${CAB_SIGNATURE} signature`);\n\tif (readUInt32LE(fixed, 4) !== 0 || readUInt32LE(fixed, 12) !== 0 || readUInt32LE(fixed, 20) !== 0) {\n\t\tthrow new ArchiveError(\"Invalid CAB archive: reserved CFHEADER fields must be zero\");\n\t}\n\tconst cabinetSize = readUInt32LE(fixed, 8);\n\tif (cabinetSize < FIXED_HEADER_SIZE || cabinetSize > source.size) {\n\t\tthrow new ArchiveError(\"Invalid CAB archive: declared cabinet size is out of bounds\");\n\t}\n\tconst fileTableOffset = readUInt32LE(fixed, 16);\n\tif (fileTableOffset < FIXED_HEADER_SIZE || fileTableOffset > cabinetSize) {\n\t\tthrow new ArchiveError(\"Invalid CAB archive: CFFILE table offset is out of bounds\");\n\t}\n\tif (fixed[24] !== 3 || fixed[25] !== 1) {\n\t\tthrow new ArchiveError(`Unsupported CAB format version ${fixed[25]}.${fixed[24]} (expected 1.3)`);\n\t}\n\tconst folderCount = readUInt16LE(fixed, 26);\n\tconst fileCount = readUInt16LE(fixed, 28);\n\tconst flags = readUInt16LE(fixed, 30);\n\tif (flags & 0x0003) throw new ArchiveError(\"Unsupported multi-volume CAB archive (previous/next cabinet link)\");\n\tassertEntryCount(folderCount + fileCount, options.limits);\n\tif (folderCount === 0 && fileCount !== 0)\n\t\tthrow new ArchiveError(\"Invalid CAB archive: files exist without a folder\");\n\n\tlet headerReserveSize = 0;\n\tlet folderReserveSize = 0;\n\tlet dataReserveSize = 0;\n\tlet folderTableOffset = FIXED_HEADER_SIZE;\n\tif (flags & 0x0004) {\n\t\tconst reserveHeader = await readExact(source, FIXED_HEADER_SIZE, FIXED_HEADER_SIZE + 4, cabinetSize);","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/cab.ts#L238-L274","documentation":"The CFHEADER's coffFiles field (offset 16) points to the start of the CFFILE table. The library requires it to fall within the cabinet: at or after the fixed header and at or before the declared cabinet size. An out-of-range offset means the header's internal layout is inconsistent.","triggerScenarios":"Calling readCab() on a signed CAB whose first-file-table offset (bytes 16-19) is smaller than 36 or greater than cbCabinet — produced by corruption, a faulty writer, or deliberate malformation.","commonSituations":"Cabinets produced by non-conforming or buggy custom packers, files damaged by byte-level corruption, and hand-crafted or fuzzed inputs where the file-table pointer was miswritten.","solutions":["Treat the archive as corrupt and obtain a fresh copy; the library will not follow an untrusted offset.","Hex-dump bytes 16-19 and 8-11 and verify coffFiles lies between 36 and cbCabinet.","If a custom packer produced the file, fix its coffFiles computation to point at the first CFFILE entry.","Validate the cabinet with cabextract or 7-Zip to confirm the header is genuinely inconsistent."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const buf = new Uint8Array(await Bun.file(path).arrayBuffer());\nconst coffFiles = (buf[16] | (buf[17]! << 8) | (buf[18]! << 16) | (buf[19]! << 24)) >>> 0;\nconst cbCabinet = (buf[8] | (buf[9]! << 8) | (buf[10]! << 16) | (buf[11]! << 24)) >>> 0;\nif (coffFiles < 36 || coffFiles > cbCabinet) throw new Error(\"CAB CFFILE offset out of range; archive is corrupt\");","typeGuard":null,"tryCatchPattern":"try {\n\tconst entries = await readCab(source);\n} catch (err) {\n\tif (err instanceof ArchiveError && err.message.includes(\"CFFILE table offset is out of bounds\")) {\n\t\tlogger.warn(\"Skipping CAB with inconsistent file-table offset\", { path });\n\t\treturn null;\n\t}\n\tthrow err;\n}","preventionTips":["Validate archives from untrusted sources with an external tool before parsing.","If writing CABs, verify coffFiles points at the first CFFILE entry.","Check transfer checksums; byte corruption commonly lands in header fields."],"tags":["archive","cab","out-of-bounds","corrupt-header"],"backgroundTag":"corrupt-archive-header","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}