{"record":{"id":"f3a2b0d27c533bfa","repo":"shwenzhang/AndResGuard","slug":"config-size-28-rawarscdecoder","errorCode":null,"errorMessage":"Config size < 28","messagePattern":"Config size < 28","errorType":"exception","errorClass":"brut.androlib.AndrolibException","httpStatus":null,"severity":"error","filePath":"AndResGuard-core/src/main/java/com/tencent/mm/androlib/res/decoder/RawARSCDecoder.java","lineNumber":241,"sourceCode":"      mIn.readInt();\n      readValue(flags, specNamesId);\n    }\n  }\n\n  private void readValue(boolean flags, int specNamesId) throws IOException, AndrolibException {\n    /* size */\n    mIn.skipCheckShort((short) 8);\n    /* zero */\n    mIn.skipCheckByte((byte) 0);\n    byte type = mIn.readByte();\n    int data = mIn.readInt();\n  }\n\n  private void readConfigFlags() throws IOException, AndrolibException {\n    int read = 28;\n    int size = mIn.readInt();\n    if (size < 28) {\n      throw new AndrolibException(\"Config size < 28\");\n    }\n\n    boolean isInvalid = false;\n    short mcc = mIn.readShort();\n    short mnc = mIn.readShort();\n    char[] language = new char[] { (char) mIn.readByte(), (char) mIn.readByte() };\n    char[] country = new char[] { (char) mIn.readByte(), (char) mIn.readByte() };\n    byte orientation = mIn.readByte();\n    byte touchscreen = mIn.readByte();\n    int density = mIn.readUnsignedShort();\n    byte keyboard = mIn.readByte();\n    byte navigation = mIn.readByte();\n    byte inputFlags = mIn.readByte();\n    /* inputPad0 */\n    mIn.skipBytes(1);\n\n    short screenWidth = mIn.readShort();\n    short screenHeight = mIn.readShort();","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/shwenzhang/AndResGuard/blob/e4df245d82f27d9a2d0dd108260a3510cbaba849/AndResGuard-core/src/main/java/com/tencent/mm/androlib/res/decoder/RawARSCDecoder.java#L223-L259","documentation":"RawARSCDecoder.readConfigFlags mirrors ARSCDecoder's check in the raw name-collection pass: each TYPE config must declare a size of at least 28 bytes (the minimal ResTable_config). A smaller value means the config chunk is malformed or the raw stream is misaligned, so the pre-scan of the arsc aborts.","triggerScenarios":"During readConfig -> readConfigFlags, mIn.readInt() returns a config size < 28, caused by a non-standard/malformed resources.arsc or by earlier chunks being consumed with wrong lengths in the raw pass.","commonSituations":"APKs repacked by third-party tools, arsc files built with non-aapt generators, corrupted downloads, or double-processed (already obfuscated) APKs.","solutions":["Rebuild the APK's resources.arsc with official aapt/aapt2 and retry","Start from the original, unmodified APK rather than a repacked one","Validate with aapt dump resources to locate the malformed config","Upgrade AndResGuard for broader arsc compatibility"],"exampleFix":"// before: repacked apk from a third-party store tool\nAndResGuard.process(repackedApk)\n// after: use the original build artifact\nAndResGuard.process(originalReleaseApk)","handlingStrategy":"try-catch","validationCode":"// validate arsc before the raw name pre-scan\n// aapt dump resources app.apk — aborts the pipeline if the arsc is malformed","typeGuard":null,"tryCatchPattern":"try {\n  RawARSCDecoder.decode(arscStream);\n} catch (AndrolibException e) {\n  if (e.getMessage().contains(\"Config size < 28\")) {\n    throw new BuildException(\"Malformed arsc config; rebuild with official aapt2\", e);\n  }\n  throw e;\n}","preventionTips":["Only process APKs from the official build pipeline","Avoid pre-repacked inputs (third-party store tools, double obfuscation)","Add aapt dump resources as a CI pre-check","Update AndResGuard for arsc variant tolerance"],"tags":["android","arsc","resource-parsing","corrupt-input"],"backgroundTag":"invalid-config-value","analyzedSha":"e4df245d82f27d9a2d0dd108260a3510cbaba849","analyzedAt":"2026-09-12T17:49:07.798Z","contentChangedAt":"2026-09-12T17:49:07.798Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}