{"record":{"id":"379cd71a57031492","repo":"can1357/oh-my-pi","slug":"invalid-cab-archive-files-exist-without-a-folder","errorCode":null,"errorMessage":"Invalid CAB archive: files exist without a folder","messagePattern":"Invalid CAB archive: files exist without a folder","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/cab.ts","lineNumber":267,"sourceCode":"\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);\n\t\theaderReserveSize = readUInt16LE(reserveHeader, 0);\n\t\tfolderReserveSize = reserveHeader[2]!;\n\t\tdataReserveSize = reserveHeader[3]!;\n\t\tif (headerReserveSize > 60_000)\n\t\t\tthrow new ArchiveError(\"Invalid CAB archive: CFHEADER reserve area exceeds 60000 bytes\");\n\t\tfolderTableOffset += 4 + headerReserveSize;\n\t}\n\tconst folderRecordSize = 8 + folderReserveSize;\n\tconst folderTableEnd = folderTableOffset + folderCount * folderRecordSize;\n\tif (!Number.isSafeInteger(folderTableEnd) || folderTableEnd > cabinetSize || folderTableEnd > fileTableOffset) {\n\t\tthrow new ArchiveError(\"Invalid CAB archive: CFFOLDER table is out of bounds\");","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/cab.ts#L249-L285","documentation":"A CAB must contain at least one CFFOLDER for its CFFILE entries to belong to; every file entry references a folder index. The library rejects a cabinet that declares zero folders while still declaring one or more files, since such a file count is internally inconsistent.","triggerScenarios":"Calling readCab() on a signed CAB whose cFolders (offset 26) is 0 while cFiles (offset 28) is greater than 0 — a header inconsistency from corruption or a malformed writer.","commonSituations":"Hand-crafted or fuzzed archives, corrupted files where the folder count byte was zeroed, and buggy custom CAB writers that forgot to emit the (at least one) folder record.","solutions":["Verify the archive with cabextract; an inconsistent header means the file should be re-obtained.","If you write CAB files, always emit at least one CFFOLDER record and set cFolders accordingly.","Check whether the file was damaged in transit by comparing checksums with the original source.","An empty-but-valid cabinet should have cFolders >= 1 and cFiles = 0; if you intend an empty archive, fix the writer."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const buf = new Uint8Array(await Bun.file(path).arrayBuffer());\nconst folderCount = buf[26] | (buf[27]! << 8);\nconst fileCount = buf[28] | (buf[29]! << 8);\nif (folderCount === 0 && fileCount !== 0) throw new Error(\"Inconsistent CAB: files declared without any folder\");","typeGuard":null,"tryCatchPattern":"try {\n\tconst entries = await readCab(source);\n} catch (err) {\n\tif (err instanceof ArchiveError && err.message.includes(\"files exist without a folder\")) {\n\t\tthrow new Error(\"CAB header is internally inconsistent; archive is corrupt\", { cause: err });\n\t}\n\tthrow err;\n}","preventionTips":["Sanity-check cFolders >= 1 whenever cFiles > 0 before parsing.","Fix CAB writers to always emit at least one CFFOLDER record.","Validate suspicious archives with cabextract before processing."],"tags":["archive","cab","corrupt-header","file-format"],"backgroundTag":"corrupt-archive-header","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}