JDK-8305734 : BitSet.get(int, int) always returns the empty BitSet when the Integer.MAX VALUE is set
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util
  • Affected Version: 8,11,17,19,20,21
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2023-04-06
  • Updated: 2025-04-09
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Related Reports
CSR :  
CSR :  
Relates :  
Relates :  
Description
A DESCRIPTION OF THE PROBLEM :
When the Integer.MAX VALUE bit is set, the get(int, int) function always returns a BitSet of size 0.
This is because length() overflows when Integer.MAX VALUE is set and so returns Integer.MIN VALUE.

public BitSet get(int fromIndex, int toIndex) {
    checkRange(fromIndex, toIndex);

    checkInvariants();

    int len = length(); // (*)

    // If no set bits in range return empty bitset
    if (len <= fromIndex || fromIndex == toIndex)
        return new BitSet(0);
    ...

When the comparison len <= fromIndex is done, this always evaluates to true regardless of the value of fromIndex, and as such the function returns BitSet(0).

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create a BitSet with the default constructor, and set the Integer.MAX VALUE bit. Next, set bit 999.
Then do BitSet.get(0, 1000).

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
A BitSet is returned with length = 1000 and size = 1024. In the resulting BitSet, the bit with index 999 is set.
ACTUAL -
A BitSet is returned with length and size = 0. The bit with index 999 is not set.

---------- BEGIN SOURCE ----------
public class BitSetGet {
    public static void main(String[] args) {
        BitSet bitSet = new BitSet(); 
        bitSet.set(Integer.MAX_VALUE);
        bitSet.set(999);  
        BitSet result = bitSet.get(0,1000);
        System.out.println(result.length());
        System.out.println(result.size());
        System.out.println(result.get(999));
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Clients can manually obtain the value of the bits using the get(int) method repeatedly.

Suggested fix: After assigning the output of length() to len, check if len < 0. If so, set len to Integer.MAX VALUE.

int len = length(); // (*)
if ( len < 0 ) len = Integer.MAX_VALUE;

This prevents the len <= fromIndex check being an issue. 
Lowering the length also does not affect the bits that can be accessed by this function. toIndex already cannot be higher than Integer.MAX VALUE, so the Integer.MAX VALUE bit was already inaccessible in this get() function.

FREQUENCY : always



Comments
A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/13388 Date: 2023-04-07 12:22:03 +0000
12-07-2023

The highest bit that can be set is Integer.MAX_VALUE-1, otherwise the "logical size" can't be represented as an int. The set methods probably need to be specified to reject Integer.MAX_VALUE.
07-04-2023

The observations on Windows 10: JDK 8: Failed, BitSet.get returned false. JDK 11: Failed. JDK 17: Failed. JDK 19: Failed. JDK 20: Failed. JDK 21ea+5: Failed.
07-04-2023