From 5cf1de5b3167322ff39783275233d0b8aeed2dd1 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 21 Apr 2021 22:05:52 +0900 Subject: numeric.c: fix `int_pow` to detect integer overflow; fix #5420 --- src/numeric.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/numeric.c b/src/numeric.c index 504a7493d..be7608e3c 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -76,31 +76,29 @@ int_zerodiv(mrb_state *mrb) static mrb_value int_pow(mrb_state *mrb, mrb_value x) { - mrb_int base = mrb_int(mrb, x); - mrb_int exp; -#ifndef MRB_NO_FLOAT mrb_value y = mrb_get_arg1(mrb); - mrb_float z; + mrb_int base = mrb_integer(x); + mrb_int result = 1; + mrb_int exp; - if (!mrb_integer_p(y)) { - mrb_get_args(mrb, "f", &z); - z = pow((mrb_float)base, z); - return mrb_float_value(mrb, z); +#ifndef MRB_NO_FLOAT + if (mrb_float_p(y)) { + return mrb_float_value(mrb, pow((double)base, mrb_float(y))); } - else { + else if (mrb_integer_p(y)) { + exp = mrb_integer(y); + } + else +#endif + { mrb_get_args(mrb, "i", &exp); - z = pow((double)base, (double)exp); - if (exp < 0 || z < (mrb_float)MRB_INT_MIN || (mrb_float)MRB_INT_MAX < z) { - return mrb_float_value(mrb, z); - } } - return mrb_int_value(mrb, (mrb_int)z); -#else - mrb_int result = 1; - - mrb_get_args(mrb, "i", &exp); if (exp < 0) { - return mrb_fixnum_value(0); +#ifndef MRB_NO_FLOAT + return mrb_float_value(mrb, pow((double)base, (double)exp)); +#else + int_overflow(mrb, "negative power"); +#endif } for (;;) { if (exp & 1) { @@ -115,7 +113,6 @@ int_pow(mrb_state *mrb, mrb_value x) } } return mrb_int_value(mrb, result); -#endif } mrb_int -- cgit v1.2.3