can1357/oh-my-pi · error · ArchiveError
Invalid CPIO archive: mode exceeds 16 bits
Error message
Invalid CPIO archive: mode exceeds 16 bits
What it means
readCpioEntriesFromBuffer validates each parsed header's mode against the 16-bit POSIX file-mode space and throws ArchiveError if mode > 0xFFFF. Old-binary headers read mode as a 16-bit value (cannot exceed), so in practice this fires on ASCII formats where a corrupt or hostile 8-hex-digit field encodes a value beyond 0xFFFF — indicating a corrupt header or tampered archive.
Source
Thrown at packages/utils/src/ar/cpio.ts:226
const portableTarget = rawTarget.replace(/\\/g, "/");
if (path.posix.isAbsolute(portableTarget)) return { path: portableTarget, resolveTarget: false };
const normalized = normalizeArchiveLookupPath(path.posix.join(path.posix.dirname(recordPath), portableTarget));
return normalized === undefined
? { path: portableTarget, resolveTarget: false }
: { path: normalized, resolveTarget: true };
}
/** Parse an already-materialized CPIO stream for direct and RPM-composed readers. */
export function readCpioEntriesFromBuffer(bytes: Uint8Array, options: FormatReadOptions): ArchiveIndexEntry[] {
assertInMemorySize(bytes.byteLength, options.limits);
const records: ParsedRecord[] = [];
let offset = 0;
let metadataSize = 0;
let foundTrailer = false;
while (offset < bytes.byteLength) {
const header = parseHeader(bytes, offset);
if (header.mode > 0xffff) throw new ArchiveError("Invalid CPIO archive: mode exceeds 16 bits");
if (header.nameSize < 1) throw new ArchiveError("Invalid CPIO archive: name size must include a NUL terminator");
assertArchivePathBytes(header.nameSize - 1, "member path", options.limits.maxPathBytes);
assertArchiveMemberSize(header.fileSize, "(CPIO entry)", options.limits);
const nameStart = offset + header.headerSize;
const nameEnd = nameStart + header.nameSize;
const dataOffset = align(nameEnd, header.alignment);
const dataEnd = dataOffset + header.fileSize;
const nextOffset = align(dataEnd, header.alignment);
requireRange(bytes, nameStart, nameEnd, "member name");
requireRange(bytes, dataOffset, dataEnd, "member data");
requireRange(bytes, dataEnd, nextOffset, "member padding");
if (bytes[nameEnd - 1] !== 0) throw new ArchiveError("Invalid CPIO archive: member name is not NUL-terminated");
for (let index = nameStart; index < nameEnd - 1; index++) {
if (bytes[index] === 0) throw new ArchiveError("Invalid CPIO archive: member name contains an embedded NUL");
}
validateZeroPadding(bytes, nameEnd, dataOffset, "name");
validateZeroPadding(bytes, dataEnd, nextOffset, "data");View on GitHub (pinned to 9690622007)
Solutions
- Rebuild the archive with a standard tool so mode fields contain conventional 16-bit permission/type values
- Fix a custom writer to mask mode to 0o7777 | file-type bits (e.g. mode & 0o1707777 → but emit ≤ 0xFFFF)
- Verify archive integrity (checksum) — this error usually means the mode field bytes are corrupt
- Treat untrusted archives triggering this as rejected input in your ingestion pipeline
Example fix
// before: writer emits 32-bit mode header.write(mode.toString(16).padStart(8, '0'), MODE_OFFSET, 'ascii'); // after: clamp to 16-bit st_mode space const m16 = mode & 0xffff; header.write(m16.toString(16).padStart(8, '0'), MODE_OFFSET, 'ascii');
Defensive patterns
Strategy: try-catch
Try / catch
try {
const entries = await readCpio(source, options);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes('mode exceeds 16 bits')) {
// corrupt/hostile header: reject the archive rather than retry
} else throw err;
} Prevention
- Custom writers must emit mode as 16-bit permission+type bits (≤ 0xFFFF)
- Treat this error on untrusted input as tampering and quarantine the archive
- Verify archive checksums to catch corruption in the mode field
- Regenerate archives with standard tooling
When it happens
Trigger: Parsing a newc ('070701'/'070702') archive whose mode field hex value exceeds FFFF, e.g. all-'F' fields or corruption shifting digit bytes into the mode slot; crafted archives from fuzzing/security tooling.
Common situations: Fuzzed or maliciously crafted archives; byte corruption in transit; custom writers emitting 32-bit mode words (including high flags) into the mode field instead of the standard permission+type bits.
Related errors
- CPIO member '${memberPath}' has an inconsistent declared siz
- Invalid CPIO archive: name size must include a NUL terminato
- Unsupported ACP mode: ${modeId}
- Invalid ARJ ${field}: missing terminator
- Invalid ARJ local header
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/60aa88429a3300cd.
Report an issue: GitHub.