{"record":{"id":"14ce8c149fe43cec","repo":"apache/dubbo","slug":"bytes2base64-length-0-length-is","errorCode":null,"errorMessage":"bytes2base64: length < 0, length is {}","messagePattern":"bytes2base64: length < 0, length is (.+?)","errorType":"exception","errorClass":"IndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"dubbo-common/src/main/java/org/apache/dubbo/common/io/Bytes.java","lineNumber":531,"sourceCode":"    public static String bytes2base64(byte[] b, char[] code) {\n        return bytes2base64(b, 0, b.length, code);\n    }\n\n    /**\n     * to base64 string.\n     *\n     * @param bs   byte array.\n     * @param off  offset.\n     * @param len  length.\n     * @param code base64 code(0-63 is base64 char,64 is pad char).\n     * @return base64 string.\n     */\n    public static String bytes2base64(final byte[] bs, final int off, final int len, final char[] code) {\n        if (off < 0) {\n            throw new IndexOutOfBoundsException(\"bytes2base64: offset < 0, offset is \" + off);\n        }\n        if (len < 0) {\n            throw new IndexOutOfBoundsException(\"bytes2base64: length < 0, length is \" + len);\n        }\n        if (off + len > bs.length) {\n            throw new IndexOutOfBoundsException(\"bytes2base64: offset + length > array length.\");\n        }\n\n        if (code.length < 64) {\n            throw new IllegalArgumentException(\"Base64 code length < 64.\");\n        }\n\n        boolean pad = code.length > 64; // has pad char.\n        int num = len / 3, rem = len % 3, r = off, w = 0;\n        char[] cs = new char[num * 4 + (rem == 0 ? 0 : pad ? 4 : rem + 1)];\n\n        for (int i = 0; i < num; i++) {\n            int b1 = bs[r++] & MASK8, b2 = bs[r++] & MASK8, b3 = bs[r++] & MASK8;\n\n            cs[w++] = code[b1 >> 2];\n            cs[w++] = code[(b1 << 4) & MASK6 | (b2 >> 4)];","sourceCodeStart":513,"sourceCodeEnd":549,"githubUrl":"https://github.com/apache/dubbo/blob/3a3043227f5571d25eb2889de5bca22f2914843b/dubbo-common/src/main/java/org/apache/dubbo/common/io/Bytes.java#L513-L549","documentation":"Thrown by the canonical Base64 encoder Bytes.bytes2base64(byte[], int off, int len, char[] code) when the supplied region length `len` is negative. The encoder sizes its output char array from `len`, so a negative length is meaningless; the method fails fast with IndexOutOfBoundsException instead of allocating a bogus buffer or producing corrupt output. All convenience overloads (bytes2base64(byte[]), bytes2base64(byte[],int,int), bytes2base64(byte[],String), etc.) eventually forward `len` to this check.","triggerScenarios":"Calling bytes2base64(bs, off, len, code) with len < 0; or a convenience overload where the caller computed len = endIndex - startIndex with endIndex < startIndex; or passing -1 as a 'to-end' sentinel (this API has no sentinel semantics).","commonSituations":"Off-by-one when slicing a sub-array before encoding; a length field that defaults to -1 and was never set; code ported from an API where -1 meant 'rest of array'; serialized payload whose declared length is negative due to truncation.","solutions":["Compute the length defensively before calling: int len = Math.max(0, end - start);","Prefer a convenience overload that derives the length for you: bytes2base64(byte[]) or bytes2base64(byte[], int offset, int length) with a validated length.","Add a precondition at the producer that computes `len` so the bad value is surfaced at its source."],"exampleFix":"// before\nint len = end - start; // can be negative if end < start\nString s = Bytes.bytes2base64(bs, off, len, Bytes.BASE64);\n// after\nint len = Math.max(0, end - start);\nString s = Bytes.bytes2base64(bs, off, len, Bytes.BASE64);","handlingStrategy":"validation","validationCode":"if (len < 0) throw new IllegalArgumentException(\"len must be >= 0, got \" + len);\nString s = Bytes.bytes2base64(bs, off, len, Bytes.BASE64);","typeGuard":null,"tryCatchPattern":"try {\n    String s = Bytes.bytes2base64(bs, off, len, Bytes.BASE64);\n} catch (IndexOutOfBoundsException e) {\n    // external/untrusted offset/length — log and reject the input\n    throw new IllegalArgumentException(\"invalid encode region\", e);\n}","preventionTips":["Never use -1 as a length sentinel for this API.","Derive length from array bounds (bs.length - off) instead of computing it separately.","Prefer the bytes2base64(byte[]) convenience overload when encoding the whole array."],"tags":["base64","encoding","bounds-check","validation","dubbo-common"],"backgroundTag":null,"analyzedSha":"3a3043227f5571d25eb2889de5bca22f2914843b","analyzedAt":"2026-08-14T00:43:19.853Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}