diff --git a/sjsonnet/src/sjsonnet/Evaluator.scala b/sjsonnet/src/sjsonnet/Evaluator.scala index e41deda5..23794024 100644 --- a/sjsonnet/src/sjsonnet/Evaluator.scala +++ b/sjsonnet/src/sjsonnet/Evaluator.scala @@ -256,8 +256,11 @@ class Evaluator( val ll = ld.toLong; val rl = rd.toLong if (ll.toDouble != ld || rl.toDouble != rd) null // not safe integers else if (rl < 0) null - else if (rl >= 1 && math.abs(ll) >= (1L << (63 - rl))) null - else Val.cachedNum(pos, (ll << rl).toDouble) + else { + val masked = (rl % 64).toInt + if (masked >= 1 && math.abs(ll) >= (1L << (63 - masked))) null + else Val.cachedNum(pos, (ll << masked).toDouble) + } case Expr.BinaryOp.OP_>> => val ll = ld.toLong; val rl = rd.toLong if (ll.toDouble != ld || rl.toDouble != rd) null @@ -1411,10 +1414,11 @@ class Evaluator( val ll = visitExprAsDouble(e.lhs).toSafeLong(pos) val rr = visitExprAsDouble(e.rhs).toSafeLong(pos) if (rr < 0) Error.fail("shift by negative exponent", pos) - if (rr >= 1 && math.abs(ll) >= (1L << (63 - rr))) + val masked = (rr % 64).toInt + if (masked >= 1 && math.abs(ll) >= (1L << (63 - masked))) Error.fail("numeric value outside safe integer range for bitwise operation", pos) else - Val.cachedNum(pos, (ll << rr).toDouble) + Val.cachedNum(pos, (ll << masked).toDouble) case Expr.BinaryOp.OP_>> => val ll = visitExprAsDouble(e.lhs).toSafeLong(pos) diff --git a/sjsonnet/test/resources/new_test_suite/error.leftshift_large_amount_overflow.jsonnet b/sjsonnet/test/resources/new_test_suite/error.leftshift_large_amount_overflow.jsonnet new file mode 100644 index 00000000..e02da149 --- /dev/null +++ b/sjsonnet/test/resources/new_test_suite/error.leftshift_large_amount_overflow.jsonnet @@ -0,0 +1 @@ +3 << 126 diff --git a/sjsonnet/test/resources/new_test_suite/error.leftshift_large_amount_overflow.jsonnet.golden b/sjsonnet/test/resources/new_test_suite/error.leftshift_large_amount_overflow.jsonnet.golden new file mode 100644 index 00000000..9d38e3ad --- /dev/null +++ b/sjsonnet/test/resources/new_test_suite/error.leftshift_large_amount_overflow.jsonnet.golden @@ -0,0 +1,2 @@ +sjsonnet.Error: numeric value outside safe integer range for bitwise operation + at [].(error.leftshift_large_amount_overflow.jsonnet:1:3) diff --git a/sjsonnet/test/resources/new_test_suite/fix_leftshift_large_amount.jsonnet b/sjsonnet/test/resources/new_test_suite/fix_leftshift_large_amount.jsonnet new file mode 100644 index 00000000..3e70af8b --- /dev/null +++ b/sjsonnet/test/resources/new_test_suite/fix_leftshift_large_amount.jsonnet @@ -0,0 +1,7 @@ +std.assertEqual(1 << 64, 1) && +std.assertEqual(0 << 64, 0) && +std.assertEqual(0 << 1000, 0) && +std.assertEqual(1 << 128, 1) && +std.assertEqual(1 << 192, 1) && +std.assertEqual(4.5 << 66, 16) && +true diff --git a/sjsonnet/test/resources/new_test_suite/fix_leftshift_large_amount.jsonnet.golden b/sjsonnet/test/resources/new_test_suite/fix_leftshift_large_amount.jsonnet.golden new file mode 100644 index 00000000..27ba77dd --- /dev/null +++ b/sjsonnet/test/resources/new_test_suite/fix_leftshift_large_amount.jsonnet.golden @@ -0,0 +1 @@ +true