Skip to content

Commit d06a6da

Browse files
Support negative jumps in 3.10
Adds support for negative relative jump args introduced in Python 3.10. Ports corresponding fix from dis python/cpython#31285
1 parent e513da5 commit d06a6da

File tree

2 files changed

+20
-2
lines changed

2 files changed

+20
-2
lines changed

code_data/blocks.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from __future__ import annotations
77

8+
import ctypes
89
import dis
910
import sys
1011
from dataclasses import dataclass, field
@@ -61,7 +62,6 @@ def bytes_to_blocks(b: bytes) -> Blocks:
6162
# Compute a sorted list of target, to map each one to a bloc offset
6263
targets = sorted(targets_set)
6364
del targets_set
64-
6565
# Then, iterate through each instruction to update the jump to point to the
6666
# block offset, instead of the bytecode offset
6767
block: list[Instruction]
@@ -232,6 +232,9 @@ def _parse_bytes(b: bytes) -> Iterable[tuple[int, int, int, int, int]]:
232232
n_args += 1
233233
if opcode == dis.EXTENDED_ARG:
234234
arg = arg << 8
235+
# https://github.com/python/cpython/pull/31285
236+
if arg > _c_int_upper_limit:
237+
arg -= _c_int_length
235238
else:
236239
first_offset = i - ((n_args - 1) * 2)
237240
next_offset = i + 2
@@ -248,3 +251,11 @@ def _instrsize(arg: int) -> int:
248251
From https://github.com/python/cpython/blob/b2e5794870eb4728ddfaafc0f79a40299576434f/Python/wordcode_helpers.h#L11-L20
249252
"""
250253
return 1 if arg <= 0xFF else 2 if arg <= 0xFFFF else 3 if arg <= 0xFFFFFF else 4
254+
255+
256+
# The number of bits in a signed int
257+
_c_int_bit_size = ctypes.sizeof(ctypes.c_int()) * 8
258+
# The maximum value that can be stored in a signed int
259+
_c_int_upper_limit = (2 ** (_c_int_bit_size - 1)) - 1
260+
# The number of values that can be stored in a signed int
261+
_c_int_length = 2 ** _c_int_bit_size

code_data/code_data_test.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,14 @@ def main(args):
183183
''',
184184
id="pip._vendor.pep517.build minimal",
185185
),
186+
pytest.param(
187+
"""while not x < y < z:
188+
pass""",
189+
# Reduced from imagesize modeul
190+
# https://bugs.python.org/issue46724
191+
# negative opargs in Python 3.10
192+
id="bpo-46724",
193+
),
186194
],
187195
)
188196
def test_examples(source):
@@ -242,7 +250,6 @@ def module_codes() -> Iterable[tuple[str, str, CodeType]]:
242250
warnings.simplefilter("ignore")
243251
for mi in pkgutil.walk_packages(onerror=lambda _name: None):
244252
loader: Loader = mi.module_finder.find_module(mi.name) # type: ignore
245-
loader.__ne__
246253
try:
247254
code = loader.get_code(mi.name) # type: ignore
248255
except SyntaxError:

0 commit comments

Comments
 (0)