{"record":{"id":"005654f744e3f0fa","repo":"HMCL-dev/HMCL","slug":"corrupted-read-data-length-d","errorCode":null,"errorMessage":"Corrupted read (Data length %d)","messagePattern":"Corrupted read \\(Data length (.+?)\\)","errorType":"exception","errorClass":"PngIntegrityException","httpStatus":null,"severity":"error","filePath":"HMCL/src/main/java/org/jackhuang/hmcl/ui/image/apng/reader/DefaultPngChunkReader.java","lineNumber":42,"sourceCode":" */\npublic class DefaultPngChunkReader<ResultT> implements PngChunkReader<ResultT> {\n    protected PngChunkProcessor<ResultT> processor;\n    protected boolean seenHeader = false;\n    protected int idatCount = 0;\n    protected int apngSequenceExpect = 0;\n    protected PngAnimationType animationType = PngAnimationType.NOT_ANIMATED;\n    //private PngMainImageOp mainImageOp = PngMainImageOp.MAIN_IMAGE_KEEP;\n\n    public DefaultPngChunkReader(PngChunkProcessor<ResultT> processor) {\n        this.processor = processor;\n    }\n\n    @Override\n    public boolean readChunk(PngSource source, int code, int dataLength) throws PngException, IOException {\n        int dataPosition = source.tell(); // note the start position before any further reads are done.\n\n        if (dataLength < 0) {\n            throw new PngIntegrityException(String.format(\"Corrupted read (Data length %d)\", dataLength));\n        }\n\n        switch (code) {\n            case PngConstants.IHDR_VALUE:\n                readHeaderChunk(source, dataLength);\n                break;\n\n            case PngConstants.IEND_VALUE:\n                // NOP\n                break;\n\n            case PngConstants.gAMA_VALUE:\n                readGammaChunk(source, dataLength);\n                break;\n\n            case PngConstants.bKGD_VALUE:\n                readBackgroundChunk(source, dataLength);\n                break;","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/ui/image/apng/reader/DefaultPngChunkReader.java#L24-L60","documentation":"This guard in DefaultPngChunkReader.readChunk fires when a chunk's declared data length cannot actually be read from the stream - fewer bytes are available than the length field promises. It indicates the PNG stream is truncated or the chunk table is corrupted, so the current chunk cannot be consumed.","triggerScenarios":"A chunk length field (or prior misread) yields dataLength < 0, e.g. after seeking errors, wrong stream offset, or corrupted length bytes with the high bit set.","commonSituations":"Corrupted PNG files, reading from a misaligned stream, treating a non-PNG file as PNG.","solutions":["Confirm the stream is positioned at a real chunk boundary (check the 8-byte PNG signature and IHDR alignment).","Inspect the corrupted file with a PNG validator (pngcheck) to find where the stream desyncs.","Re-download/re-export the image; the file bytes are damaged.","Catch PngIntegrityException around chunk iteration to fail gracefully."],"exampleFix":"// before\nreader.readChunk(source, code, dataLength);\n// after\nif (dataLength < 0 || dataLength > maxChunkSize) {\n    throw new PngIntegrityException(\"implausible chunk length \" + dataLength);\n}\nreader.readChunk(source, code, dataLength);","handlingStrategy":"try-catch","validationCode":"if (dataLength < 0 || dataLength > fileBytesRemaining) throw new IllegalStateException(\"corrupt chunk length\");","typeGuard":null,"tryCatchPattern":"try { while (reader.readChunk(source, code, len)) { ... } } catch (PngIntegrityException e) { abortDecode(\"corrupt stream: \" + e.getMessage()); }","preventionTips":["Verify PNG signature and stream alignment before chunk reads.","Bound chunk lengths by remaining file size.","Re-download truncated files.","Log the stream offset where corruption occurred."],"tags":["png","image-decoding","corruption","stream"],"backgroundTag":"invalid-argument-value","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}