summaryrefslogtreecommitdiffhomepage
path: root/src/numeric.c
diff options
context:
space:
mode:
authormurase_syuka <[email protected]>2015-11-18 21:37:17 +0900
committermurase_syuka <[email protected]>2015-11-18 21:37:17 +0900
commitef95dcd39093e0c3bb017a37fe0ff5a7158e91a7 (patch)
tree59ee35d8278e5b756341cdfe530e80e13b9a238a /src/numeric.c
parent557ab3472ada7b955fa23ebc0cc081a8e65a8b02 (diff)
downloadmruby-ef95dcd39093e0c3bb017a37fe0ff5a7158e91a7.tar.gz
mruby-ef95dcd39093e0c3bb017a37fe0ff5a7158e91a7.zip
Bugfix nagative-number lshift() bit overflow
Diffstat (limited to 'src/numeric.c')
-rw-r--r--src/numeric.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/src/numeric.c b/src/numeric.c
index e64cd2d8d..41820ff5c 100644
--- a/src/numeric.c
+++ b/src/numeric.c
@@ -821,15 +821,28 @@ static mrb_value
lshift(mrb_state *mrb, mrb_int val, mrb_int width)
{
mrb_assert(width > 0);
- if ((width > NUMERIC_SHIFT_WIDTH_MAX) ||
- (val > (MRB_INT_MAX >> width))) {
+ if (val > 0) {
+ if ((width > NUMERIC_SHIFT_WIDTH_MAX) ||
+ (val > (MRB_INT_MAX >> width))) {
+ goto bit_overflow;
+ }
+ } else {
+ if ((width > NUMERIC_SHIFT_WIDTH_MAX) ||
+ (val < (MRB_INT_MIN >> width))) {
+ goto bit_overflow;
+ }
+ }
+
+ return mrb_fixnum_value(val << width);
+
+bit_overflow:
+ {
mrb_float f = (mrb_float)val;
while (width--) {
f *= 2;
}
return mrb_float_value(mrb, f);
}
- return mrb_fixnum_value(val << width);
}
static mrb_value