Skip to content

Commit 74f69b8

Browse files
committed
Ensure that escaping closes do not leave live objects above them on the stack
1 parent a833c8e commit 74f69b8

File tree

7 files changed

+135
-87
lines changed

7 files changed

+135
-87
lines changed

Include/internal/pycore_opcode_metadata.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_metadata.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_generated_cases.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,6 +1739,18 @@ def test_no_escaping_calls_in_branching_macros(self):
17391739
with self.assertRaises(SyntaxError):
17401740
self.run_cases_test(input, "")
17411741

1742+
def test_kill_in_wrong_order(self):
1743+
input = """
1744+
inst(OP, (a, b -- c)) {
1745+
c = b;
1746+
PyStackRef_CLOSE(a);
1747+
PyStackRef_CLOSE(b);
1748+
}
1749+
"""
1750+
with self.assertRaises(SyntaxError):
1751+
self.run_cases_test(input, "")
1752+
1753+
17421754
class TestGeneratedAbstractCases(unittest.TestCase):
17431755
def setUp(self) -> None:
17441756
super().setUp()

Python/bytecodes.c

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -667,8 +667,8 @@ dummy_func(
667667

668668
STAT_INC(BINARY_OP, hit);
669669
PyObject *res_o = PyUnicode_Concat(left_o, right_o);
670-
PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc);
671670
PyStackRef_CLOSE_SPECIALIZED(right, _PyUnicode_ExactDealloc);
671+
PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc);
672672
INPUTS_DEAD();
673673
ERROR_IF(res_o == NULL, error);
674674
res = PyStackRef_FromPyObjectSteal(res_o);
@@ -711,7 +711,7 @@ dummy_func(
711711
* that the string is safe to mutate.
712712
*/
713713
assert(Py_REFCNT(left_o) >= 2);
714-
PyStackRef_CLOSE(left);
714+
PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc);
715715
DEAD(left);
716716
PyObject *temp = PyStackRef_AsPyObjectSteal(*target_local);
717717
PyUnicode_Append(&temp, right_o);
@@ -808,8 +808,7 @@ dummy_func(
808808
err = PyObject_SetItem(PyStackRef_AsPyObjectBorrow(container), slice, PyStackRef_AsPyObjectBorrow(v));
809809
Py_DECREF(slice);
810810
}
811-
PyStackRef_CLOSE(v);
812-
PyStackRef_CLOSE(container);
811+
DECREF_INPUTS();
813812
ERROR_IF(err, error);
814813
}
815814

