{"record":{"id":"3891d42764bcd256","repo":"shwenzhang/AndResGuard","slug":"writetablenamestringblock-utf-8-length-is-different-name-d","errorCode":null,"errorMessage":"writeTableNameStringBlock UTF-8 length is different  name %d, tempByte %d\n","messagePattern":"writeTableNameStringBlock UTF-8 length is different  name (.+?), tempByte (.+?)\n","errorType":"exception","errorClass":"AndrolibException","httpStatus":null,"severity":"error","filePath":"AndResGuard-core/src/main/java/com/tencent/mm/androlib/res/decoder/StringBlock.java","lineNumber":288,"sourceCode":"    for (i = 0; i < stringCount; i++) {\n      stringOffsets[i] = offset;\n      //如果找不到即没混淆这一项,直接拷贝\n      if (tableProguardMap.get(i) == null) {\n        //需要区分是否是最后一项\n        int copyLen = (i == (stringCount - 1)) ? (block.m_strings.length - block.m_stringOffsets[i])\n            : (block.m_stringOffsets[i + 1] - block.m_stringOffsets[i]);\n        System.arraycopy(block.m_strings, block.m_stringOffsets[i], strings, offset, copyLen);\n        offset += copyLen;\n        totalSize += copyLen;\n      } else {\n        String name = tableProguardMap.get(i);\n        if (block.m_isUTF8) {\n          strings[offset++] = (byte) name.length();\n          strings[offset++] = (byte) name.length();\n          totalSize += 2;\n          byte[] tempByte = name.getBytes(Charset.forName(\"UTF-8\"));\n          if (name.length() != tempByte.length) {\n            throw new AndrolibException(String.format(\n                \"writeTableNameStringBlock UTF-8 length is different  name %d, tempByte %d\\n\",\n                name.length(),\n                tempByte.length\n            ));\n          }\n          System.arraycopy(tempByte, 0, strings, offset, tempByte.length);\n          offset += name.length();\n          strings[offset++] = NULL;\n          totalSize += name.length() + 1;\n        } else {\n          writeShort(strings, offset, (short) name.length());\n          offset += 2;\n          totalSize += 2;\n          byte[] tempByte = name.getBytes(Charset.forName(\"UTF-16LE\"));\n          if ((name.length() * 2) != tempByte.length) {\n            throw new AndrolibException(String.format(\n                \"writeTableNameStringBlock UTF-16LE length is different  name %d, tempByte %d\\n\",\n                name.length(),","sourceCodeStart":270,"sourceCodeEnd":306,"githubUrl":"https://github.com/shwenzhang/AndResGuard/blob/e4df245d82f27d9a2d0dd108260a3510cbaba849/AndResGuard-core/src/main/java/com/tencent/mm/androlib/res/decoder/StringBlock.java#L270-L306","documentation":"In the UTF-8 branch of writeTableNameStringBlock, the writer casts name.length() (Java UTF-16 char count) to a byte as the pool's length field and asserts the UTF-8 encoding length equals it. For non-ASCII names (multi-byte UTF-8) or names longer than 127 bytes, the lengths differ and AndrolibException is thrown.","triggerScenarios":"writeTableNameStringBlock with block.m_isUTF8 == true and a resource-table name whose UTF-8 byte length != name.length() (non-ASCII characters or length > byte range).","commonSituations":"Apps whose resource entries use localized/non-ASCII names, or libraries shipping resources with special characters in their names, being processed by AndResGuard.","solutions":["Rename non-ASCII resource entries to ASCII-only names in the source project.","Ensure AndResGuard's name obfuscation is enabled so the original (non-ASCII) names are replaced before writing.","Patch the writer to encode the actual UTF-8 byte length instead of casting String.length().","Identify the resource from the name field in the message and fix it in res/values."],"exampleFix":"// before\nstrings[offset++] = (byte) name.length();\nstrings[offset++] = (byte) name.length();\n// after\nbyte[] utf8 = name.getBytes(StandardCharsets.UTF_8);\nstrings[offset++] = (byte) utf8.length;\nstrings[offset++] = (byte) utf8.length;","handlingStrategy":"validation","validationCode":"static boolean utf8Safe(String name) {\n  return name.getBytes(StandardCharsets.UTF_8).length == name.length()\n      && name.length() <= 127;\n}\n// ensure every resource-table name passes utf8Safe before obfuscation","typeGuard":null,"tryCatchPattern":"try { ... } catch (AndrolibException e) { if (e.getMessage().contains(\"UTF-8 length is different\")) { /* extract resource name from the log and fail with a rename hint */ } else throw e; }","preventionTips":["Keep resource and table names pure ASCII and short (<127 bytes).","Run a pre-build lint that rejects non-ASCII resource identifiers.","Enable AndResGuard obfuscation so original names are replaced before the writer runs.","Review bundled library resources for non-ASCII names."],"tags":["android","resources-arsc","utf-8","encoding"],"backgroundTag":"encoding-length-mismatch","analyzedSha":"e4df245d82f27d9a2d0dd108260a3510cbaba849","analyzedAt":"2026-09-12T17:49:07.798Z","contentChangedAt":"2026-09-12T17:49:07.798Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}