{"record":{"id":"1a6b382bfbd3d7d8","repo":"spring-projects/spring-security","slug":"invalid-len","errorCode":null,"errorMessage":"Invalid len","messagePattern":"Invalid len","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCrypt.java","lineNumber":231,"sourceCode":"\tprivate int P[] = new int[0];\n\n\tprivate int S[] = new int[0];\n\n\t/**\n\t * Encode a byte array using bcrypt's slightly-modified base64 encoding scheme. Note\n\t * that this is <strong>not</strong> compatible with the standard MIME-base64\n\t * encoding.\n\t * @param d the byte array to encode\n\t * @param len the number of bytes to encode\n\t * @param rs the destination buffer for the base64-encoded string\n\t * @exception IllegalArgumentException if the length is invalid\n\t */\n\tstatic void encode_base64(byte d[], int len, StringBuilder rs) throws IllegalArgumentException {\n\t\tint off = 0;\n\t\tint c1, c2;\n\n\t\tif (len <= 0 || len > d.length) {\n\t\t\tthrow new IllegalArgumentException(\"Invalid len\");\n\t\t}\n\n\t\twhile (off < len) {\n\t\t\tc1 = d[off++] & 0xff;\n\t\t\trs.append(base64_code[(c1 >> 2) & 0x3f]);\n\t\t\tc1 = (c1 & 0x03) << 4;\n\t\t\tif (off >= len) {\n\t\t\t\trs.append(base64_code[c1 & 0x3f]);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tc2 = d[off++] & 0xff;\n\t\t\tc1 |= (c2 >> 4) & 0x0f;\n\t\t\trs.append(base64_code[c1 & 0x3f]);\n\t\t\tc1 = (c2 & 0x0f) << 2;\n\t\t\tif (off >= len) {\n\t\t\t\trs.append(base64_code[c1 & 0x3f]);\n\t\t\t\tbreak;\n\t\t\t}","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCrypt.java#L213-L249","documentation":"BCrypt.encode_base64() encodes len bytes of d into bcrypt's custom base64 alphabet. It throws this IllegalArgumentException when len is <= 0 or exceeds d.length, i.e. when asked to encode zero bytes or more bytes than the array holds. This is an internal-argument sanity check protecting against buffer overreads.","triggerScenarios":"Calling encode_base64 with len <= 0 or len > d.length — typically via hashpw or gensalt with corrupted internal state, or direct calls with a wrong length argument.","commonSituations":"Direct use of BCrypt internals (package-private/static misuse); modified forks of BCrypt.java passing wrong offsets; empty input byte arrays reaching hashing internals.","solutions":["Check that the byte array passed to hashpw/gensalt is non-empty and correctly sized (salt: 16 raw bytes)","Do not call encode_base64 directly; use the public hashpw(String, String) API","If you forked BCrypt.java, audit the len/offset arithmetic at the call site"],"exampleFix":"// before\nBCrypt.encode_base64(new byte[0], 8, sb); // len > d.length\n// after\nbyte[] data = Arrays.copyOf(saltBytes, 16); // ensure capacity >= len\nBCrypt.encode_base64(data, 16, sb);","handlingStrategy":"try-catch","validationCode":"static boolean canEncode(byte[] d, int len) {\n    return len > 0 && len <= d.length;\n}","typeGuard":"if (data == null || data.length == 0) throw new IllegalArgumentException(\"data must be non-empty\");","tryCatchPattern":"try {\n    BCrypt.encode_base64(data, len, sb);\n} catch (IllegalArgumentException e) {\n    throw new IllegalStateException(\"encode_base64 length invariant violated: \" + e.getMessage(), e);\n}","preventionTips":["Avoid calling BCrypt internals directly; use hashpw/gensalt","Ensure salt byte arrays are exactly 16 bytes for bcrypt","Don't modify forked BCrypt length/offset arithmetic without tests"],"tags":["bcrypt","base64","input-validation","java","spring-security"],"backgroundTag":"invalid-argument-value","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}