numeric.c: fix `int_pow` to detect integer overflow; fix #5420

parent 2268405f
...@@ -76,31 +76,29 @@ int_zerodiv(mrb_state *mrb) ...@@ -76,31 +76,29 @@ int_zerodiv(mrb_state *mrb)
static mrb_value static mrb_value
int_pow(mrb_state *mrb, mrb_value x) 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_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)) { #ifndef MRB_NO_FLOAT
mrb_get_args(mrb, "f", &z); if (mrb_float_p(y)) {
z = pow((mrb_float)base, z); return mrb_float_value(mrb, pow((double)base, mrb_float(y)));
return mrb_float_value(mrb, z);
} }
else { else if (mrb_integer_p(y)) {
exp = mrb_integer(y);
}
else
#endif
{
mrb_get_args(mrb, "i", &exp); 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) { 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 (;;) { for (;;) {
if (exp & 1) { if (exp & 1) {
...@@ -115,7 +113,6 @@ int_pow(mrb_state *mrb, mrb_value x) ...@@ -115,7 +113,6 @@ int_pow(mrb_state *mrb, mrb_value x)
} }
} }
return mrb_int_value(mrb, result); return mrb_int_value(mrb, result);
#endif
} }
mrb_int mrb_int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment