{"record":{"id":"61120ef1f6180344","repo":"Tencent/tinker","slug":"invalid-leb128-sequence","errorCode":null,"errorMessage":"invalid LEB128 sequence","messagePattern":"invalid LEB128 sequence","errorType":"exception","errorClass":"DexException","httpStatus":null,"severity":"error","filePath":"third-party/aosp-dexutils/src/main/java/com/tencent/tinker/android/dex/Leb128.java","lineNumber":99,"sourceCode":"\n    /**\n     * Reads an signed integer from {@code in}.\n     */\n    public static int readSignedLeb128(ByteInput in) {\n        int result = 0;\n        int cur;\n        int count = 0;\n        int signBits = -1;\n\n        do {\n            cur = in.readByte() & 0xff;\n            result |= (cur & 0x7f) << (count * 7);\n            signBits <<= 7;\n            count++;\n        } while (((cur & 0x80) == 0x80) && count < 5);\n\n        if ((cur & 0x80) == 0x80) {\n            throw new DexException(\"invalid LEB128 sequence\");\n        }\n\n        // Sign extend if appropriate\n        if (((signBits >> 1) & result) != 0) {\n            result |= signBits;\n        }\n\n        return result;\n    }\n\n    /**\n     * Reads an unsigned leb128 integer from {@code in}.\n     */\n    public static int readUnsignedLeb128(ByteInput in) {\n        int result = 0;\n        int cur;\n        int count = 0;\n","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/third-party/aosp-dexutils/src/main/java/com/tencent/tinker/android/dex/Leb128.java#L81-L117","documentation":"Thrown by Leb128.readSignedLeb128 when a signed LEB128 varint still has its continuation bit (0x80) set after 5 bytes. LEB128 encodes at most 32 bits in 5 groups of 7 bits (35 bits, but a 32-bit int needs ≤5); a 6th continuation means the stream is not a valid LEB128 encoding of an int.","triggerScenarios":"Parsing string_ids/type list sizes, ULEB128 fields in class_def, or any signed varint field from a buffer whose position is wrong (usually 1+ bytes off), or from a corrupt/truncated dex where what follows is payload, not a varint.","commonSituations":"Misaligned reads after a partial skip; dex files truncated by a bad copy or OTA patch; hand-built dex writers emitting >5-byte (over-long, non-canonical) LEB128 encodings that AOSP rejects.","solutions":["Validate the dex before parsing (checksum + SHA-1 signature in the header, or dexdump) to rule out corruption.","Audit any custom writer that produced the input to ensure it emits canonical, ≤5-byte LEB128.","If reading a structured region, re-derive the start offset — an off-by-N start makes every subsequent varint invalid."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { int v = Leb128.readSignedLeb128(in); } catch (DexException e) { throw new CorruptDexException(dexName, offset, e); }","preventionTips":["Checksum/SHA-1 validate dexes before deep parsing so corruption surfaces as an integrity error, not a varint error.","If you write dexes, assert canonical LEB128 length (<=5 bytes) in your own writer's tests."],"tags":["dex","leb128","varint","parsing","tinker"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}