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

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


The following commit(s) were added to refs/heads/master by this push:
     new 8016b3ef9cb [fix](function) Reject overflowing IPv6 uint128 strings 
(#68334)
8016b3ef9cb is described below

commit 8016b3ef9cb6d1ff930229083f5977b7985516ce
Author: Mryange <[email protected]>
AuthorDate: Thu Sep 24 09:52:10 2026 +0800

    [fix](function) Reject overflowing IPv6 uint128 strings (#68334)
    
    Problem Summary: `ipv6_from_uint128_string_or_null` accepted empty
    strings and decimal values larger than `uint128`, causing digit-by-digit
    parsing to wrap around and produce an incorrect IPv6 value. Root cause:
    the parser performed unchecked multiplication and addition. This change
    rejects empty input and checks the value before each decimal
    accumulation so invalid input is converted to NULL by the existing
    nullable function path.
    
    ### Release note
    
    None
    
    ### Check List (For Author)
    
    - Test <!-- At least one of them must be included. -->
        - [ ] Regression test
        - [ ] Unit Test
        - [ ] Manual test (add detailed scripts or steps below)
        - [ ] No need to test or manual test. Explain why:
    - [ ] This is a refactor/code format and no logic has been changed.
            - [ ] Previous test can cover this change.
            - [ ] No code files have been changed.
            - [ ] Other reason <!-- Add your reason?  -->
    
    - Behavior changed:
        - [ ] No.
        - [ ] Yes. <!-- Explain the behavior change -->
    
    - Does this need documentation?
        - [ ] No.
    - [ ] Yes. <!-- Add document PR link here. eg:
    https://github.com/apache/doris-website/pull/1214 -->
    
    ### Check List (For Reviewer who merge this PR)
    
    - [ ] Confirm the release note
    - [ ] Confirm test cases
    - [ ] Confirm document
    - [ ] Add branch pick label <!-- Add branch pick label that this PR
    should merge into -->
---
 be/src/core/value/ipv6_value.h              | 15 ++++++++++++++-
 be/test/exprs/function/function_ip_test.cpp | 18 ++++++++++++++++++
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/be/src/core/value/ipv6_value.h b/be/src/core/value/ipv6_value.h
index 394ea7aad14..3a354ba6346 100644
--- a/be/src/core/value/ipv6_value.h
+++ b/be/src/core/value/ipv6_value.h
@@ -17,6 +17,7 @@
 
 #pragma once
 
+#include <limits>
 #include <regex>
 #include <sstream>
 #include <string>
@@ -43,12 +44,24 @@ public:
     bool from_string(const std::string& ipv6_str) { return from_string(_value, 
ipv6_str); }
 
     static bool from_uint128_string(IPv6& value, const char* ipv6_str, size_t 
len) {
+        if (len == 0) {
+            return false;
+        }
+
+        constexpr IPv6 max_value = std::numeric_limits<IPv6>::max();
+        constexpr IPv6 max_value_div_10 = max_value / 10;
+        constexpr IPv6 max_value_mod_10 = max_value % 10;
         value = 0;
         for (size_t i = 0; i < len; ++i) {
             if (ipv6_str[i] < '0' || ipv6_str[i] > '9') {
                 return false; // illegal character for uint128
             }
-            value = value * 10 + (ipv6_str[i] - '0');
+            const auto digit = static_cast<IPv6>(ipv6_str[i] - '0');
+            if (value > max_value_div_10 ||
+                (value == max_value_div_10 && digit > max_value_mod_10)) {
+                return false;
+            }
+            value = value * 10 + digit;
         }
         return true;
     }
diff --git a/be/test/exprs/function/function_ip_test.cpp 
b/be/test/exprs/function/function_ip_test.cpp
index 2de8c1eb852..29da803ffec 100644
--- a/be/test/exprs/function/function_ip_test.cpp
+++ b/be/test/exprs/function/function_ip_test.cpp
@@ -80,6 +80,24 @@ TEST(FunctionIpTest, StringToNumRejectsEmbeddedNullTail) {
     check_function_all_arg_comb<DataTypeString, true>("inet6_aton", 
input_types, ipv6_null_data);
 }
 
+TEST(FunctionIpTest, IPv6FromUInt128StringRejectsEmptyAndOverflow) {
+    const std::string max_uint128 = "340282366920938463463374607431768211455";
+    IPv6 max_value = 0;
+    EXPECT_TRUE(IPv6Value::from_uint128_string(max_value, max_uint128.data(), 
max_uint128.size()));
+    EXPECT_EQ(max_value, static_cast<IPv6>(-1));
+
+    for (const auto& value :
+         {std::string("340282366920938463463374607431768211456"),
+          std::string("680564733841876926926749214863536422913"), 
std::string()}) {
+        IPv6 parsed = 0;
+        EXPECT_FALSE(IPv6Value::from_uint128_string(parsed, value.data(), 
value.size()));
+    }
+
+    IPv6 parsed = 0;
+    EXPECT_TRUE(IPv6Value::from_uint128_string(parsed, "1", 1));
+    EXPECT_EQ(parsed, static_cast<IPv6>(1));
+}
+
 TEST(FunctionIpTest, StringToIPv6AcceptsLongIPv4Spellings) {
     std::string mapped_ipv4_zero(IPV6_BINARY_LENGTH, '\0');
     mapped_ipv4_zero[10] = static_cast<char>(0xff);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to