apache/dubbo · error · IndexOutOfBoundsException

base642bytes: offset + length > string length.

Error message

base642bytes: offset + length > string length.

What it means

Thrown by the String-alphabet Base64 decoder Bytes.base642bytes(String, int off, int len, String code) when off + len exceeds str.length(). The decoder indexes str.charAt(off + ...) up to off+len-1, so an out-of-range region would otherwise throw a raw StringIndexOutOfBoundsException in the decode loop; this guard surfaces a clear message instead.

Source

Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/io/Bytes.java:627

     *
     * @param str  base64 string.
     * @param off  offset.
     * @param len  length.
     * @param code base64 code(0-63 is base64 char,64 is pad char).
     * @return byte array.
     */
    public static byte[] base642bytes(final String str, final int off, final int len, final String code) {
        if (off < 0) {
            throw new IndexOutOfBoundsException("base642bytes: offset < 0, offset is " + off);
        }
        if (len < 0) {
            throw new IndexOutOfBoundsException("base642bytes: length < 0, length is " + len);
        }
        if (len == 0) {
            return new byte[0];
        }
        if (off + len > str.length()) {
            throw new IndexOutOfBoundsException("base642bytes: offset + length > string length.");
        }

        if (code.length() < 64) {
            throw new IllegalArgumentException("Base64 code length < 64.");
        }

        int rem = len % 4;
        if (rem == 1) {
            throw new IllegalArgumentException("base642bytes: base64 string length % 4 == 1.");
        }

        int num = len / 4, size = num * 3;
        if (code.length() > 64) {
            if (rem != 0) {
                throw new IllegalArgumentException("base642bytes: base64 string length error.");
            }

            char pc = code.charAt(64);

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Derive the region from the string: base642bytes(str, off, str.length() - off, code).
  2. Use base642bytes(str) / base642bytes(str, code) so the string drives the bounds.
  3. Precondition: assert off + len <= str.length() at the producer.

Example fix

// before
byte[] b = Bytes.base642bytes(str, off, str.length(), C64); // off double-counted
// after
byte[] b = Bytes.base642bytes(str, off, str.length() - off, C64);
Defensive patterns

Strategy: validation

Validate before calling

if (off < 0 || len < 0 || off + len > str.length()) {
    throw new IllegalArgumentException("bad region off=" + off + " len=" + len + " str=" + str.length());
}
byte[] b = Bytes.base642bytes(str, off, len, Bytes.C64);

Type guard

static boolean validRegion(String s, int off, int len) {
    return off >= 0 && len >= 0 && off + len <= s.length();
}

Try / catch

try {
    byte[] b = Bytes.base642bytes(str, off, len, Bytes.C64);
} catch (IndexOutOfBoundsException e) {
    throw new IllegalArgumentException("decode region out of bounds", e);
}

Prevention

When it happens

Trigger: Passing offset/length whose sum exceeds the string length, e.g. base642bytes(str, 2, str.length(), code) (offset not subtracted); a length copied from a longer source string.

Common situations: Reusing a length from a larger original after substring; computing remaining bytes as str.length() instead of str.length() - off; truncated/corrupted length on the wire.

Related errors


AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14). Data as JSON: /api/errors/0c3f219acda97385. Report an issue: GitHub.