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
- Rename resources containing emoji or supplementary characters to ASCII identifiers.
- Keep resource-name obfuscation enabled so original names never reach the string-pool writer.
- Patch validation to compare encoded length against the value actually written (counting code points).
- 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
- Forbid emoji and astral-plane characters in resource names.
- Prefer UTF-8 pools with short ASCII names so the strict checks pass trivially.
- Test AndResGuard output on release builds before shipping.
- Audit third-party AAR resources for exotic names during dependency review.
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
- writeSpecNameStringBlock
- writeSpecNameStringBlock
- writeTableNameStringBlock UTF-8 length is different name
- Style data size is not multiple of 4
- writeSpecNameStringBlock styleOffsetCount != 0 …
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)