{"record":{"id":"dd2616c9823ca457","repo":"skylot/jadx","slug":"config-size-4","errorCode":null,"errorMessage":"Config size < 4","messagePattern":"Config size < 4","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"jadx-core/src/main/java/jadx/core/xmlgen/ResTableBinaryParser.java","lineNumber":541,"sourceCode":"\n\tprivate RawNamedValue parseValueMap() throws IOException {\n\t\tint nameRef = is.readInt32();\n\t\treturn new RawNamedValue(nameRef, parseValue());\n\t}\n\n\tprivate RawValue parseValue() throws IOException {\n\t\tis.checkInt16(8, \"value size\");\n\t\tis.checkInt8(0, \"value res0 not 0\");\n\t\tint dataType = is.readInt8();\n\t\tint data = is.readInt32();\n\t\treturn new RawValue(dataType, data);\n\t}\n\n\tprivate EntryConfig parseConfig() throws IOException {\n\t\tlong start = is.getPos();\n\t\tint size = is.readInt32();\n\t\tif (size < 4) {\n\t\t\tthrow new IOException(\"Config size < 4\");\n\t\t}\n\n\t\t// Android zero fill this structure and only read the data present\n\t\tvar configData = new byte[Math.max(52, size - 4)];\n\t\tis.readFully(configData, 0, size - 4);\n\t\tvar configIs = new ParserStream(new ByteArrayInputStream(configData));\n\n\t\tshort mcc = (short) configIs.readInt16();\n\t\tshort mnc = (short) configIs.readInt16();\n\n\t\tchar[] language = unpackLocaleOrRegion((byte) configIs.readInt8(), (byte) configIs.readInt8(), 'a');\n\t\tchar[] country = unpackLocaleOrRegion((byte) configIs.readInt8(), (byte) configIs.readInt8(), '0');\n\n\t\tbyte orientation = (byte) configIs.readInt8();\n\t\tbyte touchscreen = (byte) configIs.readInt8();\n\t\tint density = configIs.readInt16();\n\n\t\tbyte keyboard = (byte) configIs.readInt8();","sourceCodeStart":523,"sourceCodeEnd":559,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/xmlgen/ResTableBinaryParser.java#L523-L559","documentation":"parseConfig reads the size field of a ResTable_config structure. The first 4 bytes encode the total config size; if it is less than 4, the structure is too small to even contain its own size field, indicating corrupt or invalid config data.","triggerScenarios":"parseConfig() reads an int32 size from the stream. The Android resource format guarantees config is at least 4 bytes (the size field itself). A value < 4 means the data is garbage, truncated, or misaligned. This is a defensive guard before allocating a config data buffer.","commonSituations":"Corrupt resources.arsc where config size fields are zeroed or negative (interpreted as unsigned). Obfuscation tools that mangle config entries. Truncated resource data stream. Passing a non-resource binary to the parser.","solutions":["Re-extract resources.arsc from a valid APK","Upgrade jadx to the latest version","Report the file to jadx maintainers with context","Use --no-res to skip resource decoding entirely"],"exampleFix":"// Skip resources:\njadxArgs.setSkipResources(true);","handlingStrategy":"try-catch","validationCode":"// Validate the arsc file has enough data for config structures\nif (Files.size(arscPath) < 52) { throw new IllegalArgumentException(\"arsc too small for config\"); }","typeGuard":null,"tryCatchPattern":"try {\n    resTableParser.decode(stream);\n} catch (IOException e) {\n    if (e.getMessage().contains(\"Config size\")) {\n        LOG.warn(\"Invalid config in resources, skipping\", e);\n        jadxArgs.setSkipResources(true);\n    }\n}","preventionTips":["Ensure the APK is complete and uncorrupted","Use --no-res fallback","Keep jadx updated for format robustness"],"tags":["android","binary-parsing","validation","resource-table","corrupt-input"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}