shwenzhang/AndResGuard · error · AndrolibException

writeTableNameStringBlock UTF-16LE length is different name

Error message

writeTableNameStringBlock UTF-16LE length is different  name %d, tempByte %d

What it means

The UTF-16LE branch of writeTableNameStringBlock writes name.length() as the length field and then requires the UTF-16LE encoding to occupy exactly length*2 bytes. The check fails for names containing supplementary (surrogate-pair) characters, where the char count and encoded size relationship breaks the writer's assumptions, and for pathological length values.

Solutions

  1. Rename resources containing emoji or supplementary characters to ASCII identifiers.
  2. Keep resource-name obfuscation enabled so original names never reach the string-pool writer.
  3. Patch validation to compare encoded length against the value actually written (counting code points).
  4. Find the offending name in the message and edit it in the resource sources.
Defensive patterns

Strategy: validation

Validate before calling

static boolean utf16Simple(String name) {
  return name.getBytes(StandardCharsets.UTF_16LE).length == name.length() * 2
      && name.codePoints().allMatch(cp -> cp <= 0xFFFF);
}
// gate resource names on utf16Simple before processing

Try / catch

try { ... } catch (AndrolibException e) { if (e.getMessage().contains("UTF-16LE length is different")) { /* fail the build naming the offending resource from the message */ } else throw e; }

Prevention

When it happens

Trigger: writeTableNameStringBlock with block.m_isUTF8 == false and a name where name.getBytes(UTF_16LE).length != name.length()*2 (surrogate pairs/emoji in resource names).

Common situations: Resource names with emoji or astral-plane characters; apps with creatively named resources processed through AndResGuard.

Related errors


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

Appendix: source

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

          byte[] tempByte = name.getBytes(Charset.forName("UTF-8"));
          if (name.length() != tempByte.length) {
            throw new AndrolibException(String.format(
                "writeTableNameStringBlock UTF-8 length is different  name %d, tempByte %d\n",
                name.length(),
                tempByte.length
            ));
          }
          System.arraycopy(tempByte, 0, strings, offset, tempByte.length);
          offset += name.length();
          strings[offset++] = NULL;
          totalSize += name.length() + 1;
        } else {
          writeShort(strings, offset, (short) name.length());
          offset += 2;
          totalSize += 2;
          byte[] tempByte = name.getBytes(Charset.forName("UTF-16LE"));
          if ((name.length() * 2) != tempByte.length) {
            throw new AndrolibException(String.format(
                "writeTableNameStringBlock UTF-16LE length is different  name %d, tempByte %d\n",
                name.length(),
                tempByte.length
            ));
          }
          System.arraycopy(tempByte, 0, strings, offset, tempByte.length);
          offset += tempByte.length;
          strings[offset++] = NULL;
          strings[offset++] = NULL;
          totalSize += tempByte.length + 2;
        }
      }
    }
    //要保证string size 是4的倍数,要补零
    int size = totalSize - stringsOffset;
    if ((size % 4) != 0) {
      int add = 4 - (size % 4);
      for (i = 0; i < add; i++) {

View on GitHub (pinned to e4df245d82)