Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8ed317f

Browse files
costypetrisorvstinner
authored andcommitted
bpo-34113: Fix a crash when using LLTRACE is on (GH-8517)
Fix a crash on negative STACKADJ() when Low-Level trace (LLTRACE) is enabled.
1 parent 944451c commit 8ed317f

3 files changed

Lines changed: 60 additions & 17 deletions

File tree

Lib/test/test_lltrace.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import os
2+
import textwrap
3+
import unittest
4+
5+
from test import support
6+
from test.support.script_helper import assert_python_ok
7+
8+
9+
class TestLLTrace(unittest.TestCase):
10+
11+
def test_lltrace_does_not_crash_on_subscript_operator(self):
12+
# If this test fails, it will reproduce a crash reported as
13+
# bpo-34113. The crash happened at the command line console of
14+
# debug Python builds with __ltrace__ enabled (only possible in console),
15+
# when the interal Python stack was negatively adjusted
16+
with open(support.TESTFN, 'w') as fd:
17+
self.addCleanup(os.unlink, support.TESTFN)
18+
fd.write(textwrap.dedent("""\
19+
import code
20+
21+
console = code.InteractiveConsole()
22+
console.push('__ltrace__ = 1')
23+
console.push('a = [1, 2, 3]')
24+
console.push('a[0] = 1')
25+
print('unreachable if bug exists')
26+
"""))
27+
28+
assert_python_ok(support.TESTFN)
29+
30+
if __name__ == "__main__":
31+
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed crash on debug builds when opcode stack was adjusted with negative
2+
numbers. Patch by Constantin Petrisor.

Python/ceval.c

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -762,16 +762,26 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
762762
assert(STACK_LEVEL() <= co->co_stacksize); }
763763
#define POP() ((void)(lltrace && prtrace(TOP(), "pop")), \
764764
BASIC_POP())
765-
#define STACKADJ(n) { (void)(BASIC_STACKADJ(n), \
765+
#define STACK_GROW(n) do { \
766+
assert(n >= 0); \
767+
(void)(BASIC_STACKADJ(n), \
766768
lltrace && prtrace(TOP(), "stackadj")); \
767-
assert(STACK_LEVEL() <= co->co_stacksize); }
769+
assert(STACK_LEVEL() <= co->co_stacksize); \
770+
} while (0)
771+
#define STACK_SHRINK(n) do { \
772+
assert(n >= 0); \
773+
(void)(lltrace && prtrace(TOP(), "stackadj")); \
774+
(void)(BASIC_STACKADJ(-n)); \
775+
assert(STACK_LEVEL() <= co->co_stacksize); \
776+
} while (0)
768777
#define EXT_POP(STACK_POINTER) ((void)(lltrace && \
769778
prtrace((STACK_POINTER)[-1], "ext_pop")), \
770779
*--(STACK_POINTER))
771780
#else
772781
#define PUSH(v) BASIC_PUSH(v)
773782
#define POP() BASIC_POP()
774-
#define STACKADJ(n) BASIC_STACKADJ(n)
783+
#define STACK_GROW(n) BASIC_STACKADJ(n)
784+
#define STACK_SHRINK(n) BASIC_STACKADJ(-n)
775785
#define EXT_POP(STACK_POINTER) (*--(STACK_POINTER))
776786
#endif
777787

@@ -1133,7 +1143,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
11331143
PyObject *second = SECOND();
11341144
Py_INCREF(top);
11351145
Py_INCREF(second);
1136-
STACKADJ(2);
1146+
STACK_GROW(2);
11371147
SET_TOP(top);
11381148
SET_SECOND(second);
11391149
FAST_DISPATCH();
@@ -1173,7 +1183,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
11731183
SET_TOP(Py_False);
11741184
DISPATCH();
11751185
}
1176-
STACKADJ(-1);
1186+
STACK_SHRINK(1);
11771187
goto error;
11781188
}
11791189

