shwenzhang/AndResGuard · error · AndrolibException

writeSpecNameStringBlock styleOffsetCount != 0 …

Error message

writeSpecNameStringBlock styleOffsetCount != 0  styleOffsetCount %d

What it means

writeSpecNameStringBlock re-reads the resource-table string pool while writing out a stripped spec-name block, and it only supports pools with no style spans. If styleOffsetCount (the style-offset array length in the chunk header) is non-zero, the writer cannot represent the styles and throws AndrolibException.

Solutions

  1. Remove or simplify styled (spanned) strings from resource tables so the string pool has no styles.
  2. Use a newer AndResGuard version that may handle style sections, or patch StringBlock to copy the styles section verbatim.
  3. As a workaround, pre-process the arsc with androidwide tooling (aapt2) to strip spans before obfuscation.
  4. If the styled strings are only in resources.arsc (not needed at runtime), rebuild resources without formatting spans.
Defensive patterns

Strategy: validation

Validate before calling

// Inspect the string pool header before writing
int styleOffsetCount = readIntAt(chunkStart + 20);
if (styleOffsetCount != 0) {
  // skip the spec-name fast path or strip styles first
}

Try / catch

try { block.writeSpecNameStringBlock(...); } catch (AndrolibException e) { if (e.getMessage().contains("styleOffsetCount != 0")) { /* fall back to full (non-stripped) write path */ } else throw e; }

Prevention

When it happens

Trigger: Calling writeSpecNameStringBlock on a resources.arsc string pool whose header declares styleOffsetCount != 0 (the chunk contains styled strings/span info).

Common situations: Running AndResGuard over APKs that contain styled strings in the resource table (HTML-like <b>/<i> spans in resource strings), typically from apps with rich text resources.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

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

      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
      ));
    }

    int flags = reader.readInt();
    boolean isUTF8 = (flags & UTF8_FLAG) != 0;
    int stringsOffset = reader.readInt();
    int stylesOffset = reader.readInt();
    reader.readIntArray(stringCount);
    int size = ((stylesOffset == 0) ? chunkSize : stylesOffset) - stringsOffset;

    if ((size % 4) != 0) {
      throw new IOException("String data size is not multiple of 4 (" + size + ").");
    }
    byte[] temp_strings = new byte[size];
    reader.readFully(temp_strings);
    int totalSize = 0;
    out.writeCheckInt(type, CHUNK_STRINGPOOL_TYPE);

View on GitHub (pinned to e4df245d82)