This is an automated email from the ASF dual-hosted git repository.

tanner pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git

commit 1dd1b4ac85bd16ecb5acb77a4649c869e3267e35
Author: Mihai Budiu <[email protected]>
AuthorDate: Wed Jun 28 23:18:08 2023 -0700

    [CALCITE-5810] Prevent overflow in substring length computation
    
    Signed-off-by: Mihai Budiu <[email protected]>
---
 .../src/main/java/org/apache/calcite/runtime/SqlFunctions.java | 10 ++++++----
 .../src/main/java/org/apache/calcite/test/SqlOperatorTest.java |  2 ++
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java 
b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
index 7338cbfa52..ee2516a461 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -577,16 +577,18 @@ public class SqlFunctions {
   /** SQL SUBSTRING(string FROM ... FOR ...) function. */
   public static String substring(String c, int s, int l) {
     int lc = c.length();
-    int e = s + l;
+    long e = (long) s + (long) l;
     if (l < 0) {
       throw RESOURCE.illegalNegativeSubstringLength().ex();
     }
-    if (s > lc || e < 1) {
+    // Prevent overflow in addition
+    if (s > lc || e < 1L) {
       return "";
     }
     final int s0 = Math.max(s - 1, 0);
-    final int e0 = Math.min(e - 1, lc);
-    return c.substring(s0, e0);
+    final long e0 = Math.min(e - 1, (long) lc);
+    // We know that e0 cannot exceed Integer.MAX_VALUE, since it's smaller 
than lc
+    return c.substring(s0, (int) e0);
   }
 
   /** SQL SUBSTRING(binary FROM ...) function for binary. */
diff --git a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java 
b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
index 5a67eddf4d..c7f1126ee8 100644
--- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
+++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
@@ -7438,6 +7438,8 @@ public class SqlOperatorTest {
         "ab", "VARCHAR(3) NOT NULL");
     f.checkString("substring(x'aabbcc' from 1 for 2)",
         "aabb", "VARBINARY(3) NOT NULL");
+    f.checkString("substring('abc' from 2 for 2147483646)",
+        "bc", "VARCHAR(3) NOT NULL");
 
     switch (f.conformance().semantics()) {
     case BIG_QUERY:

Reply via email to