RFR: 6187113: DefaultListSelectionModel.removeIndexInterval(0, Integer.MAX_VALUE) fails [v5]
Alexey Ivanov
aivanov at openjdk.org
Fri Oct 14 19:51:00 UTC 2022
On Fri, 14 Oct 2022 09:16:27 GMT, Prasanta Sadhukhan <psadhukhan at openjdk.org> wrote:
>> DefaultListSelectionModel.removeIndexInterva accepts `int` value which allows it to take in Integer.MAX_VALUE theoratically but it does calculation with that value which can results in IOOBE.
>> Fix is to make sure the calculation stays within bounds.
>
> Prasanta Sadhukhan has updated the pull request incrementally with one additional commit since the last revision:
>
> javadoc update
I was wrong, disallowing `Integer.MAX_VALUE` for `setSelectionInterval` is **not enough**. Moreover, if `Integer.MAX_VALUE` isn't accepted for `setSelectionInterval` and `removeIndexInterval`, it should be rejected in other places too. Otherwise, `selectionModel.isSelectedIndex(Integer.MAX_VALUE))` being valid looks inconsistent.
Even when the `gapLength` remains positive, the following loop could throw IOOBE because a negative index being accessed. The following code
selectionModel.setSelectionInterval(Integer.MAX_VALUE - 2, Integer.MAX_VALUE - 1);
selectionModel.removeIndexInterval(0, Integer.MAX_VALUE - 1);
throws
Exception in thread "main" java.lang.IndexOutOfBoundsException: bitIndex < 0: -2147483648
at java.base/java.util.BitSet.get(BitSet.java:626)
at java.desktop/javax.swing.DefaultListSelectionModel.removeIndexInterval(DefaultListSelectionModel.java:713)
at SelectionModelTest.main(SelectionModelTest.java)
where line 713 https://github.com/openjdk/jdk/blob/ee43bd8db4c378c8cecdf5051cbaa6ac177d3592/src/java.desktop/share/classes/javax/swing/DefaultListSelectionModel.java#L713
I suggested the code to fix that problem.
Then the infinite loop in `changeSelection` https://github.com/openjdk/jdk/blob/ee43bd8db4c378c8cecdf5051cbaa6ac177d3592/src/java.desktop/share/classes/javax/swing/DefaultListSelectionModel.java#L432
for `MAX_VALUE` is resolved by reversing it:
- for(int i = Math.min(setMin, clearMin); i <= Math.max(setMax, clearMax); i++) {
+ for(int i = Math.max(setMax, clearMax); i >= Math.min(setMin, clearMin); i--) {
The proposed changes will resolve the bug.
src/java.desktop/share/classes/javax/swing/DefaultListSelectionModel.java line 707:
> 705: int rmMinIndex = Math.min(index0, index1);
> 706: int rmMaxIndex = Math.max(index0, index1);
> 707: int gapLength = (rmMaxIndex - rmMinIndex) + 1;
Suggestion:
int gapLength = (rmMaxIndex - rmMinIndex) == Integer.MAX_VALUE
? Integer.MAX_VALUE
: (rmMaxIndex - rmMinIndex) + 1;
This ensures `gapLength` remains positive. (The condition `(rmMaxIndex - rmMinIndex) == Integer.MAX_VALUE` is `true` if and only if `rmMinIndex == 0 && rmMaxIndex == Integer.MAX_VALUE`.)
src/java.desktop/share/classes/javax/swing/DefaultListSelectionModel.java line 714:
> 712: for(int i = rmMinIndex; i <= maxIndex; i++) {
> 713: setState(i, value.get(i + gapLength));
> 714: }
The `for`-loop should look like this:
for(int i = rmMinIndex; i >= 0 && i <= maxIndex; i++) {
setState(i, (i <= Integer.MAX_VALUE - gapLength)
&& (i + gapLength >= minIndex)
&& value.get(i + gapLength));
}
It breaks if `i` becomes negative. In the body, the first condition `(i <= Integer.MAX_VALUE - gapLength)` prevents accessing indexes greater than `Integer.MAX_VALUE`, the second condition `(i + gapLength >= minIndex)` is an optimisation, the values for indexes below `minIndex` are `false`, so the call to `value.get` is skipped. (The second condition is not required.)
-------------
Changes requested by aivanov (Reviewer).
PR: https://git.openjdk.org/jdk/pull/10409
More information about the client-libs-dev
mailing list