{"record":{"id":"47137c2dc1ab5cbc","repo":"Tencent/tinker","slug":"name-too-long-utf-8-bytes","errorCode":null,"errorMessage":"Name too long: {} UTF-8 bytes","messagePattern":"Name too long: (.+?) UTF-8 bytes","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"third-party/tinker-ziputils/src/main/java/com/tencent/tinker/ziputils/ziputil/AlignedZipOutputStream.java","lineNumber":336,"sourceCode":"                throw new ZipException(\"STORED entry missing size\");\r\n            }\r\n            if (ze.getSize() != ze.getCompressedSize()) {\r\n                throw new ZipException(\"STORED entry size/compressed size mismatch\");\r\n            }\r\n        }\r\n\r\n        checkOpen();\r\n\r\n        if (entries.contains(ze.getName())) {\r\n            throw new ZipException(\"Entry already exists: \" + ze.getName());\r\n        }\r\n        if (entries.size() == 64*1024-1) {\r\n            throw new ZipException(\"Too many entries for the zip file format's 16-bit entry count\");\r\n        }\r\n        nameBytes = ze.getName().getBytes(Charset.forName(\"UTF-8\"));\r\n        nameLength = nameBytes.length;\r\n        if (nameLength > 0xffff) {\r\n            throw new IllegalArgumentException(\"Name too long: \" + nameLength + \" UTF-8 bytes\");\r\n        }\r\n\r\n        def.setLevel(compressionLevel);\r\n        ze.setMethod(method);\r\n\r\n        currentEntry = ze;\r\n        entries.add(currentEntry.getName());\r\n\r\n        // Local file header.\r\n        // http://www.pkware.com/documents/casestudies/APPNOTE.TXT\r\n        int flags = (method == STORED) ? 0 : GPBF_DATA_DESCRIPTOR_FLAG;\r\n        // Java always outputs UTF-8 filenames. (Before Java 7, the RI didn't set this flag and used\r\n        // modified UTF-8. From Java 7, it sets this flag and uses normal UTF-8.)\r\n        flags |= GPBF_UTF8_FLAG;\r\n        writeLong(out, LOCSIG); // Entry header\r\n        writeShort(out, ZIPLocalHeaderVersionNeeded); // Extraction version\r\n        writeShort(out, flags);\r\n        writeShort(out, method);\r","sourceCodeStart":318,"sourceCodeEnd":354,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/third-party/tinker-ziputils/src/main/java/com/tencent/tinker/ziputils/ziputil/AlignedZipOutputStream.java#L318-L354","documentation":"Entry names are stored in zip headers with a 16-bit length field, so a name longer than 65,535 UTF-8 bytes cannot be encoded. putNextEntry encodes the name to UTF-8 and throws IllegalArgumentException (not ZipException) when the encoded length exceeds 0xffff. Note the limit is on bytes, not characters, so multi-byte characters reduce the character budget.","triggerScenarios":"putNextEntry with a name whose UTF-8 encoding exceeds 65,535 bytes — deeply nested generated paths, hash-suffixed names, or a bug that concatenates path segments in a loop.","commonSituations":"Generated archives with unbounded name construction (e.g. appending suffixes per iteration); packaging user-supplied paths without length validation; encoding surprises where a name that fits in chars overflows in bytes due to CJK or emoji content.","solutions":["Validate/limit entry name length (encoded UTF-8 bytes) at the point names are constructed; reject or truncate-and-slug long names.","Flatten directory structure or shorten prefixes for generated entries (shorten the common root rather than each leaf).","If genuinely long names are required, store them in a manifest entry inside the zip and use short placeholder entry names."],"exampleFix":"// before: unbounded generated name\nzos.putNextEntry(new ZipEntry(baseDir + \"/\" + repeatedSuffix(i))); // may exceed 64Ki bytes\n\n// after: validate encoded length before creating the entry\nString name = baseDir + \"/\" + repeatedSuffix(i);\nif (name.getBytes(StandardCharsets.UTF_8).length > 0xffff) {\n    throw new IllegalArgumentException(\"entry name too long: \" + name);\n}\nzos.putNextEntry(new ZipEntry(name));","handlingStrategy":"validation","validationCode":"// Validate encoded name length before constructing the entry\nstatic void checkEntryName(String name) {\n    int len = name.getBytes(java.nio.charset.StandardCharsets.UTF_8).length;\n    if (len > 0xffff) throw new IllegalArgumentException(\"entry name too long: \" + len + \" UTF-8 bytes\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    zos.putNextEntry(new java.util.zip.ZipEntry(name));\n} catch (IllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Name too long\")) {\n        name = shorten(name); // truncate/slug and continue\n        zos.putNextEntry(new java.util.zip.ZipEntry(name));\n    } else {\n        throw e;\n    }\n}","preventionTips":["Cap generated path depth and suffix length at construction time.","Remember the limit is UTF-8 bytes, not characters, when names contain non-ASCII text.","Fuzz-test name generators in builds that create names from unbounded input."],"tags":["zip","name-length","utf8","tinker"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}