shwenzhang/AndResGuard · error

Style data size is not multiple of 4

Error message

Style data size is not multiple of 4 (${size}).

What it means

StringBlock.read() parses an Android resources.arsc string-pool chunk. When the chunk declares a styles section, the byte count from stylesOffset to the end of the chunk (chunkSize - stylesOffset) must be a multiple of 4, because styles are stored as int arrays. A misaligned size means the arsc chunk is truncated or corrupt, so the library throws IOException instead of reading garbage.

Solutions

  1. Verify the input APK's resources.arsc is intact (re-obtain the original APK or rebuild it with aapt/aapt2).
  2. Check that no other preprocessor modified resources.arsc before AndResGuard runs; disable conflicting tools in the build chain.
  3. Update AndResGuard / Android build tools to a version that handles the arsc format produced by your AGP version.
  4. Inspect chunkSize vs stylesOffset at StringBlock.java:99 with a hex dump of the arsc to confirm the chunk is truncated.
Defensive patterns

Strategy: try-catch

Validate before calling

// Before parsing, sanity-check the arsc chunk header
int expected = chunkSize - stylesOffset;
if (stylesOffset != 0 && (expected % 4) != 0) {
  throw new IllegalArgumentException("corrupt arsc chunk: size " + expected + " not 4-aligned");
}

Try / catch

try { StringBlock block = StringBlock.read(reader); } catch (IOException e) { if (e.getMessage().contains("not multiple of 4")) { /* reject APK as corrupt / fall back to original build */ } else throw e; }

Prevention

When it happens

Trigger: Calling the API path that reads a string pool (e.g. StringBlock.read(reader)) on a chunk whose stylesOffset != 0 and where (chunkSize - stylesOffset) % 4 != 0, i.e. a malformed or hand-edited resources.arsc.

Common situations: Processing APKs whose resources.arsc was obfuscated, patched by another tool, truncated by a bad repackage, or built by non-standard tooling; reading corrupted or partially-downloaded APK files.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

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

    Arrays.fill(block.m_stringOwns, -1);

    if (styleCount != 0) {
      block.m_styleOffsets = reader.readIntArray(styleCount);
    }
    {
      int size = ((stylesOffset == 0) ? chunkSize : stylesOffset) - stringsOffset;

      if ((size % 4) != 0) {
        throw new IOException("String data size is not multiple of 4 (" + size + ").");
      }
      block.m_strings = new byte[size];

      reader.readFully(block.m_strings);
    }
    if (stylesOffset != 0) {
      int size = (chunkSize - stylesOffset);
      if ((size % 4) != 0) {
        throw new IOException("Style data size is not multiple of 4 (" + size + ").");
      }
      block.m_styles = reader.readIntArray(size / 4);
    }
    return block;
  }

  public static int writeSpecNameStringBlock(
          ExtDataInput reader, ExtDataOutput out, Map<String, Set<String>> specNames, Map<String, Integer> curSpecNameToPos)
      throws IOException, AndrolibException {
    int type = reader.readInt();
    int chunkSize = reader.readInt();
    int stringCount = reader.readInt();
    int styleOffsetCount = reader.readInt();

    if (styleOffsetCount != 0) {
      throw new AndrolibException(String.format("writeSpecNameStringBlock styleOffsetCount != 0  styleOffsetCount %d",
          styleOffsetCount
      ));

View on GitHub (pinned to e4df245d82)