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:
