{"record":{"id":"52794c98228cb900","repo":"can1357/oh-my-pi","slug":"invalid-lzh-level-2-header-size","errorCode":null,"errorMessage":"Invalid LZH level-2 header size","messagePattern":"Invalid LZH level-2 header size","errorType":"validation","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/lzh.ts","lineNumber":531,"sourceCode":"\t\t\t\tif (++extensionCount > 65_535) throw new ArchiveError(\"Invalid LZH archive: too many extended headers\");\n\t\t\t\tconst type = bytes[cursor]!;\n\t\t\t\tconst dataEnd = cursor + extensionSize - 2;\n\t\t\t\tconst data = bytes.subarray(cursor + 1, dataEnd);\n\t\t\t\tif (type === 0x01 || type === 0x02 || type === 0x44 || type === 0x45) {\n\t\t\t\t\tassertArchivePathBytes(data.byteLength, \"member path\", options.limits.maxPathBytes);\n\t\t\t\t}\n\t\t\t\tprocessExtendedHeader(type, data, cursor + 1, fields);\n\t\t\t\tconst currentSize = extensionSize;\n\t\t\t\textensionSize = u16(bytes, dataEnd);\n\t\t\t\tcursor += currentSize;\n\t\t\t}\n\t\t\tdataStart = baseEnd + totalExtensionSize;\n\t\t\tpackedSize = fields.packedSize ?? packedSize - totalExtensionSize;\n\t\t\tif (packedSize < 0) throw new ArchiveError(\"Invalid LZH level-1 packed size\");\n\t\t}\n\t} else {\n\t\tconst headerLength = u16(bytes, offset);\n\t\tif (headerLength < 26) throw new ArchiveError(\"Invalid LZH level-2 header size\");\n\t\tconst headerEnd = offset + headerLength;\n\t\tassertRange(bytes, offset, headerEnd, \"header\");\n\t\tcrc = u16(bytes, offset + 21);\n\t\tosId = bytes[offset + 23]!;\n\t\tmtimeMs = u32(bytes, offset + 15) * 1000;\n\t\tlet cursor = offset + 24;\n\t\tlet extensionCount = 0;\n\t\twhile (cursor + 2 <= headerEnd) {\n\t\t\tconst extensionSize = u16(bytes, cursor);\n\t\t\tif (extensionSize === 0) {\n\t\t\t\tcursor += 2;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (extensionSize < 3 || cursor + extensionSize > headerEnd)\n\t\t\t\tthrow new ArchiveError(\"Invalid LZH extended header size\");\n\t\t\tif (++extensionCount > 65_535) throw new ArchiveError(\"Invalid LZH archive: too many extended headers\");\n\t\t\tconst type = bytes[cursor + 2]!;\n\t\t\tconst data = bytes.subarray(cursor + 3, cursor + extensionSize);","sourceCodeStart":513,"sourceCodeEnd":549,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/lzh.ts#L513-L549","documentation":"Thrown when a level-2 LZH header's 16-bit declared length is smaller than the 26-byte minimum required for its fixed fields. The header cannot contain the mandatory level-2 layout (CRC, OS id, timestamps), so parsing aborts.","triggerScenarios":"Reading a level-2 LHA archive with a corrupt or truncated header-length field, or a file misidentified as level-2 LZH.","commonSituations":"Damaged downloads, archives from buggy level-2 writers, fuzzed or hostile inputs.","solutions":["Obtain an uncorrupted copy of the archive","Repack with a conforming tool (e.g. lha -w2 or a level-2 capable packer)","Catch ArchiveError and reject the input if processing untrusted files"],"exampleFix":"null","handlingStrategy":"validation","validationCode":"const headerLength = bytes[0] | (bytes[1] << 8); if (headerLength < 26) throw new Error('level-2 header too small');","typeGuard":null,"tryCatchPattern":"try { parse(); } catch (err) { if (err instanceof ArchiveError && err.message.includes('level-2')) reject(err); else throw err; }","preventionTips":["Validate the u16 header length before delegating to the reader","Fail fast on truncated inputs"],"tags":["archive","lzh","level-2","header","corruption"],"backgroundTag":"corrupt-archive-header","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}