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

JingsongLi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git


The following commit(s) were added to refs/heads/master by this push:
     new bc493b6cf2 [common] Range-check the digit guard in DateTimeUtils 
(#9649)
bc493b6cf2 is described below

commit bc493b6cf29e9fa9017fc6b2f814dbbd7854f761
Author: YangJie <[email protected]>
AuthorDate: Fri Sep 11 03:09:08 2026 -0400

    [common] Range-check the digit guard in DateTimeUtils (#9649)
---
 .../org/apache/paimon/utils/DateTimeUtils.java     | 26 +++++++++++++++++-----
 .../org/apache/paimon/utils/DateTimeUtilsTest.java | 26 ++++++++++++++++++++++
 2 files changed, 47 insertions(+), 5 deletions(-)

diff --git 
a/paimon-common/src/main/java/org/apache/paimon/utils/DateTimeUtils.java 
b/paimon-common/src/main/java/org/apache/paimon/utils/DateTimeUtils.java
index d202a5bc47..13f422e8fb 100644
--- a/paimon-common/src/main/java/org/apache/paimon/utils/DateTimeUtils.java
+++ b/paimon-common/src/main/java/org/apache/paimon/utils/DateTimeUtils.java
@@ -349,15 +349,31 @@ public class DateTimeUtils {
                 + milli;
     }
 
+    /**
+     * Whether the string is a non-negative decimal integer that fits in an 
{@code int}. Callers
+     * hand the string straight to {@link Integer#parseInt}, so the range 
matters as much as the
+     * characters.
+     */
     private static boolean isInteger(String s) {
-        boolean isInt = s.length() > 0;
+        if (s.isEmpty()) {
+            return false;
+        }
+        // Accumulate with overflow checking rather than a digit-count limit: 
a zero-padded
+        // component such as "00000002024" is still in range, so what matters 
is the value, not
+        // how many characters it took to write. Bailing out the moment the 
running value passes
+        // Integer.MAX_VALUE keeps the accumulator itself from overflowing a 
long.
+        long value = 0;
         for (int i = 0; i < s.length(); i++) {
-            if (s.charAt(i) < '0' || s.charAt(i) > '9') {
-                isInt = false;
-                break;
+            char c = s.charAt(i);
+            if (c < '0' || c > '9') {
+                return false;
+            }
+            value = value * 10 + (c - '0');
+            if (value > Integer.MAX_VALUE) {
+                return false;
             }
         }
-        return isInt;
+        return true;
     }
 
     private static boolean isIllegalDate(int y, int m, int d) {
diff --git 
a/paimon-common/src/test/java/org/apache/paimon/utils/DateTimeUtilsTest.java 
b/paimon-common/src/test/java/org/apache/paimon/utils/DateTimeUtilsTest.java
index 6a0f88a367..a0c86be483 100644
--- a/paimon-common/src/test/java/org/apache/paimon/utils/DateTimeUtilsTest.java
+++ b/paimon-common/src/test/java/org/apache/paimon/utils/DateTimeUtilsTest.java
@@ -33,6 +33,32 @@ import static 
org.assertj.core.api.Assertions.assertThatThrownBy;
 /** Test for {@link DateTimeUtils}. */
 public class DateTimeUtilsTest {
 
+    @Test
+    public void testParseDateAndTimeOverflowReturnsNull() {
+        // A component too large for an int is an invalid date or time, not a 
crash: the
+        // contract of parseDate/parseTime is null for unparseable input. 
2147483648 is
+        // Integer.MAX_VALUE + 1, the smallest ten-digit value that does not 
fit.
+        assertThat(DateTimeUtils.parseDate("2147483648-01-01")).isNull();
+        assertThat(DateTimeUtils.parseDate("2147483647-01-01"))
+                .isNull(); // in range, but not a year
+        assertThat(DateTimeUtils.parseDate("99999999999-01-01")).isNull();
+        assertThat(DateTimeUtils.parseDate("2024-99999999999-01")).isNull();
+        assertThat(DateTimeUtils.parseDate("2024-01-99999999999")).isNull();
+        assertThat(DateTimeUtils.parseTime("99999999999:00:00")).isNull();
+
+        // Sanity: valid values still parse.
+        assertThat(DateTimeUtils.parseDate("2024-01-15")).isNotNull();
+        assertThat(DateTimeUtils.parseTime("12:30:00")).isNotNull();
+
+        // Zero-padded components whose value still fits an int must keep 
parsing: the range
+        // guard has to judge the value, not the digit count, or previously 
accepted padded
+        // dates/times would silently turn into NULL.
+        assertThat(DateTimeUtils.parseDate("00000002024-01-15"))
+                .isEqualTo(DateTimeUtils.parseDate("2024-01-15"));
+        assertThat(DateTimeUtils.parseTime("00000000012:30:00"))
+                .isEqualTo(DateTimeUtils.parseTime("12:30:00"));
+    }
+
     @Test
     public void testFormatLocalDateTime() {
         LocalDateTime time = LocalDateTime.of(2023, 8, 30, 12, 30, 59, 
999_999_999);

Reply via email to