8000 bpo-46724: Fix dis support for overflow args (GH-31285) · python/cpython@c3ce778 · GitHub
[go: up one dir, main page]

Skip to content

Commit c3ce778

Browse files
bpo-46724: Fix dis support for overflow args (GH-31285)
1 parent 2923d87 commit c3ce778

File tree

3 files changed

+40
-5
lines changed

3 files changed

+40
-5
lines changed

Lib/dis.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,13 +515,24 @@ def _disassemble_str(source, **kwargs):
515515

516516
disco = disassemble # XXX For backwards compatibility
517517

518+
519+
# Rely on C `int` being 32 bits for oparg
520+
_INT_BITS = 32
521+
# Value for c int when it overflows
522+
_INT_OVERFLOW = 2 ** (_INT_BITS - 1)
523+
518524
def _unpack_opargs(code):
519525
extended_arg = 0
520526
for i in range(0, len(code), 2):
521527
op = code[i]
522528
if op >= HAVE_ARGUMENT:
523529
arg = code[i+1] | extended_arg
524530
extended_arg = (arg << 8) if op == EXTENDED_ARG else 0
531+
# The oparg is stored as a signed integer
532+
# If the value exceeds its upper limit, it will overflow and wrap
533+
# to a negative integer
534+
if extended_arg >= _INT_OVERFLOW:
535+
extended_arg -= 2 * _INT_OVERFLOW
525536
else:
526537
arg = None
527538
extended_arg = 0

Lib/test/test_dis.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
# Minimal tests for dis module
22

3-
from test.support import captured_stdout, requires_debug_ranges
4-
from test.support.bytecode_helper import BytecodeTestCase
5-
import unittest
6-
import sys
3+
import contextlib
74
import dis
85
import io
96
import re
7+
import sys
108
import types
11-
import contextlib
9+
import unittest
10+
from test.support import captured_stdout, requires_debug_ranges
11+
from test.support.bytecode_helper import BytecodeTestCase
12+
13+
import opcode
14+
1215

1316
def get_tb():
1417
def _error():
@@ -219,6 +222,22 @@ def bug42562():
219222
RETURN_VALUE
220223
"""
221224

225+
# [255, 255, 255, 252] is -4 in a 4 byte signed integer
226+
bug46724 = bytes([
227+
opcode.EXTENDED_ARG, 255,
228+
opcode.EXTENDED_ARG, 255,
229+
opcode.EXTENDED_ARG, 255,
230+
opcode.opmap['JUMP_FORWARD'], 252,
231+
])
232+
233+
234+
dis_bug46724 = """\
235+
>> EXTENDED_ARG 255
236+
EXTENDED_ARG 65535
237+
EXTENDED_ARG 16777215
238+
JUMP_FORWARD -4 (to 0)
239+
"""
240+
222241
_BIG_LINENO_FORMAT = """\
223242
1 RESUME 0
224243
@@ -688,6 +707,10 @@ def test_bug_45757(self):
688707
# Extended arg followed by NOP
689708
self.do_disassembly_test(code_bug_45757, dis_bug_45757)
690709

710+
def test_bug_46724(self):
711+
# Test that negative operargs are handled properly
712+
self.do_disassembly_test(bug46724, dis_bug46724)
713+
691714
def test_big_linenos(self):
692715
def func(count):
693716
namespace = {}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix :mod:`dis` behavior on negative jump offsets.

0 commit comments

Comments
 (0)
0