{"record":{"id":"540e879d3f83d548","repo":"apache/pulsar","slug":"fromindex-fromindex-toindex-toindex","errorCode":null,"errorMessage":"fromIndex: <fromIndex> > toIndex: <toIndex>","messagePattern":"fromIndex: <fromIndex> > toIndex: <toIndex>","errorType":"validation","errorClass":"IndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"pulsar-common/src/main/java/org/apache/pulsar/common/util/collections/BitSetRecyclable.java","lineNumber":343,"sourceCode":"     */\n    private void expandTo(int wordIndex) {\n        int wordsRequired = wordIndex+1;\n        if (wordsInUse < wordsRequired) {\n            ensureCapacity(wordsRequired);\n            wordsInUse = wordsRequired;\n        }\n    }\n\n    /**\n     * Checks that fromIndex ... toIndex is a valid range of bit indices.\n     */\n    private static void checkRange(int fromIndex, int toIndex) {\n        if (fromIndex < 0)\n            throw new IndexOutOfBoundsException(\"fromIndex < 0: \" + fromIndex);\n        if (toIndex < 0)\n            throw new IndexOutOfBoundsException(\"toIndex < 0: \" + toIndex);\n        if (fromIndex > toIndex)\n            throw new IndexOutOfBoundsException(\"fromIndex: \" + fromIndex +\n                \" > toIndex: \" + toIndex);\n    }\n\n    /**\n     * Sets the bit at the specified index to the complement of its\n     * current value.\n     *\n     * @param  bitIndex the index of the bit to flip\n     * @throws IndexOutOfBoundsException if the specified index is negative\n     * @since  1.4\n     */\n    public void flip(int bitIndex) {\n        if (bitIndex < 0)\n            throw new IndexOutOfBoundsException(\"bitIndex < 0: \" + bitIndex);\n\n        int wordIndex = wordIndex(bitIndex);\n        expandTo(wordIndex);\n","sourceCodeStart":325,"sourceCodeEnd":361,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-common/src/main/java/org/apache/pulsar/common/util/collections/BitSetRecyclable.java#L325-L361","documentation":"BitSetRecyclable.checkRange validates index ranges for the range-based flip(int,int), set(int,int) and clear(int,int) methods (and the get(int,int) read path). When fromIndex is greater than toIndex the range is empty/malformed, so the method throws IndexOutOfBoundsException instead of silently doing nothing. It is a caller-contract violation mirroring java.util.BitSet semantics.","triggerScenarios":"Calling BitSetRecyclable.flip(int,int), set(int,int), clear(int,int) or get(int,int) with fromIndex > toIndex, e.g. after swapping variables, computing indices from min/max incorrectly, or building a range from user input where the start can exceed the end.","commonSituations":"Batch-acknowledgment code computing message ranges from data where the range is inverted (end before start after sorting changes); off-by-one loops passing (i, j) in the wrong order; refactoring a single-bit call into a range call and swapping arguments.","solutions":["Check the call site and ensure arguments are passed as (fromIndex, toIndex) with fromIndex <= toIndex","Guard or normalize the range before calling: fromIndex = Math.min(a,b); toIndex = Math.max(a,b)","Skip the call when the range is empty (fromIndex == toIndex only clears/sets nothing for ranges) or log the source of the inverted range","Add a unit test covering inverted ranges if the indices come from user/protocol data"],"exampleFix":"// before\nbitSet.flip(endIndex, startIndex);\n// after\nif (startIndex <= endIndex) {\n    bitSet.flip(startIndex, endIndex);\n}","handlingStrategy":"validation","validationCode":"if (fromIndex < 0 || toIndex < 0) throw new IllegalArgumentException(\"negative index\");\nif (fromIndex > toIndex) throw new IllegalArgumentException(\"fromIndex \" + fromIndex + \" > toIndex \" + toIndex);","typeGuard":null,"tryCatchPattern":"try {\n    bitSet.set(fromIndex, toIndex);\n} catch (IndexOutOfBoundsException e) {\n    LOG.warn(\"invalid range [{}, {}]\", fromIndex, toIndex, e);\n}","preventionTips":["Normalize ranges with Math.min/Math.max before calling","Keep (from, to) argument order consistent; avoid positional swaps in refactors","Validate user/protocol-derived ranges at the boundary","Unit-test inverted and empty ranges"],"tags":["java","bitset","index-out-of-bounds","argument-validation"],"backgroundTag":"index-out-of-bounds","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}