{"record":{"id":"e88acc9c31909306","repo":"shwenzhang/AndResGuard","slug":"readandwriteheader-size-0-size-d","errorCode":null,"errorMessage":"readAndWriteHeader size < 0: size=%d","messagePattern":"readAndWriteHeader size < 0: size=(.+?)","errorType":"exception","errorClass":"brut.androlib.AndrolibException","httpStatus":null,"severity":"error","filePath":"AndResGuard-core/src/main/java/com/tencent/mm/androlib/res/decoder/ARSCDecoder.java","lineNumber":1041,"sourceCode":"        return new Header(type, size);\n      } catch (EOFException ex) {\n        return new Header(TYPE_NONE, 0);\n      }\n    }\n\n    public static Header readAndWriteHeader(ExtDataInput in, ExtDataOutput out, int diffSize)\n       throws IOException, AndrolibException {\n      short type;\n      int size;\n      try {\n        type = in.readShort();\n        out.writeShort(type);\n        short count = in.readShort();\n        out.writeShort(count);\n        size = in.readInt();\n        size -= diffSize;\n        if (size <= 0) {\n          throw new AndrolibException(String.format(\"readAndWriteHeader size < 0: size=%d\", size));\n        }\n        out.writeInt(size);\n      } catch (EOFException ex) {\n        return new Header(TYPE_NONE, 0);\n      }\n      return new Header(type, size);\n    }\n  }\n\n  public static class FlagsOffset {\n    public final int offset;\n    public final int count;\n\n    public FlagsOffset(int offset, int count) {\n      this.offset = offset;\n      this.count = count;\n    }\n  }","sourceCodeStart":1023,"sourceCodeEnd":1059,"githubUrl":"https://github.com/shwenzhang/AndResGuard/blob/e4df245d82f27d9a2d0dd108260a3510cbaba849/AndResGuard-core/src/main/java/com/tencent/mm/androlib/res/decoder/ARSCDecoder.java#L1023-L1059","documentation":"Header.readAndWriteHeader copies a chunk header while subtracting diffSize (bytes removed earlier, e.g. shortened string entries) from the chunk size. If the adjusted size drops to <= 0 the chunk would be non-positive-length, which is invalid in the arsc format, so the tool throws rather than writing a corrupt header.","triggerScenarios":"size = in.readInt(); size -= diffSize; yields <= 0 — the diffSize (space saved by resource-name shortening) equals or exceeds the chunk's declared size, which happens with extreme obfuscation savings on tiny chunks or a miscomputed diff upstream.","commonSituations":"Obfuscating APKs with very small type chunks where the name-shortening savings exceed the chunk size, custom arsc layouts, or an AndResGuard bug in diff accounting with unusual resource tables.","solutions":["Upgrade AndResGuard — later versions fixed diffSize accounting bugs","Reduce obfuscation aggressiveness (e.g. keep longer resource names, use --keep-extensions style options) so savings stay below chunk size","Check the resources.arsc for unusually small TYPE chunks via aapt dump","Report/reproduce with the failing APK and fall back to disabling resource obfuscation for that build"],"exampleFix":"// before\nandResGuard {\n  mappingFile = file('old-mapping.txt') // reusing aggressive mapping\n}\n// after: use a fresh mapping / default setting for this apk\nandResGuard {\n  mappingFile = null\n}","handlingStrategy":"validation","validationCode":"// before obfuscating, check resource counts per type stay in normal ranges\n// and avoid reusing aggressive mappings from other apks\nif (mappingFile != null && !mappingBelongsToThisApk(mappingFile)) {\n  throw new GradleException(\"mappingFile does not match this apk; clear it\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  andResGuardTask.execute();\n} catch (AndrolibException e) {\n  if (e.getMessage().contains(\"readAndWriteHeader size < 0\")) {\n    logger.warn(\"diffSize exceeded chunk size; retry with default mapping\");\n    retryWithoutCustomMapping();\n  } else throw e;\n}","preventionTips":["Don't reuse obfuscation mappings across different APKs","Keep AndResGuard on the latest fixed version","Enable resource shrinking so chunks don't contain pathological entries","Reproduce with aapt dump resources if it persists"],"tags":["android","arsc","re-encoding","size-accounting"],"backgroundTag":"value-out-of-range","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"}