{"record":{"id":"be5761b0743f982a","repo":"Tencent/tinker","slug":"bad-oat-magic-x-x-x-x-be5761","errorCode":null,"errorMessage":"Bad oat magic: %x %x %x %x","messagePattern":"Bad oat magic: %x %x %x %x","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/shareutil/ShareOatUtil.java","lineNumber":68,"sourceCode":"        String result = \"\";\n        try {\n            elfFile = new ShareElfFile(oatFile);\n            final ShareElfFile.SectionHeader roDataHdr = elfFile.getSectionHeaderByName(\".rodata\");\n            if (roDataHdr == null) {\n                throw new IOException(\"Unable to find .rodata section.\");\n            }\n\n            final FileChannel channel = elfFile.getChannel();\n            channel.position(roDataHdr.shOffset);\n\n            final byte[] oatMagicAndVersion = new byte[8];\n            ShareElfFile.readUntilLimit(channel, ByteBuffer.wrap(oatMagicAndVersion), \"Failed to read oat magic and version.\");\n\n            if (oatMagicAndVersion[0] != 'o'\n                    || oatMagicAndVersion[1] != 'a'\n                    || oatMagicAndVersion[2] != 't'\n                    || oatMagicAndVersion[3] != '\\n') {\n                throw new IOException(\n                        String.format(\"Bad oat magic: %x %x %x %x\",\n                                oatMagicAndVersion[0],\n                                oatMagicAndVersion[1],\n                                oatMagicAndVersion[2],\n                                oatMagicAndVersion[3])\n                );\n            }\n\n            final int versionOffsetFromOatBegin = 4;\n            final int versionBytes = 3;\n\n            final String oatVersion = new String(oatMagicAndVersion,\n                    versionOffsetFromOatBegin, versionBytes, Charset.forName(\"ASCII\"));\n            try {\n                Integer.parseInt(oatVersion);\n            } catch (NumberFormatException e) {\n                throw new IOException(\"Bad oat version: \" + oatVersion);\n            }","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/shareutil/ShareOatUtil.java#L50-L86","documentation":"After locating the .rodata section of an odex, ShareOatUtil reads 8 bytes of oat magic and version and requires the first four bytes to be 'o','a','t','\\n'. If they differ it throws IOException formatted as \"Bad oat magic: %x %x %x %x\". The .rodata content is not a real OAT header, so the instruction set cannot be extracted from it.","triggerScenarios":"getOatFileInstructionSet on an ELF whose .rodata begins with bytes other than the oat magic — wrong offset assumption for that ART version, a non-oat ELF, or a corrupted odex.","commonSituations":"Newer Android/ART versions changing the oat header placement; passing a stripped or unusual odex; patched/custom ROMs with non-standard dexopt output.","solutions":["Pull the odex and hex-dump the first bytes of .rodata to confirm whether it is a real oat header.","Fall back to ShareTinkerInternals.getCurrentInstructionSet() (Build.CPU_ABI based) when oat parsing fails.","Update Tinker to a version matching the target Android version's odex layout.","Wrap the call in try-catch (it throws Throwable) and treat failure as 'isa unknown'."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Cheap pre-check: peek 8 bytes at .rodata offset for 'oat\\n' before full parse\n// (only if you already parse sections; otherwise rely on the try-catch fallback)","typeGuard":null,"tryCatchPattern":"try {\n    isa = ShareOatUtil.getOatFileInstructionSet(odexFile);\n} catch (IOException ioe) {\n    // 'Bad oat magic': unrecognized oat format, fall back to ABI-based ISA\n    isa = ShareTinkerInternals.getCurrentInstructionSet();\n}","preventionTips":["Keep Tinker updated for new ART/oat layouts.","Do not assume the odex format; always code an ISA fallback path.","Hex-verify odex files when bringing up new Android versions."],"tags":["android","tinker","oat","file-format","instruction-set"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}