{"record":{"id":"f246e5e36fe06ee5","repo":"can1357/oh-my-pi","slug":"archive-is-too-large-to-read-safely","errorCode":null,"errorMessage":"Archive is too large to read safely","messagePattern":"Archive is too large to read safely","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/limits.ts","lineNumber":38,"sourceCode":"\t/** Max byte length of a member path or link target. */\n\tmaxPathBytes: number;\n\t/** Max symlink rewrites while resolving one path. */\n\tmaxLinkDepth: number;\n}\n\nexport const DEFAULT_ARCHIVE_LIMITS: ArchiveLimits = {\n\tmaxEntries: 1_000_000,\n\tmaxInMemorySize: 256 * 1024 * 1024,\n\tmaxIndexSize: 64 * 1024 * 1024,\n\tmaxMemberSize: 64 * 1024 * 1024,\n\tmaxPathBytes: 4096,\n\tmaxLinkDepth: 40,\n};\n\n/** Reject an archive that would be fully materialized beyond `maxInMemorySize`. */\nexport function assertInMemorySize(size: number, limits: ArchiveLimits): void {\n\tif (!Number.isSafeInteger(size) || size < 0) {\n\t\tthrow new ArchiveError(\"Archive is too large to read safely\");\n\t}\n\tif (size > limits.maxInMemorySize) {\n\t\tthrow new ArchiveError(\n\t\t\t`Archive is too large to read in memory (${formatBytes(size)} > ${formatBytes(limits.maxInMemorySize)} limit)`,\n\t\t);\n\t}\n}\n\n/** Reject archive metadata (index/header) beyond `maxIndexSize`. */\nexport function assertIndexSize(size: number, limits: ArchiveLimits, what: string): void {\n\tif (!Number.isSafeInteger(size) || size < 0) {\n\t\tthrow new ArchiveError(`Invalid archive: ${what} has an invalid size`);\n\t}\n\tif (size > limits.maxIndexSize) {\n\t\tthrow new ArchiveError(\n\t\t\t`Archive ${what} is too large (${formatBytes(size)} > ${formatBytes(limits.maxIndexSize)} limit)`,\n\t\t);\n\t}","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/limits.ts#L20-L56","documentation":"assertInMemorySize guards every reader that must fully materialize an archive (arj, cab, cpio, deb tar members, etc.). This variant fires when the claimed size is not a safe non-negative integer — a corrupted size field, integer overflow, or garbage metadata — so the size itself is untrustworthy and reading would be unsafe even before comparing against the configured limit.","triggerScenarios":"Calling any buffer-materializing archive reader (readArj, readCabArchive, readCpio, readDeb's decompressDebTar, etc.) when a size value fed to assertInMemorySize is NaN, negative, or exceeds Number.MAX_SAFE_INTEGER — typically from a corrupted header/length field or bad arithmetic on offsets.","commonSituations":"Corrupt or truncated archive headers, malicious archives with overflowed 64-bit size fields, files larger than ~9 petabytes mis-parsed due to field-width bugs, or a caller passing wrong limits/offsets causing bogus computed sizes.","solutions":["Verify the archive's integrity (checksum) and re-obtain a good copy; the size field is almost certainly corrupt","Check the archive header manually to see whether the declared size is sane (compare with actual file size)","Validate/re-encode the archive with its native tooling (cabextract -l, cpio -it < file) to detect structural damage","If you feed computed sizes yourself (offsets/lengths), audit that arithmetic for overflow or unit errors"],"exampleFix":"// before: size read from corrupt header\nawait readCpio(bytes); // ArchiveError: Archive is too large to read safely\n// after: sanity-check before reading\nconst headerSize = readSizeField(bytes);\nif (!Number.isSafeInteger(headerSize) || headerSize < 0 || headerSize > bytes.byteLength * 8) {\n  throw new Error('implausible archive size field');\n}\nawait readCpio(bytes);","handlingStrategy":"validation","validationCode":"function plausibleSize(size, fileBytes) {\n  return Number.isSafeInteger(size) && size >= 0 && size <= fileBytes * 16; // inflate headroom\n}\n// call readers only after validating header-derived sizes\nif (!plausibleSize(headerSize, bytes.byteLength)) throw new Error('corrupt size field');","typeGuard":"function isSafeSize(size) {\n  return typeof size === 'number' && Number.isSafeInteger(size) && size >= 0;\n}","tryCatchPattern":"try {\n  entries = await readCabArchive(buf);\n} catch (err) {\n  if (err instanceof ArchiveError && err.message === 'Archive is too large to read safely') {\n    // corrupt/overflowed size field -> treat as corrupt archive\n  } else throw err;\n}","preventionTips":["Validate archive headers/checksums before reading untrusted files","Never feed sizes you computed with unchecked arithmetic","Distinguish this 'unsafe size' error from the limit-exceeded variant when triaging"],"tags":["archive","limits","memory","corrupt-header"],"backgroundTag":"archive-size-limit","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}