{"record":{"id":"79ac1a69c5175dfe","repo":"shwenzhang/AndResGuard","slug":"writespecnamestringblock-s-utf-8-length-is-different-name-d","errorCode":null,"errorMessage":"writeSpecNameStringBlock %s UTF-8 length is different name %d, tempByte %d\n","messagePattern":"writeSpecNameStringBlock (.+?) 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":161,"sourceCode":"    byte[] stringBytes = new byte[size * 2];\n    int offset = 0;\n    int i = 0;\n    curSpecNameToPos.clear();\n\n    for (Iterator<String> it = specNames.keySet().iterator(); it.hasNext(); ) {\n      stringOffsets[i] = offset;\n      String name = it.next();\n      for (String specName : specNames.get(name)) {\n        // N res entry item point to one string constant\n        curSpecNameToPos.put(specName, i);\n      }\n      if (isUTF8) {\n        stringBytes[offset++] = (byte) name.length();\n        stringBytes[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              \"writeSpecNameStringBlock %s UTF-8 length is different name %d, tempByte %d\\n\",\n              name,\n              name.length(),\n              tempByte.length\n          ));\n        }\n        System.arraycopy(tempByte, 0, stringBytes, offset, tempByte.length);\n        offset += name.length();\n        stringBytes[offset++] = NULL;\n        totalSize += name.length() + 1;\n      } else {\n        writeShort(stringBytes, 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              \"writeSpecNameStringBlock %s UTF-16LE length is different name %d, tempByte %d\\n\",","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/shwenzhang/AndResGuard/blob/e4df245d82f27d9a2d0dd108260a3510cbaba849/AndResGuard-core/src/main/java/com/tencent/mm/androlib/res/decoder/StringBlock.java#L143-L179","documentation":"When writing a spec-name string in UTF-8 mode, the writer reserves 2 bytes for the two length fields and casts name.length() to byte. Java's String.length() counts UTF-16 code units, which differs from UTF-8 byte length whenever the name contains non-ASCII characters, so the consistency check name.length() != tempByte.length throws AndrolibException.","triggerScenarios":"writeSpecNameStringBlock with isUTF8 == true and a resource name whose UTF-8 byte length differs from its Java char count (non-ASCII or multi-byte characters, or names longer than 255 bytes cast into a byte).","commonSituations":"Apps with non-English resource entry names (Chinese, emoji, accented characters) in resources.arsc being obfuscated; also very long names exceeding 127/255-byte single-byte length encoding.","solutions":["Rename the offending resources to ASCII-only names in the source project (most robust fix).","Ensure resource shrinking/obfuscation runs so names are replaced with short ASCII names before this writer executes.","Patch StringBlock to compute the actual UTF-8 byte length and write multi-byte length fields (varint) instead of casting to byte.","Locate the failing name from the message text and fix it in res/ values files."],"exampleFix":"// before\nstringBytes[offset++] = (byte) name.length();\n// after\nbyte[] utf8 = name.getBytes(StandardCharsets.UTF_8);\nstringBytes[offset++] = (byte) utf8.length;\nstringBytes[offset++] = (byte) utf8.length;","handlingStrategy":"validation","validationCode":"// Caller-side check before obfuscation\nstatic boolean isAsciiSafe(String name) {\n  return name.chars().allMatch(c -> c > 0 && c < 128);\n}\n// scan aapt2 output / res names: if (!isAsciiSafe(resName)) flagForRename(resName);","typeGuard":null,"tryCatchPattern":"try { ... } catch (AndrolibException e) { if (e.getMessage().contains(\"UTF-8 length is different\")) { /* report the offending resource name from the message and fail the build with a clear hint */ } else throw e; }","preventionTips":["Enforce ASCII-only resource names via lint/custom check in the project.","Enable resource obfuscation so original names are replaced with short ASCII ones.","Avoid emoji and accented characters in resource entry names.","CI: scan res/ filenames and value entry names for non-ASCII before release."],"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"}