{"record":{"id":"6eabd7f2a89e1a29","repo":"Tencent/tinker","slug":"bad-crc32-value","errorCode":null,"errorMessage":"Bad CRC32: ${value}","messagePattern":"Bad CRC32: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"third-party/tinker-ziputils/src/main/java/com/tencent/tinker/ziputils/ziputil/TinkerZipEntry.java","lineNumber":266,"sourceCode":"     * @return the checksum, or -1 if the checksum has not been set.\n     */\n    public long getCrc() {\n        return crc;\n    }\n\n    /**\n     * Sets the checksum for this {@code ZipEntry}.\n     *\n     * @param value\n     *            the checksum for this entry.\n     * @throws IllegalArgumentException\n     *             if {@code value} is < 0 or > 0xFFFFFFFFL.\n     */\n    public void setCrc(long value) {\n        if (value >= 0 && value <= 0xFFFFFFFFL) {\n            crc = value;\n        } else {\n            throw new IllegalArgumentException(\"Bad CRC32: \" + value);\n        }\n    }\n\n    /**\n     * Gets the extra information for this {@code ZipEntry}.\n     *\n     * @return a byte array containing the extra information, or {@code null} if\n     *         there is none.\n     */\n    public byte[] getExtra() {\n        return extra;\n    }\n\n    /**\n     * Sets the extra information for this {@code ZipEntry}.\n     *\n     * @throws IllegalArgumentException if the data length >= 64 KiB.\n     */","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/third-party/tinker-ziputils/src/main/java/com/tencent/tinker/ziputils/ziputil/TinkerZipEntry.java#L248-L284","documentation":"A zip entry's CRC32 is stored as an unsigned 32-bit value, so setCrc only accepts values in the range 0..0xFFFFFFFFL. Passing a negative long or any value above 0xFFFFFFFFL throws IllegalArgumentException. This mirrors the contract of java.util.zip.ZipEntry.setCrc. It usually means the caller computed or propagated a corrupted CRC value instead of reading one from CRC32.getValue().","triggerScenarios":"Calling setCrc(value) where value < 0 or value > 0xFFFFFFFFL — typically a sign-extended int cast to long (e.g. setCrc((long) someInt) with the high bit set), or arithmetic that underflows/overflows when copying CRCs between entries.","commonSituations":"Porting code that stored CRCs in signed ints and reinterprets them with sign extension; recomputing a CRC with a buggy incremental update; copying metadata from a parsed zip header into a new entry.","solutions":["Mask the value into unsigned 32-bit range before setting: setCrc(value & 0xFFFFFFFFL).","Use java.util.zip.CRC32, call reset() then update()/getValue() so the result is always in range.","Audit any int-to-long casts of CRC values in the call path and remove sign extension."],"exampleFix":"// before\nint crcFromHeader = ...; // may have high bit set\nentry.setCrc(crcFromHeader); // implicit sign extension -> negative long\n\n// after\nentry.setCrc(crcFromHeader & 0xFFFFFFFFL);","handlingStrategy":"validation","validationCode":"long crc = computeCrc(data);\nif (crc < 0 || crc > 0xFFFFFFFFL) {\n    throw new IllegalStateException(\"CRC computation bug: \" + crc);\n}\nentry.setCrc(crc);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always produce CRCs via java.util.zip.CRC32.getValue(), never by manual arithmetic on ints.","Mask with & 0xFFFFFFFFL whenever a CRC crosses an int boundary.","Treat an out-of-range CRC as a bug in your code, not bad input — fix the computation, do not catch."],"tags":["zip","crc","validation","tinker"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}