[Python-checkins] GH-94438: Handle extended arguments and conditional pops in mark_stacks (GH-95110)
miss-islington
webhook-mailer at python.org
Fri Jul 22 19:49:02 EDT 2022
https://github.com/python/cpython/commit/bbdacb402bb441972312372f7b2104a51c32350e
commit: bbdacb402bb441972312372f7b2104a51c32350e
branch: 3.11
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: miss-islington <31488909+miss-islington at users.noreply.github.com>
date: 2022-07-22T16:48:53-07:00
summary:
GH-94438: Handle extended arguments and conditional pops in mark_stacks (GH-95110)
(cherry picked from commit e4d3a96a113070fde433834a6c9fb79ebeebad4a)
Co-authored-by: Brandt Bucher <brandtbucher at microsoft.com>
files:
A Misc/NEWS.d/next/Core and Builtins/2022-07-22-12-53-34.gh-issue-94438.hNqACc.rst
M Lib/test/test_sys_settrace.py
M Objects/frameobject.c
diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py
index 4f2dd4f9eade3..d77deae32cd5c 100644
--- a/Lib/test/test_sys_settrace.py
+++ b/Lib/test/test_sys_settrace.py
@@ -2674,6 +2674,42 @@ def test_jump_with_null_on_stack_load_attr(output):
)
output.append(15)
+ @jump_test(2, 3, [1, 3])
+ def test_jump_extended_args_unpack_ex_simple(output):
+ output.append(1)
+ _, *_, _ = output.append(2) or "Spam"
+ output.append(3)
+
+ @jump_test(3, 4, [1, 4, 4, 5])
+ def test_jump_extended_args_unpack_ex_tricky(output):
+ output.append(1)
+ (
+ _, *_, _
+ ) = output.append(4) or "Spam"
+ output.append(5)
+
+ def test_jump_extended_args_for_iter(self):
+ # In addition to failing when extended arg handling is broken, this can
+ # also hang for a *very* long time:
+ source = [
+ "def f(output):",
+ " output.append(1)",
+ " for _ in spam:",
+ *(f" output.append({i})" for i in range(3, 100_000)),
+ f" output.append(100_000)",
+ ]
+ namespace = {}
+ exec("\n".join(source), namespace)
+ f = namespace["f"]
+ self.run_test(f, 2, 100_000, [1, 100_000])
+
+ @jump_test(2, 3, [1, 3])
+ def test_jump_or_pop(output):
+ output.append(1)
+ _ = output.append(2) and "Spam"
+ output.append(3)
+
+
class TestExtendedArgs(unittest.TestCase):
def setUp(self):
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-22-12-53-34.gh-issue-94438.hNqACc.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-22-12-53-34.gh-issue-94438.hNqACc.rst
new file mode 100644
index 0000000000000..2a7249a833c2e
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-22-12-53-34.gh-issue-94438.hNqACc.rst
@@ -0,0 +1,4 @@
+Fix an issue that caused extended opcode arguments and some conditional pops
+to be ignored when calculating valid jump targets for assignments to the
+``f_lineno`` attribute of frame objects. In some cases, this could cause
+inconsistent internal state, resulting in a hard crash of the interpreter.
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 78113366c0d7e..47e108b9ae79b 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -230,11 +230,15 @@ mark_stacks(PyCodeObject *code_obj, int len)
int64_t target_stack;
int j = get_arg(code, i);
if (opcode == POP_JUMP_FORWARD_IF_FALSE ||
- opcode == POP_JUMP_FORWARD_IF_TRUE) {
+ opcode == POP_JUMP_FORWARD_IF_TRUE ||
+ opcode == JUMP_IF_FALSE_OR_POP ||
+ opcode == JUMP_IF_TRUE_OR_POP)
+ {
j += i + 1;
}
- else if (opcode == POP_JUMP_BACKWARD_IF_FALSE ||
- opcode == POP_JUMP_BACKWARD_IF_TRUE) {
+ else {
+ assert(opcode == POP_JUMP_BACKWARD_IF_FALSE ||
+ opcode == POP_JUMP_BACKWARD_IF_TRUE);
j = i + 1 - j;
}
assert(j < len);
@@ -334,7 +338,8 @@ mark_stacks(PyCodeObject *code_obj, int len)
break;
default:
{
- int delta = PyCompile_OpcodeStackEffect(opcode, _Py_OPARG(code[i]));
+ int delta = PyCompile_OpcodeStackEffect(opcode, get_arg(code, i));
+ assert(delta != PY_INVALID_STACK_EFFECT);
while (delta < 0) {
next_stack = pop_value(next_stack);
delta++;
More information about the Python-checkins
mailing list