diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 889861cac1..d1b5a32531 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -24,6 +24,7 @@
+ Avoid integer overflow when retrieving the last partition from ListUtils.partition().
Fix inverted fixed-size guard in FixedSizeSortedMap.putAll (#722).
Keep existing sort order in ComparatorChain.setComparator (#723).
Update the index on remove via IndexedCollection.iterator() (#724).
diff --git a/src/main/java/org/apache/commons/collections4/ListUtils.java b/src/main/java/org/apache/commons/collections4/ListUtils.java
index d78515c802..9a1cbfac97 100644
--- a/src/main/java/org/apache/commons/collections4/ListUtils.java
+++ b/src/main/java/org/apache/commons/collections4/ListUtils.java
@@ -123,7 +123,7 @@ public List get(final int index) {
throw new IndexOutOfBoundsException("Index " + index + " must be less than size " + listSize);
}
final int start = index * size;
- final int end = Math.min(start + size, list.size());
+ final int end = start + Math.min(size, list.size() - start);
return list.subList(start, end);
}
diff --git a/src/test/java/org/apache/commons/collections4/ListUtilsTest.java b/src/test/java/org/apache/commons/collections4/ListUtilsTest.java
index f64d37e422..1ffe4b52a6 100644
--- a/src/test/java/org/apache/commons/collections4/ListUtilsTest.java
+++ b/src/test/java/org/apache/commons/collections4/ListUtilsTest.java
@@ -25,6 +25,7 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -340,6 +341,27 @@ void testPartition() {
assertEquals(strings, partitionMax.get(0));
}
+ @Test
+ void testPartitionLastPartitionDoesNotOverflow() {
+ final List list = new AbstractList() {
+ @Override
+ public Integer get(final int index) {
+ return index;
+ }
+
+ @Override
+ public int size() {
+ return Integer.MAX_VALUE;
+ }
+ };
+ final int size = (1 << 30) + 1;
+ final List> partition = ListUtils.partition(list, size);
+
+ assertEquals(2, partition.size());
+ assertEquals(Integer.MAX_VALUE - size, partition.get(1).size());
+ assertEquals(size, partition.get(1).get(0));
+ }
+
@Test
void testPredicatedList() {
final Predicate