{"record":{"id":"0673a7fb3f87ae89","repo":"apache/dubbo","slug":"hex2bytes-offset-0-offset-is","errorCode":null,"errorMessage":"hex2bytes: offset < 0, offset is {}","messagePattern":"hex2bytes: offset < 0, offset is (.+?)","errorType":"exception","errorClass":"IndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"dubbo-common/src/main/java/org/apache/dubbo/common/io/Bytes.java","lineNumber":443,"sourceCode":"    public static byte[] hex2bytes(String str) {\n        return hex2bytes(str, 0, str.length());\n    }\n\n    /**\n     * from hex string.\n     *\n     * @param str hex string.\n     * @param off offset.\n     * @param len length.\n     * @return byte array.\n     */\n    public static byte[] hex2bytes(final String str, final int off, int len) {\n        if ((len & 1) == 1) {\n            throw new IllegalArgumentException(\"hex2bytes: ( len & 1 ) == 1.\");\n        }\n\n        if (off < 0) {\n            throw new IndexOutOfBoundsException(\"hex2bytes: offset < 0, offset is \" + off);\n        }\n        if (len < 0) {\n            throw new IndexOutOfBoundsException(\"hex2bytes: length < 0, length is \" + len);\n        }\n        if (off + len > str.length()) {\n            throw new IndexOutOfBoundsException(\"hex2bytes: offset + length > array length.\");\n        }\n\n        int num = len / 2, r = off, w = 0;\n        byte[] b = new byte[num];\n        for (int i = 0; i < num; i++) {\n            b[w++] = (byte) (hex(str.charAt(r++)) << 4 | hex(str.charAt(r++)));\n        }\n        return b;\n    }\n\n    /**\n     * to base64 string.","sourceCodeStart":425,"sourceCodeEnd":461,"githubUrl":"https://github.com/apache/dubbo/blob/3a3043227f5571d25eb2889de5bca22f2914843b/dubbo-common/src/main/java/org/apache/dubbo/common/io/Bytes.java#L425-L461","documentation":"Thrown by Bytes.hex2bytes(String, int, int) when the offset argument is negative. This is the index bounds check for the source string region, running after the even-length check. offset must be within [0, str.length()] so the substring region is valid.","triggerScenarios":"Calling Bytes.hex2bytes(str, off, len) with off < 0. Typically from a parsed/decoded offset that was not range-checked, or a sentinel -1 value.","commonSituations":"Offset computed from a binary field that yielded -1 as 'not found'; index math underflow; passing a cursor that was decremented below zero.","solutions":["Validate offset >= 0 before calling hex2bytes.","Use hex2bytes(String) for the whole string to avoid manual offset.","Range-check parsed offsets against the string length at the parsing boundary."],"exampleFix":"// before\nint off = indexOfHex - 1; // negative if indexOfHex == 0\nbyte[] b = Bytes.hex2bytes(hex, off, len); // throws [155]\n\n// after\nif (off < 0 || off + len > hex.length()) throw new IllegalArgumentException();\nbyte[] b = Bytes.hex2bytes(hex, off, len);","handlingStrategy":"validation","validationCode":"if (off < 0) throw new IllegalArgumentException(\"negative offset: \" + off);\nbyte[] b = Bytes.hex2bytes(str, off, len);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use hex2bytes(String) for the whole string to avoid manual offset.","Range-check parsed offsets against the string length.","Handle -1 'not found' sentinels explicitly."],"tags":["bytes","hex","bounds-check","validation"],"backgroundTag":null,"analyzedSha":"3a3043227f5571d25eb2889de5bca22f2914843b","analyzedAt":"2026-08-14T00:43:19.853Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}