diff --git a/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/singlerange/SingleRange.java b/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/singlerange/SingleRange.java index 9302f51763f..b99bbefbe3c 100644 --- a/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/singlerange/SingleRange.java +++ b/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/singlerange/SingleRange.java @@ -204,6 +204,15 @@ public final OrderedLongSet ixRemove(final long key) { return OrderedLongSet.twoRanges(rangeStart(), key - 1, key + 1, rangeEnd()); } + private static long addSaturated(final long x, final long y) { + // we know x >= 0, y >= 0. + final long res = x + y; + if (res < 0) { + return Long.MAX_VALUE; + } + return res; + } + @Override public final OrderedLongSet ixSubindexByPosOnNew(final long startPos, final long endPosExclusive) { final long endPos = endPosExclusive - 1; // make inclusive. @@ -219,8 +228,8 @@ public final OrderedLongSet ixSubindexByPosOnNew(final long startPos, final long return ixCowRef(); } return make( - Math.max(rangeStart() + startPos, rangeStart()), - Math.min(rangeStart() + endPos, rangeEnd())); + rangeStart() + startPos, // cannot overflow given previous checks: startPos < cardinality + Math.min(addSaturated(rangeStart(), endPos), rangeEnd())); } @Override diff --git a/engine/rowset/src/test/java/io/deephaven/engine/rowset/impl/SingleRangeTest.java b/engine/rowset/src/test/java/io/deephaven/engine/rowset/impl/SingleRangeTest.java index 68e2950afc3..c171daac05a 100644 --- a/engine/rowset/src/test/java/io/deephaven/engine/rowset/impl/SingleRangeTest.java +++ b/engine/rowset/src/test/java/io/deephaven/engine/rowset/impl/SingleRangeTest.java @@ -462,4 +462,14 @@ public void testRowSequenceIteratorAdvanceRegression0() { assertTrue(valid); assertEquals(1000, rsIt.peekNextKey()); } + + @Test + public void testSaturation() { + final long first = 1073741821; + final long last = first + 6; + final SingleRange sr = SingleRange.make(first, last); + final OrderedLongSet res = sr.ixSubindexByPosOnNew(5, Long.MAX_VALUE); + assertEquals(last - 1, res.ixFirstKey()); + assertEquals(last, res.ixLastKey()); + } }