This is an automated email from the ASF dual-hosted git repository.
Cole-Greer pushed a commit to branch 3.8-dev
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/3.8-dev by this push:
new d929579f05 CTR: Fix integer range literal parsing to reject overflow
and endpoint cases
d929579f05 is described below
commit d929579f051f2358445e8b1e18d52c35a32b66c7
Author: Cole Greer <[email protected]>
AuthorDate: Wed Oct 28 17:19:05 2026 -0700
CTR: Fix integer range literal parsing to reject overflow and endpoint cases
The range size guard used signed int arithmetic (Math.abs(start - end)),
which int subtraction overflow and Math.abs(Integer.MIN_VALUE) could slip
past, and the inclusive int loop wrapped around for ranges at the int
min/max bounds. Compute the width in long for the limit check and drive
the loop by that bounded count.
Assisted-by: Kiro:claude-opus-4.8
---
CHANGELOG.asciidoc | 1 +
.../language/grammar/GenericLiteralVisitor.java | 26 +++++++++-------------
.../grammar/GeneralLiteralVisitorTest.java | 12 +++++++++-
3 files changed, 22 insertions(+), 17 deletions(-)
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index f568cbec14..0858931f70 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -28,6 +28,7 @@
image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
This release also includes changes from prior 3.7.x releases.
* Fixed `AddPropertyStep` not passing the old property to `EventStrategy`
listeners when the cardinality was not specified in `property()`.
+* Fixed integer range literal parsing in Gremlin-Lang where certain ranges
bypassed the range size limit.
[[release-3-8-2]]
=== TinkerPop 3.8.2 (Release Date: September 1, 2026)
diff --git
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
index fe43ad24f7..9a92081d7c 100644
---
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
+++
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
@@ -189,28 +189,22 @@ public class GenericLiteralVisitor extends
DefaultGremlinBaseVisitor<Object> {
* @return : return an object which is type of array of object, and each
object is a Integer inside the range.
*/
private static Object createIntegerRange(final int start, final int end,
final String range) {
- final List<Object> results = new ArrayList<>();
- int total_result_count = Math.abs(start - end);
+ // Compute the gap between endpoints in long arithmetic so the limit
check cannot be bypassed by
+ // int subtraction overflow (e.g. MIN..MAX) or by
Math.abs(Integer.MIN_VALUE) remaining negative.
+ final long total_result_count = Math.abs((long) start - (long) end);
// validate result count not exceeding limit
if (total_result_count > TOTAL_INTEGER_RANGE_RESULT_COUNT_LIMIT) {
throw new IllegalArgumentException("Range " + range + " is too
wide. Current limit is " + TOTAL_INTEGER_RANGE_RESULT_COUNT_LIMIT + " items");
}
- if (start <= end) {
- // handle start <= end
- int cur = start;
- while (cur <= end) {
- results.add(cur);
- cur++;
- }
- } else {
- // handle start > end
- int cur = start;
- while (cur >= end) {
- results.add(cur);
- cur--;
- }
+ final List<Object> results = new ArrayList<>((int)
total_result_count+1);
+
+ final int step = (start <= end) ? 1 : -1;
+ int cur = start;
+ for (int i = 0; i <= total_result_count; i++) {
+ results.add(cur);
+ cur += step;
}
return results;
diff --git
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
index f590f6212d..e3478ec3b7 100644
---
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
+++
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
@@ -80,6 +80,12 @@ public class GeneralLiteralVisitorTest {
{1, 1000000},
{1, 1},
{1000000, 1},
+ // endpoint cases where an inclusive int loop would wrap
around past the endpoint
+ {Integer.MAX_VALUE, Integer.MAX_VALUE},
+ {Integer.MIN_VALUE, Integer.MIN_VALUE},
+ {Integer.MAX_VALUE - 1, Integer.MAX_VALUE},
+ {Integer.MIN_VALUE, Integer.MIN_VALUE + 1},
+ {Integer.MIN_VALUE + 1, Integer.MIN_VALUE},
});
}
@@ -119,6 +125,10 @@ public class GeneralLiteralVisitorTest {
return Arrays.asList(new Object[][]{
{0, 10000000},
{10000000, 1},
+ // widths that overflow signed int arithmetic and used to
slip past the guard:
+ // Math.abs(start - end) == Integer.MIN_VALUE (stays
negative), and start - end overflow
+ {-1073741824, 1073741824},
+ {Integer.MIN_VALUE, Integer.MAX_VALUE},
});
}
@@ -127,7 +137,7 @@ public class GeneralLiteralVisitorTest {
*/
@Test(expected = IllegalArgumentException.class)
public void shouldNotParse() {
- assertThat(Math.abs(end - start),
greaterThanOrEqualTo(GenericLiteralVisitor.TOTAL_INTEGER_RANGE_RESULT_COUNT_LIMIT));
+ assertThat(Math.abs((long) start - (long) end),
greaterThanOrEqualTo((long)
GenericLiteralVisitor.TOTAL_INTEGER_RANGE_RESULT_COUNT_LIMIT));
parseGenericLiteralRange(String.format("%d..%d", start, end));
}
}