summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/numeric.c3
-rw-r--r--test/t/integer.rb3
2 files changed, 5 insertions, 1 deletions
diff --git a/src/numeric.c b/src/numeric.c
index 6cceaeb9e..e64cd2d8d 100644
--- a/src/numeric.c
+++ b/src/numeric.c
@@ -821,7 +821,8 @@ static mrb_value
lshift(mrb_state *mrb, mrb_int val, mrb_int width)
{
mrb_assert(width > 0);
- if (width > NUMERIC_SHIFT_WIDTH_MAX) {
+ if ((width > NUMERIC_SHIFT_WIDTH_MAX) ||
+ (val > (MRB_INT_MAX >> width))) {
mrb_float f = (mrb_float)val;
while (width--) {
f *= 2;
diff --git a/test/t/integer.rb b/test/t/integer.rb
index be3c13db2..c6084bfeb 100644
--- a/test/t/integer.rb
+++ b/test/t/integer.rb
@@ -147,6 +147,9 @@ assert('Integer#<<', '15.2.8.3.12') do
# Left Shift by a negative is Right Shift
assert_equal 23, 46 << -1
+
+ # Left Shift by 31 is bitShift overflow to SignedInt
+ assert_equal 2147483648, 1 << 31
end
assert('Integer#>>', '15.2.8.3.13') do