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

yiguolei pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-4.1 by this push:
     new 572bf1333d5 branch-4.1: [fix](be) prevent SIGFPE in int_divide for 
signed min value #64828 (#64948)
572bf1333d5 is described below

commit 572bf1333d5461dc1b4b8806232bcb53590a5d7a
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Tue Jun 30 12:23:57 2026 +0800

    branch-4.1: [fix](be) prevent SIGFPE in int_divide for signed min value 
#64828 (#64948)
    
    Cherry-picked from #64828
    
    Co-authored-by: Mryange <[email protected]>
---
 be/src/exprs/function/int_div.cpp                  | 30 +++++++-
 .../exprs/function/function_arithmetic_test.cpp    | 87 ++++++++++++++++++++++
 2 files changed, 115 insertions(+), 2 deletions(-)

diff --git a/be/src/exprs/function/int_div.cpp 
b/be/src/exprs/function/int_div.cpp
index 923c0d12a57..52229a7a865 100644
--- a/be/src/exprs/function/int_div.cpp
+++ b/be/src/exprs/function/int_div.cpp
@@ -20,6 +20,7 @@
 
 #include <libdivide.h>
 
+#include <limits>
 #include <utility>
 
 #include "core/data_type/data_type_number.h"
@@ -112,12 +113,21 @@ struct DivideIntegralImpl {
     using Arg = typename PrimitiveTypeTraits<Type>::CppType;
     using ColumnType = typename PrimitiveTypeTraits<Type>::ColumnType;
     static constexpr PrimitiveType ResultType = Type;
+    static constexpr bool is_signed_integer = std::is_signed_v<Arg> || 
std::is_same_v<Arg, Int128>;
 
     static DataTypes get_variadic_argument_types() {
         return {std::make_shared<typename 
PrimitiveTypeTraits<Type>::DataType>(),
                 std::make_shared<typename 
PrimitiveTypeTraits<Type>::DataType>()};
     }
 
+    static bool division_leads_to_fpe(Arg a, Arg b) {
+        if constexpr (is_signed_integer) {
+            return b == -1 && a == std::numeric_limits<Arg>::min();
+        } else {
+            return false;
+        }
+    }
+
     static void apply(const typename ColumnType::Container& a, Arg b,
                       typename 
PrimitiveTypeTraits<ResultType>::ColumnType::Container& c,
                       PaddedPODArray<UInt8>& null_map) {
@@ -126,6 +136,19 @@ struct DivideIntegralImpl {
         memset(null_map.data(), is_null, size);
 
         if (!is_null) {
+            if constexpr (is_signed_integer) {
+                if (b == -1) {
+                    for (size_t i = 0; i < size; i++) {
+                        null_map[i] = division_leads_to_fpe(a[i], b);
+                        if (!null_map[i]) {
+                            c[i] = typename 
PrimitiveTypeTraits<ResultType>::CppType(a[i] / b);
+                        } else {
+                            c[i] = {};
+                        }
+                    }
+                    return;
+                }
+            }
             if constexpr (!std::is_floating_point_v<Arg> && 
!std::is_same_v<Arg, Int128> &&
                           !std::is_same_v<Arg, Int8> && !std::is_same_v<Arg, 
UInt8>) {
                 const auto divider = libdivide::divider<Arg>(Arg(b));
@@ -142,8 +165,11 @@ struct DivideIntegralImpl {
 
     static inline typename PrimitiveTypeTraits<ResultType>::CppType apply(Arg 
a, Arg b,
                                                                           
UInt8& is_null) {
-        is_null = b == 0;
-        return typename PrimitiveTypeTraits<ResultType>::CppType(a / (b + 
is_null));
+        is_null = b == 0 || division_leads_to_fpe(a, b);
+        if (is_null) {
+            return {};
+        }
+        return typename PrimitiveTypeTraits<ResultType>::CppType(a / b);
     }
 
     static ColumnPtr constant_constant(Arg a, Arg b) {
diff --git a/be/test/exprs/function/function_arithmetic_test.cpp 
b/be/test/exprs/function/function_arithmetic_test.cpp
index bf40fa7bf55..09c66ba9bf8 100644
--- a/be/test/exprs/function/function_arithmetic_test.cpp
+++ b/be/test/exprs/function/function_arithmetic_test.cpp
@@ -18,6 +18,7 @@
 #include <stdint.h>
 
 #include <iomanip>
+#include <limits>
 #include <string>
 #include <vector>
 
@@ -53,6 +54,92 @@ TEST(function_arithmetic_test, 
function_arithmetic_divide_test) {
     }
 }
 
+TEST(function_arithmetic_test, 
function_arithmetic_int_divide_min_signed_by_minus_one_test) {
+    std::string func_name = "int_divide";
+    const auto min_int8 = std::numeric_limits<int8_t>::min();
+    const auto min_int16 = std::numeric_limits<int16_t>::min();
+    const auto min_int32 = std::numeric_limits<int32_t>::min();
+    const auto min_int64 = std::numeric_limits<int64_t>::min();
+    const auto min_int128 = std::numeric_limits<Int128>::min();
+
+    {
+        InputTypeSet input_types = {PrimitiveType::TYPE_TINYINT, 
PrimitiveType::TYPE_TINYINT};
+        DataSet data_set = {{{int8_t {1}, int8_t {-1}}, int8_t {-1}},
+                            {{min_int8, int8_t {-1}}, Null()}};
+        static_cast<void>(check_function<DataTypeInt8, true>(func_name, 
input_types, data_set));
+    }
+
+    {
+        InputTypeSet input_types = {PrimitiveType::TYPE_SMALLINT, 
PrimitiveType::TYPE_SMALLINT};
+        DataSet data_set = {{{int16_t {1}, int16_t {-1}}, int16_t {-1}},
+                            {{min_int16, int16_t {-1}}, Null()}};
+        static_cast<void>(check_function<DataTypeInt16, true>(func_name, 
input_types, data_set));
+    }
+
+    {
+        InputTypeSet input_types = {PrimitiveType::TYPE_INT, 
PrimitiveType::TYPE_INT};
+        DataSet data_set = {{{int32_t {1}, int32_t {-1}}, int32_t {-1}},
+                            {{min_int32, int32_t {-1}}, Null()}};
+        static_cast<void>(check_function<DataTypeInt32, true>(func_name, 
input_types, data_set));
+    }
+
+    {
+        InputTypeSet input_types = {Consted {PrimitiveType::TYPE_BIGINT},
+                                    Consted {PrimitiveType::TYPE_BIGINT}};
+        DataSet data_set = {{{min_int64, int64_t {-1}}, Null()}};
+        static_cast<void>(check_function<DataTypeInt64, true>(func_name, 
input_types, data_set));
+    }
+
+    {
+        InputTypeSet input_types = {PrimitiveType::TYPE_BIGINT,
+                                    Consted {PrimitiveType::TYPE_BIGINT}};
+        DataSet data_set = {{{min_int64, int64_t {-1}}, Null()}};
+        static_cast<void>(check_function<DataTypeInt64, true>(func_name, 
input_types, data_set));
+    }
+
+    {
+        InputTypeSet input_types = {Consted {PrimitiveType::TYPE_BIGINT},
+                                    PrimitiveType::TYPE_BIGINT};
+        DataSet data_set = {{{min_int64, int64_t {-1}}, Null()}};
+        static_cast<void>(check_function<DataTypeInt64, true>(func_name, 
input_types, data_set));
+    }
+
+    {
+        InputTypeSet input_types = {PrimitiveType::TYPE_BIGINT, 
PrimitiveType::TYPE_BIGINT};
+        DataSet data_set = {{{int64_t {1}, int64_t {-1}}, int64_t {-1}},
+                            {{min_int64, int64_t {-1}}, Null()}};
+        static_cast<void>(check_function<DataTypeInt64, true>(func_name, 
input_types, data_set));
+    }
+
+    {
+        InputTypeSet input_types = {Consted {PrimitiveType::TYPE_LARGEINT},
+                                    Consted {PrimitiveType::TYPE_LARGEINT}};
+        DataSet data_set = {{{min_int128, Int128 {-1}}, Null()}};
+        static_cast<void>(check_function<DataTypeInt128, true>(func_name, 
input_types, data_set));
+    }
+
+    {
+        InputTypeSet input_types = {PrimitiveType::TYPE_LARGEINT,
+                                    Consted {PrimitiveType::TYPE_LARGEINT}};
+        DataSet data_set = {{{min_int128, Int128 {-1}}, Null()}};
+        static_cast<void>(check_function<DataTypeInt128, true>(func_name, 
input_types, data_set));
+    }
+
+    {
+        InputTypeSet input_types = {Consted {PrimitiveType::TYPE_LARGEINT},
+                                    PrimitiveType::TYPE_LARGEINT};
+        DataSet data_set = {{{min_int128, Int128 {-1}}, Null()}};
+        static_cast<void>(check_function<DataTypeInt128, true>(func_name, 
input_types, data_set));
+    }
+
+    {
+        InputTypeSet input_types = {PrimitiveType::TYPE_LARGEINT, 
PrimitiveType::TYPE_LARGEINT};
+        DataSet data_set = {{{Int128 {1}, Int128 {-1}}, Int128 {-1}},
+                            {{min_int128, Int128 {-1}}, Null()}};
+        static_cast<void>(check_function<DataTypeInt128, true>(func_name, 
input_types, data_set));
+    }
+}
+
 TEST(function_arithmetic_test, bitnot_test) {
     std::string func_name = "bitnot";
 


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

Reply via email to