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

yiguolei 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 287f5ca2de7 [Bug](function) fix mod function cause core dump (#37999)
287f5ca2de7 is described below

commit 287f5ca2de77a4b0a7c526b11d2d4892912c1ef6
Author: zhangstar333 <87313068+zhangstar...@users.noreply.github.com>
AuthorDate: Sat Jul 20 16:00:09 2024 +0800

    [Bug](function) fix mod function cause core dump (#37999)
    
    ## Proposed changes
    
    as (-9223372036854775808 % -1) will cause coredump directly by fpe,
    so check this case and throw exception.
    
    
    
![core-dump](https://github.com/user-attachments/assets/fc68d707-4582-4098-9714-4fe3958cd8a2)
    
    <!--Describe your changes.-->
---
 be/src/vec/functions/modulo.cpp                    | 18 ++++++++
 .../sql_functions/math_functions/test_mod.out      |  6 +++
 .../sql_functions/math_functions/test_mod.groovy   | 49 ++++++++++++++++++++++
 3 files changed, 73 insertions(+)

diff --git a/be/src/vec/functions/modulo.cpp b/be/src/vec/functions/modulo.cpp
index 66376b66019..7a2dfc004ef 100644
--- a/be/src/vec/functions/modulo.cpp
+++ b/be/src/vec/functions/modulo.cpp
@@ -33,6 +33,20 @@
 
 namespace doris::vectorized {
 
+template <typename A, typename B>
+inline void throw_if_division_leads_to_FPE(A a, B b) {
+    // http://avva.livejournal.com/2548306.html
+    // (-9223372036854775808 % -1) will cause coredump directly, so check this 
case to throw exception, or maybe could return 0 as result
+    if constexpr (std::is_signed_v<A> && std::is_signed_v<B>) {
+        if (b == -1 && a == std::numeric_limits<A>::min()) {
+            throw Exception(ErrorCode::INVALID_ARGUMENT,
+                            "Division of minimal signed number by minus one is 
an undefined "
+                            "behavior, {} % {}. ",
+                            a, b);
+        }
+    }
+}
+
 template <typename A, typename B>
 struct ModuloImpl {
     using ResultType = typename NumberTraits::ResultOfModulo<A, B>::Type;
@@ -51,6 +65,7 @@ struct ModuloImpl {
                 if constexpr (std::is_floating_point_v<ResultType>) {
                     c[i] = std::fmod((double)a[i], (double)b);
                 } else {
+                    throw_if_division_leads_to_FPE(a[i], b);
                     c[i] = a[i] % b;
                 }
             }
@@ -65,6 +80,7 @@ struct ModuloImpl {
         if constexpr (std::is_floating_point_v<Result>) {
             return std::fmod((double)a, (double)b);
         } else {
+            throw_if_division_leads_to_FPE(a, b);
             return a % b;
         }
     }
@@ -94,6 +110,7 @@ struct PModuloImpl {
                 if constexpr (std::is_floating_point_v<ResultType>) {
                     c[i] = std::fmod(std::fmod((double)a[i], (double)b) + 
(double)b, double(b));
                 } else {
+                    throw_if_division_leads_to_FPE(a[i], b);
                     c[i] = (a[i] % b + b) % b;
                 }
             }
@@ -108,6 +125,7 @@ struct PModuloImpl {
         if constexpr (std::is_floating_point_v<Result>) {
             return std::fmod(std::fmod((double)a, (double)b) + (double)b, 
(double)b);
         } else {
+            throw_if_division_leads_to_FPE(a, b);
             return (a % b + b) % b;
         }
     }
diff --git 
a/regression-test/data/query_p0/sql_functions/math_functions/test_mod.out 
b/regression-test/data/query_p0/sql_functions/math_functions/test_mod.out
new file mode 100644
index 00000000000..6e3ce6219de
--- /dev/null
+++ b/regression-test/data/query_p0/sql_functions/math_functions/test_mod.out
@@ -0,0 +1,6 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !sql --
+-2147483648    4       -1
+1      2       3
+5      -9223372036854775808    -1
+
diff --git 
a/regression-test/suites/query_p0/sql_functions/math_functions/test_mod.groovy 
b/regression-test/suites/query_p0/sql_functions/math_functions/test_mod.groovy
new file mode 100644
index 00000000000..027983ff749
--- /dev/null
+++ 
b/regression-test/suites/query_p0/sql_functions/math_functions/test_mod.groovy
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+suite("test_mod") {
+    def tableName = "test_mod"
+    sql "set enable_fold_constant_by_be = false;"
+    sql """DROP TABLE IF EXISTS `test_mod`"""
+    sql """ CREATE TABLE `test_mod` (
+        `k1` int NULL COMMENT "用户id",
+        `k2` bigint COMMENT "数据灌入日期时间",
+        `k3` int COMMENT "数据灌入日期时间")
+        DUPLICATE KEY(`k1`) DISTRIBUTED BY HASH(`k1`)
+        PROPERTIES ( "replication_num" = "1" ); """
+
+    sql """ insert into `test_mod` values(1,2,3); """
+    sql """ insert into `test_mod` values(-2147483648,4,-1); """
+    sql """ insert into `test_mod` values(5,-9223372036854775808,-1); """
+
+    qt_sql """
+        SELECT * from test_mod order by 1;
+    """
+
+    test {
+        sql "select mod(-2147483648,-1); "
+        exception "Division of minimal signed number by minus one is an 
undefined"
+    }
+    test {
+        sql "select mod(-9223372036854775808,-1); "
+        exception "Division of minimal signed number by minus one is an 
undefined"
+    }
+    test {
+        sql "select pmod(-9223372036854775808,-1); "
+        exception "Division of minimal signed number by minus one is an 
undefined"
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to