Skip to content

Commit 9f53816

Browse files
committed
Fix undefined 32-bit shifts in frameobject.c stack_swap()
Widen MASK and top to int64_t before shifting: shift can reach 60.
1 parent 288cc2b commit 9f53816

2 files changed

Lines changed: 27 additions & 1 deletion

File tree

‎Lib/test/test_frame.py‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import textwrap
66
import threading
77
import unittest
8+
import warnings
89
import weakref
910
try:
1011
import _testcapi
@@ -222,6 +223,30 @@ def test_f_lineno_del_segfault(self):
222223
with self.assertRaises(AttributeError):
223224
del f.f_lineno
224225

226+
def test_f_lineno_deep_stack_swap(self):
227+
fors = " ".join(f"for v{i} in range(1)" for i in range(11))
228+
params = ", ".join(f"v{i}=None" for i in range(11))
229+
ns = {}
230+
exec(f"def f({params}):\n return [0 {fors}]\n", ns)
231+
f = ns["f"]
232+
233+
jumped = []
234+
235+
def tracer(frame, event, arg):
236+
if (event == 'line' and frame.f_code is f.__code__
237+
and not jumped):
238+
jumped.append(None)
239+
frame.f_lineno = frame.f_lineno
240+
return tracer
241+
242+
with warnings.catch_warnings():
243+
warnings.simplefilter('ignore', RuntimeWarning)
244+
sys.settrace(tracer)
245+
try:
246+
self.assertEqual(f(), [0])
247+
finally:
248+
sys.settrace(None)
249+
225250
def test_f_trace(self):
226251
f, _, _ = self.make_frames()
227252
def tracer(*args):

‎Objects/frameobject.c‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1320,7 +1320,8 @@ stack_swap(int64_t stack, int n)
13201320
Kind to_swap = peek(stack, n);
13211321
Kind top = top_of_stack(stack);
13221322
int shift = BITS_PER_BLOCK*(n-1);
1323-
int64_t replaced_low = (stack & ~(MASK << shift)) | (top << shift);
1323+
int64_t replaced_low = (stack & ~((int64_t)MASK << shift))
1324+
| ((int64_t)top << shift);
13241325
int64_t replaced_top = (replaced_low & ~MASK) | to_swap;
13251326
return replaced_top;
13261327
}

0 commit comments

Comments
 (0)