diff --git a/src/numeric.c b/src/numeric.c index 5d695c77e..a6a59e96b 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -1352,6 +1352,7 @@ int_rev(mrb_state *mrb, mrb_value num) } #define bit_op(x,y,op1,op2) do {\ + if (!mrb_integer_p(y)) mrb_int_noconv(mrb, y);\ return mrb_int_value(mrb, (mrb_integer(x) op2 mrb_integer(y)));\ } while(0) diff --git a/test/t/integer.rb b/test/t/integer.rb index 1767f06da..b51826829 100644 --- a/test/t/integer.rb +++ b/test/t/integer.rb @@ -129,6 +129,18 @@ assert('Integer#^', '15.2.8.3.11') do assert_equal 6, 5 ^ 3 end +assert('Integer bitwise ops reject non-Integer operands') do + # A non-Integer operand has no bit pattern to combine, so &, |, ^ raise + # TypeError instead of silently reading garbage (Float used to return a + # bogus value via an unchecked union access). + assert_raise(TypeError) { 5 & 5.0 } + assert_raise(TypeError) { 5 | 5.0 } + assert_raise(TypeError) { 5 ^ 5.0 } + assert_raise(TypeError) { 5 | "3" } + assert_raise(TypeError) { 5 & nil } + assert_raise(TypeError) { 5 ^ :sym } +end + assert('Integer#<<', '15.2.8.3.12') do # Left Shift by one # 00010111 (23)