@@ -2068,11 +2067,8 @@ dummy_func(
20682067
int method_found = 0;
20692068
PyObject *attr_o = _PySuper_Lookup(cls, self, name,
20702069
Py_TYPE(self)->tp_getattro == PyObject_GenericGetAttr ? &method_found : NULL);
2071-
PyStackRef_CLOSE(global_super_st);
2072-
PyStackRef_CLOSE(class_st);
20732070
if (attr_o == NULL) {
2074-
PyStackRef_CLOSE(self_st);
2075-
ERROR_IF(true, error);
2071+
ERROR_NO_POP();
20762072
}
20772073
if (method_found) {
20782074
self_or_null = self_st; // transfer ownership
@@ -2081,6 +2077,8 @@ dummy_func(
20812077
PyStackRef_CLOSE(self_st);
20822078
self_or_null = PyStackRef_NULL;
20832079
}
2080+
PyStackRef_CLOSE(class_st);
2081+
PyStackRef_CLOSE(global_super_st);
20842082

20852083
attr = PyStackRef_FromPyObjectSteal(attr_o);
20862084
}
@@ -3451,11 +3449,11 @@ dummy_func(
34513449
/* Callable is not a normal Python function */
34523450
STACKREFS_TO_PYOBJECTS(args, total_args, args_o);
34533451
if (CONVERSION_FAILED(args_o)) {
3454-
PyStackRef_CLOSE(callable[0]);
34553452
for (int i = 0; i < total_args; i++) {
34563453
PyStackRef_CLOSE(args[i]);
34573454
}
34583455
DEAD(self_or_null);
3456+
PyStackRef_CLOSE(callable[0]);
34593457
ERROR_IF(true, error);
34603458
}
34613459
PyObject *res_o = PyObject_Vectorcall(
@@ -3481,11 +3479,11 @@ dummy_func(
34813479
}
34823480
}
34833481
assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
3484-
PyStackRef_CLOSE(callable[0]);
34853482
for (int i = 0; i < total_args; i++) {
34863483
PyStackRef_CLOSE(args[i]);
34873484
}
34883485
DEAD(self_or_null);
3486+
PyStackRef_CLOSE(callable[0]);
34893487
ERROR_IF(res_o == NULL, error);
34903488
res = PyStackRef_FromPyObjectSteal(res_o);
34913489
}
@@ -3621,11 +3619,11 @@ dummy_func(
36213619
NULL);
36223620
STACKREFS_TO_PYOBJECTS_CLEANUP(args_o);
36233621
assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
3624-
PyStackRef_CLOSE(callable[0]);
36253622
for (int i = 0; i < total_args; i++) {
36263623
PyStackRef_CLOSE(args[i]);
36273624
}
36283625
DEAD(self_or_null);
3626+
PyStackRef_CLOSE(callable[0]);
36293627
ERROR_IF(res_o == NULL, error);
36303628
res = PyStackRef_FromPyObjectSteal(res_o);
36313629
}
@@ -3872,6 +3870,7 @@ dummy_func(
38723870
for (int i = 0; i < total_args; i++) {
38733871
PyStackRef_CLOSE(arguments[i]);
38743872
}
3873+
DEAD(args);
38753874
PyStackRef_CLOSE(callable[0]);
38763875
ERROR_IF(res_o == NULL, error);
38773876
res = PyStackRef_FromPyObjectSteal(res_o);
@@ -3951,6 +3950,7 @@ dummy_func(
39513950
for (int i = 0; i < total_args; i++) {
39523951
PyStackRef_CLOSE(arguments[i]);
39533952
}
3953+
DEAD(args);
39543954
PyStackRef_CLOSE(callable[0]);
39553955
ERROR_IF(res_o == NULL, error);
39563956
res = PyStackRef_FromPyObjectSteal(res_o);
@@ -4029,8 +4029,10 @@ dummy_func(
40294029
if (res_o == NULL) {
40304030
GOTO_ERROR(error);
40314031
}
4032-
PyStackRef_CLOSE(callable[0]);
40334032
PyStackRef_CLOSE(arg_stackref);
4033+
DEAD(args);
4034+
DEAD(self_or_null);
4035+
PyStackRef_CLOSE(callable[0]);
40344036
res = PyStackRef_FromPyObjectSteal(res_o);
40354037
}
40364038

@@ -4039,25 +4041,24 @@ dummy_func(
40394041
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
40404042

40414043
int total_args = oparg;
4044+
_PyStackRef *arguments = args;
40424045
if (!PyStackRef_IsNull(self_or_null[0])) {
4043-
args--;
4046+
arguments--;
40444047
total_args++;
40454048
}
40464049
DEOPT_IF(total_args != 2);
40474050
PyInterpreterState *interp = tstate->interp;
40484051
DEOPT_IF(callable_o != interp->callable_cache.isinstance);
40494052
STAT_INC(CALL, hit);
4050-
_PyStackRef cls_stackref = args[1];
4051-
_PyStackRef inst_stackref = args[0];
4053+
_PyStackRef cls_stackref = arguments[1];
4054+
_PyStackRef inst_stackref = arguments[0];
40524055
int retval = PyObject_IsInstance(PyStackRef_AsPyObjectBorrow(inst_stackref), PyStackRef_AsPyObjectBorrow(cls_stackref));
40534056
if (retval < 0) {
40544057
ERROR_NO_POP();
40554058
}
40564059
res = retval ? PyStackRef_True : PyStackRef_False;
40574060
assert((!PyStackRef_IsNull(res)) ^ (_PyErr_Occurred(tstate) != NULL));
4058-
PyStackRef_CLOSE(inst_stackref);
4059-
PyStackRef_CLOSE(cls_stackref);
4060-
PyStackRef_CLOSE(callable[0]);
4061+
DECREF_INPUTS();
40614062
}
40624063

40634064
// This is secretly a super-instruction
@@ -4356,11 +4357,11 @@ dummy_func(
43564357
}
43574358
PyStackRef_CLOSE(kwnames);
43584359
assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
4359-
PyStackRef_CLOSE(callable[0]);
43604360
for (int i = 0; i < total_args; i++) {
43614361
PyStackRef_CLOSE(args[i]);
43624362
}
43634363
DEAD(self_or_null);
4364+
PyStackRef_CLOSE(callable[0]);
43644365
ERROR_IF(res_o == NULL, error);
43654366
res = PyStackRef_FromPyObjectSteal(res_o);
43664367
}
@@ -4515,6 +4516,8 @@ dummy_func(
45154516
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
45164517
if (PyTuple_CheckExact(callargs_o)) {
45174518
tuple = callargs;
4519+
kwargs_out = kwargs_in;
4520+
DEAD(kwargs_in);
45184521
DEAD(callargs);
45194522
}
45204523
else {
@@ -4526,11 +4529,11 @@ dummy_func(
45264529
if (tuple_o == NULL) {
45274530
ERROR_NO_POP();
45284531
}
4532+
kwargs_out = kwargs_in;
4533+
DEAD(kwargs_in);
45294534
PyStackRef_CLOSE(callargs);
45304535
tuple = PyStackRef_FromPyObjectSteal(tuple_o);
45314536
}
4532-
kwargs_out = kwargs_in;
4533-
DEAD(kwargs_in);
45344537
}
45354538

45364539
op(_DO_CALL_FUNCTION_EX, (func_st, unused, callargs_st, kwargs_st if (oparg & 1) -- result)) {
@@ -4706,8 +4709,7 @@ dummy_func(
47064709

47074710
inst(FORMAT_WITH_SPEC, (value, fmt_spec -- res)) {
47084711
PyObject *res_o = PyObject_Format(PyStackRef_AsPyObjectBorrow(value), PyStackRef_AsPyObjectBorrow(fmt_spec));
4709-
PyStackRef_CLOSE(value);
4710-
PyStackRef_CLOSE(fmt_spec);
4712+
DECREF_INPUTS();
47114713
ERROR_IF(res_o == NULL, error);
47124714
res = PyStackRef_FromPyObjectSteal(res_o);
47134715
}

0 commit comments

Comments
 (0)