From fb421d67174482e1eb7c394a0ba6f70218bbbb49 Mon Sep 17 00:00:00 2001 From: hezuojiao Date: Tue, 15 Oct 2024 05:14:07 +0000 Subject: [PATCH] Fix SIGFPE caused by dividing INT64_MIN by -1 --- src/sql/engine/expr/ob_expr_div.cpp | 24 ++++++++++++++---------- src/sql/engine/expr/ob_expr_mod.cpp | 11 ++++++++++- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/sql/engine/expr/ob_expr_div.cpp b/src/sql/engine/expr/ob_expr_div.cpp index bfbdaf1fc7..0bc4371fbb 100644 --- a/src/sql/engine/expr/ob_expr_div.cpp +++ b/src/sql/engine/expr/ob_expr_div.cpp @@ -954,16 +954,20 @@ struct ObDecimalIntBatchDivRaw : public ObArithOpRawType { using val_type = typename common::wide::CommonType::type; UNUSED(is_error_div_by_zero); - res = l / r; - const val_type round = l % r; - const val_type abs_right = r < 0 ? -r : r; - const val_type abs_round = round < 0 ? -round : round; - // if |right| is odd, |right|/2 < |r| => need_carry - // if |right| is even, |right|/2 <= |r| => need_carry - const bool need_carry = ((abs_right >> 1) + (abs_right & 1)) <= abs_round; - if (need_carry) { - const int32_t carry = res < 0 ? -1 : 1; - res = res + carry; + if (r == -1) { + res = -l; + } else { + res = l / r; + const val_type round = l % r; + const val_type abs_right = r < 0 ? -r : r; + const val_type abs_round = round < 0 ? -round : round; + // if |right| is odd, |right|/2 < |r| => need_carry + // if |right| is even, |right|/2 <= |r| => need_carry + const bool need_carry = ((abs_right >> 1) + (abs_right & 1)) <= abs_round; + if (need_carry) { + const int32_t carry = res < 0 ? -1 : 1; + res = res + carry; + } } } diff --git a/src/sql/engine/expr/ob_expr_mod.cpp b/src/sql/engine/expr/ob_expr_mod.cpp index 7b52fad649..61f4a3c099 100644 --- a/src/sql/engine/expr/ob_expr_mod.cpp +++ b/src/sql/engine/expr/ob_expr_mod.cpp @@ -494,7 +494,16 @@ int ObExprMod::mod_decimalint(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &datum ObDecimalIntBuilder res_val; switch (int_bytes) { CALC_DECIMAL_INT_MOD(int32) - CALC_DECIMAL_INT_MOD(int64) + case sizeof(int64_t): { + const int64_t l = *(l_decint->int64_v_); + const int64_t r = *(r_decint->int64_v_); + if (INT64_MIN == l && -1 == r) { + res_val.from(0); //INT64_MIN % -1 --> FPE + } else { + res_val.from(l % r); + } + break; + } CALC_DECIMAL_INT_MOD(int128) CALC_DECIMAL_INT_MOD(int256) CALC_DECIMAL_INT_MOD(int512)