{"record":{"id":"5c4540cbab0ef635","repo":"can1357/oh-my-pi","slug":"invalid-tar-numeric-field","errorCode":null,"errorMessage":"Invalid tar numeric field","messagePattern":"Invalid tar numeric field","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/tar.ts","lineNumber":115,"sourceCode":"\t\tbytesMatchAscii(buffer, offset + MAGIC_OFFSET, MAGIC) && bytesMatchAscii(buffer, offset + VERSION_OFFSET, VERSION)\n\t);\n}\n\nfunction readMetadataPath(data: Uint8Array, field: string, limits: ArchiveLimits): string {\n\tconst nul = data.indexOf(0);\n\tconst value = data.subarray(0, nul === -1 ? data.byteLength : nul);\n\tassertArchivePathBytes(value.byteLength, field, limits.maxPathBytes);\n\treturn TEXT_DECODER.decode(value);\n}\n\nfunction readPaxPath(data: Uint8Array, field: string, limits: ArchiveLimits): string {\n\tassertArchivePathBytes(data.byteLength, field, limits.maxPathBytes);\n\treturn TEXT_DECODER.decode(data);\n}\n\nfunction readTarNumeric(buffer: Uint8Array, offset: number, length: number): number {\n\tif (offset < 0 || length <= 0 || offset + length > buffer.byteLength) {\n\t\tthrow new ArchiveError(\"Invalid tar numeric field\");\n\t}\n\tconst first = buffer[offset]!;\n\tlet value = 0n;\n\tif ((first & 0x80) !== 0) {\n\t\tvalue = BigInt(first & 0x7f);\n\t\tfor (let index = 1; index < length; index++) {\n\t\t\tvalue = (value << 8n) | BigInt(buffer[offset + index]!);\n\t\t}\n\t\tif ((first & 0x40) !== 0) value -= 1n << BigInt(length * 8 - 1);\n\t} else {\n\t\tfor (let index = 0; index < length; index++) {\n\t\t\tconst byte = buffer[offset + index]!;\n\t\t\tif (byte >= 0x30 && byte <= 0x37) value = value * 8n + BigInt(byte - 0x30);\n\t\t}\n\t}\n\treturn Number(value);\n}\n","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/tar.ts#L97-L133","documentation":"readTarNumeric decodes tar header numeric fields (octal text or GNU base-256 binary) from the archive buffer. This throw means the requested field does not fit inside the buffer at all (negative offset, non-positive length, or offset+length past the end of the bytes). The library throws instead of reading out-of-bounds because the header block is truncated or the caller supplied a bad offset.","triggerScenarios":"Calling readTarNumeric (via the size/stored/mtime/rawMode accessors of a tar member) on a buffer shorter than the field requires — e.g. a buffer < 512 bytes passed where a full tar header block is expected, or an offset computed past buffer end.","commonSituations":"Feeding a truncated download (partial tar), a buffer sliced at the wrong offset, sniffing a file smaller than one 512-byte block, or passing non-tar bytes to a helper that trusts a size field.","solutions":["Verify the input is a complete tar buffer (at least one 512-byte block) before parsing; use sniffTar to detect the format first.","Check where the offset/length arguments come from — an earlier miscomputed size or offset in your own code is the usual culprit.","Re-download or re-extract the archive; a truncated file cannot be repaired by the parser.","Wrap the parse in try-catch on ArchiveError and surface 'corrupt/truncated tar archive' to the user."],"exampleFix":"// before\nconst size = readTarNumeric(truncatedChunk, 124, 12); // throws\n// after\nif (truncatedChunk.byteLength < 512) throw new Error(\"tar buffer too small\");\nconst size = readTarNumeric(truncatedChunk, 124, 12);","handlingStrategy":"validation","validationCode":"import { sniffTar } from \"@oh-my-pi/pi-utils/ar/tar\";\nif (buffer.byteLength < 512 || !sniffTar(buffer)) {\n  throw new Error(\"Input is not a complete tar archive\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  const entries = readTarEntriesFromBuffer(buffer, options);\n} catch (err) {\n  if (err instanceof ArchiveError && err.message === \"Invalid tar numeric field\") {\n    throw new Error(\"Tar buffer truncated or misaligned: header field out of bounds\");\n  }\n  throw err;\n}","preventionTips":["Always pass whole, complete tar buffers — never partial reads — to the tar readers.","Run sniffTar before parsing untrusted bytes.","Double-check offsets if you slice headers yourself; tar headers are fixed 512-byte blocks.","Validate downloads against a checksum before extraction."],"tags":["tar","archive","corrupt-data","bounds-check"],"backgroundTag":"corrupt-tar-archive","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}