Skip to content

Commit

Permalink
GH-128682: Make PyStackRef_CLOSE escaping. (GH-129404)
Browse files Browse the repository at this point in the history
  • Loading branch information
markshannon authored Feb 3, 2025
1 parent 218f205 commit 808071b
Show file tree
Hide file tree
Showing 12 changed files with 1,348 additions and 657 deletions.
2 changes: 1 addition & 1 deletion Include/internal/pycore_opcode_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions Include/internal/pycore_uop_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 15 additions & 5 deletions Lib/test/test_generated_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,9 @@ def test_error_if_plain(self):
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(OP);
if (cond) goto label;
if (cond) {
goto label;
}
DISPATCH();
}
"""
Expand All @@ -555,7 +557,9 @@ def test_error_if_plain_with_comment(self):
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(OP);
if (cond) goto label;
if (cond) {
goto label;
}
// Comment is ok
DISPATCH();
}
Expand All @@ -582,7 +586,9 @@ def test_error_if_pop(self):
right = stack_pointer[-1];
left = stack_pointer[-2];
SPAM(left, right);
if (cond) goto pop_2_label;
if (cond) {
goto pop_2_label;
}
res = 0;
stack_pointer[-2] = res;
stack_pointer += -1;
Expand Down Expand Up @@ -611,7 +617,9 @@ def test_error_if_pop_with_result(self):
right = stack_pointer[-1];
left = stack_pointer[-2];
res = SPAM(left, right);
if (cond) goto pop_2_label;
if (cond) {
goto pop_2_label;
}
stack_pointer[-2] = res;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
Expand Down Expand Up @@ -1392,7 +1400,9 @@ def test_pop_on_error_peeks(self):
// THIRD
{
// Mark j and k as used
if (cond) goto pop_2_error;
if (cond) {
goto pop_2_error;
}
}
stack_pointer += -2;
assert(WITHIN_STACK_BOUNDS());
Expand Down
79 changes: 37 additions & 42 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -2130,8 +2130,7 @@ dummy_func(
PyStackRef_CLOSE(self_st);
self_or_null = PyStackRef_NULL;
}
PyStackRef_CLOSE(class_st);
PyStackRef_CLOSE(global_super_st);
DECREF_INPUTS();

attr = PyStackRef_FromPyObjectSteal(attr_o);
}
Expand Down Expand Up @@ -2245,7 +2244,7 @@ dummy_func(
attr = PyStackRef_FromPyObjectNew(attr_o);
#endif
STAT_INC(LOAD_ATTR, hit);
DECREF_INPUTS();
PyStackRef_CLOSE(owner);
}

macro(LOAD_ATTR_INSTANCE_VALUE) =
Expand Down Expand Up @@ -3671,15 +3670,14 @@ dummy_func(
EXIT_IF(!PyStackRef_IsNull(null[0]));
}

op(_EXPAND_METHOD, (callable[1], null[1], unused[oparg] -- method[1], self[1], unused[oparg])) {
op(_EXPAND_METHOD, (callable[1], self_or_null[1], unused[oparg] -- callable[1], self_or_null[1], unused[oparg])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
assert(PyStackRef_IsNull(null[0]));
DEAD(null);
assert(PyStackRef_IsNull(self_or_null[0]));
assert(Py_TYPE(callable_o) == &PyMethod_Type);
self[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
self_or_null[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
_PyStackRef temp = callable[0];
method[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
assert(PyStackRef_FunctionCheck(method[0]));
callable[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
assert(PyStackRef_FunctionCheck(callable[0]));
PyStackRef_CLOSE(temp);
}

Expand Down Expand Up @@ -3740,13 +3738,13 @@ dummy_func(
EXIT_IF(Py_TYPE(PyStackRef_AsPyObjectBorrow(callable[0])) != &PyMethod_Type);
}

op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable[1], null[1], unused[oparg] -- func[1], self[1], unused[oparg])) {
DEAD(null);
op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable[1], self_or_null[1], unused[oparg] -- callable[1], self_or_null[1], unused[oparg])) {
assert(PyStackRef_IsNull(self_or_null[0]));
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
STAT_INC(CALL, hit);
self[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
self_or_null[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
_PyStackRef temp = callable[0];
func[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
callable[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
PyStackRef_CLOSE(temp);
}

Expand Down Expand Up @@ -4171,8 +4169,9 @@ dummy_func(
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);

int total_args = oparg;
_PyStackRef *arguments = args;
if (!PyStackRef_IsNull(self_or_null[0])) {
args--;
arguments--;
total_args++;
}

Expand All @@ -4183,8 +4182,8 @@ dummy_func(
EXIT_IF(meth->ml_flags != METH_O);
// CPython promises to check all non-vectorcall function calls.
EXIT_IF(tstate->c_recursion_remaining <= 0);
_PyStackRef arg_stackref = args[1];
_PyStackRef self_stackref = args[0];
_PyStackRef arg_stackref = arguments[1];
_PyStackRef self_stackref = arguments[0];
EXIT_IF(!Py_IS_TYPE(PyStackRef_AsPyObjectBorrow(self_stackref),
method->d_common.d_type));
STAT_INC(CALL, hit);
Expand All @@ -4195,11 +4194,7 @@ dummy_func(
PyStackRef_AsPyObjectBorrow(arg_stackref));
_Py_LeaveRecursiveCallTstate(tstate);
assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
PyStackRef_CLOSE(self_stackref);
PyStackRef_CLOSE(arg_stackref);
DEAD(args);
DEAD(self_or_null);
PyStackRef_CLOSE(callable[0]);
DECREF_INPUTS();
ERROR_IF(res_o == NULL, error);
res = PyStackRef_FromPyObjectSteal(res_o);
}
Expand Down Expand Up @@ -4486,15 +4481,14 @@ dummy_func(
EXIT_IF(!PyStackRef_IsNull(null[0]));
}

op(_EXPAND_METHOD_KW, (callable[1], null[1], unused[oparg], unused -- method[1], self[1], unused[oparg], unused)) {
op(_EXPAND_METHOD_KW, (callable[1], self_or_null[1], unused[oparg], unused -- callable[1], self_or_null[1], unused[oparg], unused)) {
assert(PyStackRef_IsNull(self_or_null[0]));
_PyStackRef callable_s = callable[0];
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable_s);

assert(PyStackRef_IsNull(null[0]));
assert(Py_TYPE(callable_o) == &PyMethod_Type);
self[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
method[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
assert(PyStackRef_FunctionCheck(method[0]));
self_or_null[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
callable[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
assert(PyStackRef_FunctionCheck(callable[0]));
PyStackRef_CLOSE(callable_s);
}

Expand Down Expand Up @@ -4600,7 +4594,8 @@ dummy_func(
}
}

op(_DO_CALL_FUNCTION_EX, (func_st, unused, callargs_st, kwargs_st -- result)) {
op(_DO_CALL_FUNCTION_EX, (func_st, null, callargs_st, kwargs_st -- result)) {
(void)null;
PyObject *func = PyStackRef_AsPyObjectBorrow(func_st);

// DICT_MERGE is called before this opcode if there are kwargs.
Expand Down Expand Up @@ -4671,8 +4666,8 @@ dummy_func(
result_o = PyObject_Call(func, callargs, kwargs);
}
PyStackRef_XCLOSE(kwargs_st);
DEAD(kwargs_st);
PyStackRef_CLOSE(callargs_st);
DEAD(null);
PyStackRef_CLOSE(func_st);
ERROR_IF(result_o == NULL, error);
result = PyStackRef_FromPyObjectSteal(result_o);
Expand Down Expand Up @@ -4809,12 +4804,11 @@ dummy_func(

macro(BINARY_OP) = _SPECIALIZE_BINARY_OP + unused/4 + _BINARY_OP;

pure inst(SWAP, (bottom_in, unused[oparg-2], top_in --
top_out, unused[oparg-2], bottom_out)) {
bottom_out = bottom_in;
DEAD(bottom_in);
top_out = top_in;
DEAD(top_in);
pure inst(SWAP, (bottom[1], unused[oparg-2], top[1] --
bottom[1], unused[oparg-2], top[1])) {
_PyStackRef temp = bottom[0];
bottom[0] = top[0];
top[0] = temp;
assert(oparg >= 2);
}

Expand Down Expand Up @@ -5174,7 +5168,8 @@ dummy_func(
EXIT_TO_TIER1();
}

tier2 op(_ERROR_POP_N, (target/2, unused[oparg] --)) {
tier2 op(_ERROR_POP_N, (target/2 --)) {
assert(oparg == 0);
frame->instr_ptr = _PyFrame_GetBytecode(frame) + target;
SYNC_SP();
GOTO_UNWIND();
Expand All @@ -5193,18 +5188,18 @@ dummy_func(
}

label(pop_4_error) {
STACK_SHRINK(1);
goto pop_3_error;
STACK_SHRINK(4);
goto error;
}

label(pop_3_error) {
STACK_SHRINK(1);
goto pop_2_error;
STACK_SHRINK(3);
goto error;
}

label(pop_2_error) {
STACK_SHRINK(1);
goto pop_1_error;
STACK_SHRINK(2);
goto error;
}

label(pop_1_error) {
Expand Down
Loading

0 comments on commit 808071b

Please sign in to comment.