{"record":{"id":"6f2a8b98f6c1aa6a","repo":"Tencent/tinker","slug":"bad-elf-magic-x-x-x-x","errorCode":null,"errorMessage":"bad elf magic: %x %x %x %x.","messagePattern":"bad elf magic: %x %x %x %x\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"tinker-android/tinker-android-loader-no-op/src/main/java/com/tencent/tinker/loader/shareutil/ShareElfFile.java","lineNumber":213,"sourceCode":"        public final short eType;\n        public final short eMachine;\n        public final int eVersion;\n        public final long eEntry;\n        public final long ePhOff;\n        public final long eShOff;\n        public final int eFlags;\n        public final short eEhSize;\n        public final short ePhEntSize;\n        public final short ePhNum;\n        public final short eShEntSize;\n        public final short eShNum;\n        public final short eShStrNdx;\n\n        private ElfHeader(FileChannel channel) throws IOException {\n            channel.position(0);\n            channel.read(ByteBuffer.wrap(eIndent));\n            if (eIndent[0] != 0x7F || eIndent[1] != 'E' || eIndent[2] != 'L' || eIndent[3] != 'F') {\n                throw new IOException(String.format(\"bad elf magic: %x %x %x %x.\", eIndent[0], eIndent[1], eIndent[2], eIndent[3]));\n            }\n\n            assertInRange(eIndent[EI_CLASS], ELFCLASS32, ELFCLASS64, \"bad elf class: \" + eIndent[EI_CLASS]);\n            assertInRange(eIndent[EI_DATA], ELFDATA2LSB, ELFDATA2MSB, \"bad elf data encoding: \" + eIndent[EI_DATA]);\n\n            final ByteBuffer restBuffer = ByteBuffer.allocate(eIndent[EI_CLASS] == ELFCLASS32 ? 36 : 48);\n            restBuffer.order(eIndent[EI_DATA] == ELFDATA2LSB ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);\n            readUntilLimit(channel, restBuffer, \"failed to read rest part of ehdr.\");\n\n            eType = restBuffer.getShort();\n            eMachine = restBuffer.getShort();\n\n            eVersion = restBuffer.getInt();\n            assertInRange(eVersion, EV_CURRENT, EV_CURRENT, \"bad elf version: \" + eVersion);\n\n            switch (eIndent[EI_CLASS]) {\n                case ELFCLASS32:\n                    eEntry = restBuffer.getInt();","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/tinker-android/tinker-android-loader-no-op/src/main/java/com/tencent/tinker/loader/shareutil/ShareElfFile.java#L195-L231","documentation":"ShareElfFile.ElfHeader reads the first 16 bytes (e_ident) of the file and requires the ELF magic 0x7F 'E' 'L' 'F'. A mismatch throws IOException('bad elf magic: %x %x %x %x.') showing the actual first four bytes. Tinker parses ELF when checking native libraries in patches (and OAT files), so this means the file being parsed is simply not an ELF binary.","triggerScenarios":"Constructing ShareElfFile over a file whose first 4 bytes are not 7f 45 4c 46 — e.g. a plain dex/jar/zip named .so, a text file, a compressed archive, or an already-stripped fake library placed in the patch's lib directory.","commonSituations":"Patch built with mismatched ABIs or a placeholder .so; gradle plugin packaging a non-ELF file into lib/; pointing tinker's lib check at odex/dex artifacts; downloading patches through a proxy that returns an HTML error page saved with the .so name.","solutions":["Inspect the offending file's first bytes (xxd file | head -1) to identify what it actually is.","Rebuild the patch ensuring only genuine ELF .so files for the target ABIs are included (match ABIs with the base APK).","Verify patch download integrity (md5/length) before apply so proxy/error payloads never enter lib/.","cleanPatch() to remove the bad state after the failure."],"exampleFix":"// before\nShareElfFile elf = new ShareElfFile(libFile); // IOException: bad elf magic\n\n// after: cheap magic guard\nprivate static boolean looksLikeElf(File f) throws IOException {\n    try (RandomAccessFile raf = new RandomAccessFile(f, \"r\")) {\n        byte[] m = new byte[4];\n        raf.readFully(m);\n        return (m[0] & 0xff) == 0x7f && m[1] == 'E' && m[2] == 'L' && m[3] == 'F';\n    }\n}","handlingStrategy":"type-guard","validationCode":"try (RandomAccessFile raf = new RandomAccessFile(f, \"r\")) {\n    byte[] m = new byte[4];\n    raf.readFully(m);\n    boolean isElf = (m[0] & 0xff) == 0x7f && m[1] == 'E' && m[2] == 'L' && m[3] == 'F';\n    if (!isElf) throw new IOException(\"not an ELF file: \" + f);\n}","typeGuard":"public static boolean isElfFile(File f) throws IOException {\n    if (f.length() < 16) return false;\n    try (RandomAccessFile raf = new RandomAccessFile(f, \"r\")) {\n        byte[] m = new byte[4];\n        raf.readFully(m);\n        return (m[0] & 0xff) == 0x7f && m[1] == 'E' && m[2] == 'L' && m[3] == 'F';\n    }\n}","tryCatchPattern":"catch (IOException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"bad elf magic\")) {\n        // wrong file type: fix packaging, don't retry\n    }\n}","preventionTips":["Validate downloaded binaries by md5 and magic bytes before use","Ensure patch packaging only includes real .so ELF files for matching ABIs"],"tags":["tinker","android","elf","file-format","native-lib"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}