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.  <!--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