In PyTorch before 2.7.0, bitwise_right_shift produces incorrect output for certain out-of-bounds values of the "other" argument.
Research is free — Hunters explains how the bug works, the root-cause code pattern, how the fix addresses it, and how to test whether a target is affected, in chat. Investigate & write exploit is a paid run — the engine reads the advisory and fix commits, then builds and validates a working proof-of-concept exploit with reproduction steps.
Affected versions
2.6.0 → fixed in 2.7.0
Details
In PyTorch before 2.7.0, bitwise_right_shift produces incorrect output for certain out-of-bounds values of the "other" argument.
The fix
Update
test/inductor/test_cpu_repro.py+18 −0
@@ -2281,6 +2281,24 @@ def test_bitwise_right_shift(self):res = cfn(x, bit_num)self.assertEqual(res_aten_eager, res)+def test_bitwise_shift_right_corner_inputs(self):+# Fix https://github.com/pytorch/pytorch/issues/143555+x = torch.tensor(1000, dtype=torch.int64)+bit_num = torch.tensor(64, dtype=torch.int64)+res_aten_eager = torch.bitwise_right_shift(x, bit_num)+cfn = torch.compile(torch.bitwise_right_shift)+res = cfn(x, bit_num)+self.assertEqual(res_aten_eager, res)++def test_bitwise_shift_left_corner_inputs(self):+# Fix https://github.com/pytorch/pytorch/issues/143555+x = torch.tensor(1000, dtype=torch.int64)+bit_num = torch.tensor(64, dtype=torch.int64)+res_aten_eager = torch.bitwise_left_shift(x, bit_num)+cfn = torch.compile(torch.bitwise_left_shift)+res = cfn(x, bit_num)+self.assertEqual(res_aten_eager, res)+def test_view_dtype(self):def f(x):return x.view(torch.int32) >> 2
torch/_inductor/codegen/cpp.py+32 −2
@@ -973,11 +973,41 @@ def bitwise_xor(a, b):@staticmethoddef bitwise_left_shift(a, b):-return f"decltype({a})({a} << {b})"+code = BracesBuffer()+code.writeline("[&]()")+with code.indent():+scalar_t = DTYPE_TO_CPP[a.dtype]+code.writeline(+f"constexpr decltype({b}) max_shift = sizeof({scalar_t}) * CHAR_BIT;"+)+code.writeline(+f"if ((static_cast<std::make_signed_t<{scalar_t}>>({b}) < 0) || ({b} >= max_shift))"+)+with code.indent():+code.writeline(f"return decltype({a})(0);")+code.writeline(+f"return decltype({a})(static_cast<std::make_unsigned_t<{scalar_t}>>({a}) << {b});"+)+code.writeline("()")+return code@staticmethoddef bitwise_right_shift(a, b):-return f"decltype({a})({a} >> {b})"+code = BracesBuffer()+code.writeline("[&]()")+with code.indent():+scalar_t = DTYPE_TO_CPP[a.dtype]+code.writeline(+f"constexpr decltype({b}) max_shift = sizeof({scalar_t}) * CHAR_BIT - std::is_signed_v<{scalar_t}>;"+)+code.writeline(+f"if ((static_cast<std::make_signed_t<{scalar_t}>>({b}) < 0) || ({b} >= max_shift))"+)+with code.indent():+code.writeline(f"return decltype({a})({a} >> max_shift);")+code.writeline(f"return decltype({a})({a} >> {b});")+code.writeline("()")+return code@staticmethoddef rand(seed: sympy.Expr, offset: sympy.Expr):test/inductor/test_cpu_repro.py | 2 +-1 file changed, 1 insertion(+), 1 deletion(-)
test/inductor/test_cpu_repro.py+1 −1
@@ -2291,7 +2291,7 @@ def test_bitwise_shift_right_corner_inputs(self):self.assertEqual(res_aten_eager, res)def test_bitwise_shift_left_corner_inputs(self):-# Fix https://github.com/pytorch/pytorch/issues/143555+# Fix https://github.com/pytorch/pytorch/issues/143566x = torch.tensor(1000, dtype=torch.int64)bit_num = torch.tensor(64, dtype=torch.int64)res_aten_eager = torch.bitwise_left_shift(x, bit_num)test/inductor/test_cpu_repro.py | 31 +++++++++++++++----------------1 file changed, 15 insertions(+), 16 deletions(-)
test/inductor/test_cpu_repro.py+15 −16
@@ -2281,23 +2281,22 @@ def test_bitwise_right_shift(self):res = cfn(x, bit_num)self.assertEqual(res_aten_eager, res)-def test_bitwise_shift_right_corner_inputs(self):+def test_bitwise_shift_corner_inputs(self):# Fix https://github.com/pytorch/pytorch/issues/143555-x = torch.tensor(1000, dtype=torch.int64)-bit_num = torch.tensor(64, dtype=torch.int64)-res_aten_eager = torch.bitwise_right_shift(x, bit_num)-cfn = torch.compile(torch.bitwise_right_shift)-res = cfn(x, bit_num)-self.assertEqual(res_aten_eager, res)--def test_bitwise_shift_left_corner_inputs(self):-# Fix https://github.com/pytorch/pytorch/issues/143566-x = torch.tensor(1000, dtype=torch.int64)-bit_num = torch.tensor(64, dtype=torch.int64)-res_aten_eager = torch.bitwise_left_shift(x, bit_num)-cfn = torch.compile(torch.bitwise_left_shift)-res = cfn(x, bit_num)-self.assertEqual(res_aten_eager, res)+# and https://github.com/pytorch/pytorch/issues/143566+bitwise_fns = (+torch.bitwise_left_shift,+torch.bitwise_right_shift,+)+for bitwise_fn in bitwise_fns:+torch._dynamo.reset()+metrics.reset()+x = torch.tensor(1000, dtype=torch.int64)+bit_num = torch.tensor(64, dtype=torch.int64)+res_aten_eager = bitwise_fn(x, bit_num)+cfn = torch.compile(bitwise_fn)+res = cfn(x, bit_num)+self.assertEqual(res_aten_eager, res)def test_view_dtype(self):def f(x):