shwenzhang/AndResGuard · error · brut.androlib.AndrolibException

Config size < 28

Error message

Config size < 28

What it means

ARSCDecoder.readConfigFlags reads a resource table TYPE config structure and validates that its declared size is at least 28 bytes, the minimum defined by the Android resources.arsc format (ResTable_config header). A size smaller than 28 means the arsc chunk is malformed, truncated, or produced by a non-standard tool, so decoding cannot continue safely.

Solutions

  1. Rebuild the APK's resources.arsc with the official aapt/aapt2 from the Android SDK and re-run AndResGuard
  2. Verify the input APK is a valid, unmodified APK (aapt dump badging) before obfuscation
  3. Upgrade AndResGuard to the latest version, which tolerates more arsc variants
  4. If the arsc is intentionally non-standard, exclude it from processing or use --dont混淆 arsc options

Example fix

// before: decoding an APK compiled with a non-standard tool
AndResGuard.process(apkFile);
// after: rebuild resources with standard aapt2 first
// ./gradlew assembleRelease  (aapt2-produced arsc)
AndResGuard.process(apkFile);
Defensive patterns

Strategy: try-catch

Validate before calling

// java
File arsc = extractArsc(apk);
long len = arsc.length();
if (len < 8 || !isPlausibleArsc(arsc)) throw new IllegalArgumentException("resources.arsc looks malformed");

Type guard

boolean isPlausibleArsc(File f) throws IOException {
  try (DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(f)))) {
    int type = in.readUnsignedShort();
    int size = in.readInt();
    return type == 0x0002 && size > 28; // RES_TABLE_TYPE with sane header
  }
}

Try / catch

try {
  arscDecoder.decode(arscStream);
} catch (AndrolibException e) {
  if (e.getMessage().contains("Config size < 28")) {
    // fail fast: rebuild apk with aapt2; do not retry on the same input
    throw new BuildException("Malformed resources.arsc — rebuild with official aapt/aapt2", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Called during ARSC decode when iterating type configs: mIn.readInt() yields a config size < 28, i.e. the aapt-generated resources.arsc contains a ResTable_type entry with an undersized config header, or the stream is misaligned from earlier bad parsing.

Common situations: Processing an APK whose resources.arsc was built or rewritten by non-aapt tools (obfuscators, repackers), corrupted/truncated arsc files, or APKs from unusual build pipelines; also happens when a previous chunk was misread so the decoder reads garbage as the size field.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of shwenzhang/AndResGuard@e4df245d82 (2026-09-12). Data as JSON: /api/errors/5567f9b2ab52146f. Report an issue: GitHub.

Appendix: source

Thrown at AndResGuard-core/src/main/java/com/tencent/mm/androlib/res/decoder/ARSCDecoder.java:852

    return filterInfo;
  }

  private void writeValue() throws IOException, AndrolibException {
    /* size */
    mOut.writeCheckShort(mIn.readShort(), (short) 8);
    /* zero */
    mOut.writeCheckByte(mIn.readByte(), (byte) 0);
    byte type = mIn.readByte();
    mOut.writeByte(type);
    int data = mIn.readInt();
    mOut.writeInt(data);
  }

  private void readConfigFlags() throws IOException, AndrolibException {
    int size = mIn.readInt();
    int read = 28;
    if (size < 28) {
      throw new AndrolibException("Config size < 28");
    }

    boolean isInvalid = false;

    short mcc = mIn.readShort();
    short mnc = mIn.readShort();

    char[] language = new char[] { (char) mIn.readByte(), (char) mIn.readByte() };
    char[] country = new char[] { (char) mIn.readByte(), (char) mIn.readByte() };

    byte orientation = mIn.readByte();
    byte touchscreen = mIn.readByte();

    int density = mIn.readUnsignedShort();

    byte keyboard = mIn.readByte();
    byte navigation = mIn.readByte();
    byte inputFlags = mIn.readByte();

View on GitHub (pinned to e4df245d82)