github-actions[bot] commented on code in PR #65693:
URL: https://github.com/apache/doris/pull/65693#discussion_r3595218040


##########
be/src/exprs/function/cast/cast_to_decimal.h:
##########
@@ -35,45 +39,166 @@ namespace doris {
                    value, from_type_name, precision, scale))
 
 struct CastToDecimal {
+    static bool is_lossless_decimal_string(const char* data, size_t size, 
UInt32 precision,
+                                           UInt32 target_scale) {
+        size_t begin = 0;
+        size_t end = size;
+        while (begin < end && std::isspace(static_cast<unsigned 
char>(data[begin]))) {
+            ++begin;
+        }
+        while (begin < end && std::isspace(static_cast<unsigned char>(data[end 
- 1]))) {
+            --end;
+        }
+        if (begin == end) {
+            return false;
+        }
+
+        size_t pos = begin;
+        if (data[pos] == '+' || data[pos] == '-') {
+            ++pos;
+        }
+
+        bool seen_dot = false;
+        bool seen_digit = false;
+        size_t digits_before_dot = 0;
+        size_t digits = 0;
+        size_t first_non_zero = 0;
+        size_t last_non_zero = 0;
+        while (pos < end && data[pos] != 'e' && data[pos] != 'E') {
+            unsigned char ch = static_cast<unsigned char>(data[pos]);
+            if (std::isdigit(ch)) {
+                seen_digit = true;
+                ++digits;
+                if (!seen_dot) {
+                    ++digits_before_dot;
+                }
+                if (ch != '0') {
+                    if (first_non_zero == 0) {
+                        first_non_zero = digits;
+                    }
+                    last_non_zero = digits;
+                }
+            } else if (data[pos] == '.' && !seen_dot) {
+                seen_dot = true;
+            } else {
+                return false;
+            }
+            ++pos;
+        }
+        if (!seen_digit) {
+            return false;
+        }
+
+        int64_t exponent = 0;
+        if (pos < end) {
+            ++pos;
+            bool negative_exponent = false;
+            if (pos < end && (data[pos] == '+' || data[pos] == '-')) {
+                negative_exponent = data[pos] == '-';
+                ++pos;
+            }
+            if (pos == end) {
+                return false;
+            }
+
+            int64_t exponent_magnitude = 0;
+            while (pos < end) {
+                unsigned char ch = static_cast<unsigned char>(data[pos]);
+                if (!std::isdigit(ch)) {
+                    return false;
+                }
+                if (exponent_magnitude > (std::numeric_limits<int64_t>::max() 
- (ch - '0')) / 10) {

Review Comment:
   [P1] Finish validating the exponent before accepting zero — For 
`0e9223372036854775808x`, this returns true as soon as the exponent overflows 
because the significand is zero, without ever validating the trailing `x`. 
`StringParser::string_to_decimal` also stops at its smaller exponent cap, 
returns `PARSE_OVERFLOW` with value 0, and `from_string_lossless` accepts that 
status, so this malformed VARCHAR becomes a non-NULL zero and incorrectly 
matches DECIMAL zero. Please keep scanning the exponent grammar after magnitude 
overflow and only accept zero once the whole token is valid; this is the 
opposite direction from the existing cancelling-exponent thread.
   



##########
be/src/exprs/function/cast/cast_to_decimal.h:
##########
@@ -35,45 +39,166 @@ namespace doris {
                    value, from_type_name, precision, scale))
 
 struct CastToDecimal {
+    static bool is_lossless_decimal_string(const char* data, size_t size, 
UInt32 precision,
+                                           UInt32 target_scale) {
+        size_t begin = 0;
+        size_t end = size;
+        while (begin < end && std::isspace(static_cast<unsigned 
char>(data[begin]))) {
+            ++begin;
+        }
+        while (begin < end && std::isspace(static_cast<unsigned char>(data[end 
- 1]))) {
+            --end;
+        }
+        if (begin == end) {
+            return false;
+        }
+
+        size_t pos = begin;
+        if (data[pos] == '+' || data[pos] == '-') {
+            ++pos;
+        }
+
+        bool seen_dot = false;
+        bool seen_digit = false;
+        size_t digits_before_dot = 0;
+        size_t digits = 0;
+        size_t first_non_zero = 0;
+        size_t last_non_zero = 0;
+        while (pos < end && data[pos] != 'e' && data[pos] != 'E') {
+            unsigned char ch = static_cast<unsigned char>(data[pos]);
+            if (std::isdigit(ch)) {
+                seen_digit = true;
+                ++digits;
+                if (!seen_dot) {
+                    ++digits_before_dot;
+                }
+                if (ch != '0') {
+                    if (first_non_zero == 0) {
+                        first_non_zero = digits;
+                    }
+                    last_non_zero = digits;
+                }
+            } else if (data[pos] == '.' && !seen_dot) {
+                seen_dot = true;
+            } else {
+                return false;
+            }
+            ++pos;
+        }
+        if (!seen_digit) {
+            return false;
+        }
+
+        int64_t exponent = 0;
+        if (pos < end) {
+            ++pos;
+            bool negative_exponent = false;
+            if (pos < end && (data[pos] == '+' || data[pos] == '-')) {
+                negative_exponent = data[pos] == '-';
+                ++pos;
+            }
+            if (pos == end) {
+                return false;
+            }
+
+            int64_t exponent_magnitude = 0;
+            while (pos < end) {
+                unsigned char ch = static_cast<unsigned char>(data[pos]);
+                if (!std::isdigit(ch)) {
+                    return false;
+                }
+                if (exponent_magnitude > (std::numeric_limits<int64_t>::max() 
- (ch - '0')) / 10) {
+                    return first_non_zero == 0;

Review Comment:
   [P1] Finish validating the exponent before accepting zero — For 
`0e9223372036854775808x`, this returns true as soon as the exponent overflows 
because the significand is zero, without ever validating the trailing `x`. 
`StringParser::string_to_decimal` also stops at its smaller exponent cap, 
returns `PARSE_OVERFLOW` with value 0, and `from_string_lossless` accepts that 
status, so this malformed VARCHAR becomes a non-NULL zero and incorrectly 
matches DECIMAL zero. Please keep scanning the exponent grammar after magnitude 
overflow and only accept zero once the whole token is valid; this is the 
opposite direction from the existing cancelling-exponent thread.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to