{"record":{"id":"69e2aa60be6fa72e","repo":"Tencent/tinker","slug":"switch-instruction-at-address-index-0x-x-d-points","errorCode":null,"errorMessage":"Switch instruction at address/index 0x%x/%d points to the end of the method.","messagePattern":"Switch instruction at address/index 0x%x/(.+?) points to the end of the method\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"tinker-build/tinker-patch-lib/src/main/java/org/jf/dexlib2/builder/BuilderMutableMethodImplementation.java","lineNumber":474,"sourceCode":"            }\n        }\n        return null;\n    }\n\n    private void fixInstructions() {\n        HashSet<MethodLocation> payloadLocations = Sets.newHashSet();\n\n        for (MethodLocation location : instructionList) {\n            BuilderInstruction instruction = location.instruction;\n            if (instruction != null) {\n                switch (instruction.getOpcode()) {\n                    case SPARSE_SWITCH:\n                    case PACKED_SWITCH: {\n                        MethodLocation targetLocation =\n                                ((BuilderOffsetInstruction) instruction).getTarget().getLocation();\n                        BuilderInstruction targetInstruction = targetLocation.instruction;\n                        if (targetInstruction == null) {\n                            throw new IllegalStateException(String.format(\"Switch instruction at address/index \"\n                                    + \"0x%x/%d points to the end of the method.\", location.codeAddress, location.index));\n                        }\n\n                        if (targetInstruction.getOpcode() == Opcode.NOP) {\n                            targetInstruction = getFirstNonNop(targetLocation.index + 1);\n                        }\n                        if (targetInstruction == null || !(targetInstruction instanceof BuilderSwitchPayload)) {\n                            throw new IllegalStateException(String.format(\"Switch instruction at address/index \"\n                                            + \"0x%x/%d does not refer to a payload instruction.\",\n                                    location.codeAddress, location.index));\n                        }\n                        if ((instruction.opcode == Opcode.PACKED_SWITCH\n                                && targetInstruction.getOpcode() != Opcode.PACKED_SWITCH_PAYLOAD)\n                                || (instruction.opcode == Opcode.SPARSE_SWITCH\n                                        && targetInstruction.getOpcode() != Opcode.SPARSE_SWITCH_PAYLOAD)) {\n                            throw new IllegalStateException(String.format(\"Switch instruction at address/index \"\n                                            + \"0x%x/%d refers to the wrong type of payload instruction.\",\n                                    location.codeAddress, location.index));","sourceCodeStart":456,"sourceCodeEnd":492,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/tinker-build/tinker-patch-lib/src/main/java/org/jf/dexlib2/builder/BuilderMutableMethodImplementation.java#L456-L492","documentation":"Thrown while dexlib2's BuilderMutableMethodImplementation verifies switch instructions during conversion of a method's instructions into builder form (used by Tinker when parsing/rewriting dex files). It means a PACKED_SWITCH/SPARSE_SWITCH instruction's branch target offset resolves to the end of the method, where no instruction exists. This indicates a malformed or non-standard dex produced by an aggressive obfuscator/protector or a damaged file.","triggerScenarios":"Loading a dex into BuilderMutableMethodImplementation (e.g., during Tinker patch generation or on-device dex patch applying) where a switch instruction's target Label/offset points past the final instruction of the method.","commonSituations":"Dex protected by packers/obfuscators (360 Jiagu, Bangcle, DexGuard tricks) that emit unconventional switch payloads; truncated or corrupted dex from a bad download; dex produced by toolchains newer than the dexlib2 bundled with your Tinker version.","solutions":["Upgrade Tinker (and its bundled dexlib2/tinker-patch-lib) to a version that supports the dex producer","Rebuild the base apk without the offending obfuscation/packing step and regenerate the patch","Verify dex integrity (dex checksum/signature) before feeding it to the patch toolchain","If only one class is affected, exclude that dex/class from patching while you investigate"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-validate dex with a strict parser before Tinker processes it\ntry {\n    org.jf.dexlib2.iface.DexFile df = org.jf.dexlib2.DexFileFactory.loadDexFile(dexFile);\n    df.getClasses(); // force full parse\n} catch (Exception e) {\n    throw new IllegalArgumentException(\"dex fails pre-parse, skip patching\", e);\n}","typeGuard":null,"tryCatchPattern":"try {\n    // dex diff or patch application\n} catch (IllegalStateException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"points to the end of the method\")) {\n        // reject this dex/patch, alert, do not retry blindly\n    } else { throw e; }\n}","preventionTips":["Run a full baksmali/dexlib2 parse pass over protected dex files before patch generation","Keep Tinker's dexlib2 version at least as new as the tools that produced your dex","Verify patch package digests before applying"],"tags":["dexlib2","dex","malformed-dex","switch-instruction","patch-build"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}