@@ -1569,7 +1579,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
15691579
PyObject *container = SECOND();
15701580
PyObject *v = THIRD();
15711581
int err;
1572-
STACKADJ(-3);
1582+
STACK_SHRINK(3);
15731583
/* container[sub] = v */
15741584
err = PyObject_SetItem(container, sub, v);
15751585
Py_DECREF(v);
@@ -1584,7 +1594,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
15841594
PyObject *sub = TOP();
15851595
PyObject *container = SECOND();
15861596
int err;
1587-
STACKADJ(-2);
1597+
STACK_SHRINK(2);
15881598
/* del container[sub] */
15891599
err = PyObject_DelItem(container, sub);
15901600
Py_DECREF(container);
@@ -2067,7 +2077,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
20672077
}
20682078
} else if (unpack_iterable(seq, oparg, -1,
20692079
stack_pointer + oparg)) {
2070-
STACKADJ(oparg);
2080+
STACK_GROW(oparg);
20712081
} else {
20722082
/* unpack_iterable() raised an exception */
20732083
Py_DECREF(seq);
@@ -2097,7 +2107,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
20972107
PyObject *owner = TOP();
20982108
PyObject *v = SECOND();
20992109
int err;
2100-
STACKADJ(-2);
2110+
STACK_SHRINK(2);
21012111
err = PyObject_SetAttr(owner, name, v);
21022112
Py_DECREF(v);
21032113
Py_DECREF(owner);
@@ -2420,7 +2430,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
24202430
err = PySet_Add(set, item);
24212431
Py_DECREF(item);
24222432
}
2423-
STACKADJ(-oparg);
2433+
STACK_SHRINK(oparg);
24242434
if (err != 0) {
24252435
Py_DECREF(set);
24262436
goto error;
@@ -2641,7 +2651,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
26412651
PyObject *value = SECOND();
26422652
PyObject *map;
26432653
int err;
2644-
STACKADJ(-2);
2654+
STACK_SHRINK(2);
26452655
map = PEEK(oparg); /* dict */
26462656
assert(PyDict_CheckExact(map));
26472657
err = PyDict_SetItem(map, key, value); /* map[key] = value */
@@ -2784,7 +2794,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
27842794
PyObject *cond = TOP();
27852795
int err;
27862796
if (cond == Py_True) {
2787-
STACKADJ(-1);
2797+
STACK_SHRINK(1);
27882798
Py_DECREF(cond);
27892799
FAST_DISPATCH();
27902800
}
@@ -2794,7 +2804,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
27942804
}
27952805
err = PyObject_IsTrue(cond);
27962806
if (err > 0) {
2797-
STACKADJ(-1);
2807+
STACK_SHRINK(1);
27982808
Py_DECREF(cond);
27992809
}
28002810
else if (err == 0)
@@ -2808,7 +2818,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
28082818
PyObject *cond = TOP();
28092819
int err;
28102820
if (cond == Py_False) {
2811-
STACKADJ(-1);
2821+
STACK_SHRINK(1);
28122822
Py_DECREF(cond);
28132823
FAST_DISPATCH();
28142824
}
@@ -2821,7 +2831,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
28212831
JUMPTO(oparg);
28222832
}
28232833
else if (err == 0) {
2824-
STACKADJ(-1);
2834+
STACK_SHRINK(1);
28252835
Py_DECREF(cond);
28262836
}
28272837
else
@@ -2907,7 +2917,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
29072917
PyErr_Clear();
29082918
}
29092919
/* iterator ended normally */
2910-
STACKADJ(-1);
2920+
STACK_SHRINK(1);
29112921
Py_DECREF(iter);
29122922
JUMPBY(oparg);
29132923
PREDICT(POP_BLOCK);
@@ -3015,7 +3025,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
30153025
val = tb = Py_None;
30163026
exc = TOP();
30173027
if (exc == NULL) {
3018-
STACKADJ(-1);
3028+
STACK_SHRINK(1);
30193029
exit_func = TOP();
30203030
SET_TOP(exc);
30213031
exc = Py_None;

0 commit comments

Comments
 (0)