can1357/oh-my-pi · error · ArchiveError
Invalid CPIO archive: ${field} is too large
Error message
Invalid CPIO archive: ${field} is too large What it means
After successfully decoding all digits of a header field, parseDigits checks Number.isSafeInteger on the accumulated value and throws ArchiveError if the field exceeds Number.MAX_SAFE_INTEGER. CPIO numeric fields are fixed-width ASCII, so a pathological or hostile archive can encode values (e.g. a 16-hex-digit newc field) larger than 2^53-1; the library refuses rather than silently losing precision in sizes, offsets, or inode values.
Source
Thrown at packages/utils/src/ar/cpio.ts:117
) {
throw new ArchiveError(`Invalid CPIO archive: truncated ${what}`);
}
}
function parseDigits(bytes: Uint8Array, offset: number, length: number, radix: 8 | 16, field: string): number {
requireRange(bytes, offset, offset + length, `${field} field`);
let value = 0;
for (let index = offset; index < offset + length; index++) {
const code = bytes[index]!;
let digit: number;
if (code >= 0x30 && code <= 0x39) digit = code - 0x30;
else if (radix === 16 && code >= 0x41 && code <= 0x46) digit = code - 0x41 + 10;
else if (radix === 16 && code >= 0x61 && code <= 0x66) digit = code - 0x61 + 10;
else throw new ArchiveError(`Invalid CPIO archive: ${field} is not a valid base-${radix} number`);
if (digit >= radix) throw new ArchiveError(`Invalid CPIO archive: ${field} is not a valid base-${radix} number`);
value = value * radix + digit;
}
if (!Number.isSafeInteger(value)) throw new ArchiveError(`Invalid CPIO archive: ${field} is too large`);
return value;
}
function parseHeader(bytes: Uint8Array, offset: number): ParsedHeader {
requireRange(bytes, offset, offset + 2, "header");
const first = bytes[offset]!;
const second = bytes[offset + 1]!;
if ((first === 0xc7 && second === 0x71) || (first === 0x71 && second === 0xc7)) {
requireRange(bytes, offset, offset + BINARY_HEADER_SIZE, "old binary header");
const littleEndian = first === 0xc7;
const read16 = littleEndian ? readUInt16LE : readUInt16BE;
const read32Words = (fieldOffset: number): number =>
read16(bytes, offset + fieldOffset) * 0x10000 + read16(bytes, offset + fieldOffset + 2);
return {
headerSize: BINARY_HEADER_SIZE,
alignment: 2,
devMajor: 0,
devMinor: read16(bytes, offset + 2),View on GitHub (pinned to 9690622007)
Solutions
- Inspect the offending field bytes and re-create the archive with sane values using standard cpio tooling
- If this comes from an RPM payload, rebuild the package — real archives never have unsafe field values
- Treat the archive as untrusted/corrupt and reject it upstream; this error is a tamper indicator
- Check you are not double-reading or concatenating archives such that a later entry's digits run together
Example fix
// before: trusting an untrusted cpio blob wholesale
const entries = await readCpio(untrustedSource, options);
// after: reject obviously oversized declarations up front
if (untrustedSource.size > 2 ** 32) throw new Error('implausible archive size');
try {
const entries = await readCpio(untrustedSource, options);
} catch (e) {
if (e instanceof ArchiveError) quarantine(e);
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
// plausibility check before parsing untrusted input
if (source.size > 2 ** 32) throw new Error('archive implausibly large for a CPIO payload'); Try / catch
try {
const entries = await readCpio(source, options);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes('is too large')) {
// unsafe integer in header field: quarantine input, do not retry
} else throw err;
} Prevention
- Treat 'too large' header values from untrusted sources as tamper indicators
- Cap input size before parsing via reader limits (assertInMemorySize options)
- Avoid concatenating multiple cpio streams where trailing digits could inflate a field
- Regenerate archives with standard tooling; legit fields never exceed 32 bits
When it happens
Trigger: Parsing a newc/new ASCII CPIO whose 8-hex-char field is at its maximum (0xFFFFFFFF = 4294967295 is safe, but wider/degenerate inputs or accumulated offsets produce unsafe values) — practically, archives with absurd file sizes, name sizes, or checksums near 2^53+; crafted/fuzzed headers with all-'F' or digit-saturated fields combined with wide field interpretations.
Common situations: Maliciously crafted or fuzzed archives (security scanning pipelines); corruption that turns padding into digit bytes inflating a field; tools writing 64-bit values into fields this parser reads as wider ASCII spans.
Related errors
- Archive path cannot contain '..'
- Unsafe embedded addon archive entry: ${filename}
- Archive entry escapes extraction directory: ${archivePath}
- Archive uses offsets or sizes too large to read safely
- Corrupt compress (.Z) dictionary chain
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/a1b78f0e31ae08f0.
Report an issue: GitHub.