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.
This commit is contained in:
parent
944451cd8d
commit
8ed317f1ca
|
@ -0,0 +1,31 @@
|
|||
import os
|
||||
import textwrap
|
||||
import unittest
|
||||
|
||||
from test import support
|
||||
from test.support.script_helper import assert_python_ok
|
||||
|
||||
|
||||
class TestLLTrace(unittest.TestCase):
|
||||
|
||||
def test_lltrace_does_not_crash_on_subscript_operator(self):
|
||||
# If this test fails, it will reproduce a crash reported as
|
||||
# bpo-34113. The crash happened at the command line console of
|
||||
# debug Python builds with __ltrace__ enabled (only possible in console),
|
||||
# when the interal Python stack was negatively adjusted
|
||||
with open(support.TESTFN, 'w') as fd:
|
||||
self.addCleanup(os.unlink, support.TESTFN)
|
||||
fd.write(textwrap.dedent("""\
|
||||
import code
|
||||
|
||||
console = code.InteractiveConsole()
|
||||
console.push('__ltrace__ = 1')
|
||||
console.push('a = [1, 2, 3]')
|
||||
console.push('a[0] = 1')
|
||||
print('unreachable if bug exists')
|
||||
"""))
|
||||
|
||||
assert_python_ok(support.TESTFN)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -0,0 +1,2 @@
|
|||
Fixed crash on debug builds when opcode stack was adjusted with negative
|
||||
numbers. Patch by Constantin Petrisor.
|
|
@ -762,16 +762,26 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
|
|||
assert(STACK_LEVEL() <= co->co_stacksize); }
|
||||
#define POP() ((void)(lltrace && prtrace(TOP(), "pop")), \
|
||||
BASIC_POP())
|
||||
#define STACKADJ(n) { (void)(BASIC_STACKADJ(n), \
|
||||
#define STACK_GROW(n) do { \
|
||||
assert(n >= 0); \
|
||||
(void)(BASIC_STACKADJ(n), \
|
||||
lltrace && prtrace(TOP(), "stackadj")); \
|
||||
assert(STACK_LEVEL() <= co->co_stacksize); }
|
||||
assert(STACK_LEVEL() <= co->co_stacksize); \
|
||||
} while (0)
|
||||
#define STACK_SHRINK(n) do { \
|
||||
assert(n >= 0); \
|
||||
(void)(lltrace && prtrace(TOP(), "stackadj")); \
|
||||
(void)(BASIC_STACKADJ(-n)); \
|
||||
assert(STACK_LEVEL() <= co->co_stacksize); \
|
||||
} while (0)
|
||||
#define EXT_POP(STACK_POINTER) ((void)(lltrace && \
|
||||
prtrace((STACK_POINTER)[-1], "ext_pop")), \
|
||||
*--(STACK_POINTER))
|
||||
#else
|
||||
#define PUSH(v) BASIC_PUSH(v)
|
||||
#define POP() BASIC_POP()
|
||||
#define STACKADJ(n) BASIC_STACKADJ(n)
|
||||
#define STACK_GROW(n) BASIC_STACKADJ(n)
|
||||
#define STACK_SHRINK(n) BASIC_STACKADJ(-n)
|
||||
#define EXT_POP(STACK_POINTER) (*--(STACK_POINTER))
|
||||
#endif
|
||||
|
||||
|
@ -1133,7 +1143,7 @@ main_loop:
|
|||
PyObject *second = SECOND();
|
||||
Py_INCREF(top);
|
||||
Py_INCREF(second);
|
||||
STACKADJ(2);
|
||||
STACK_GROW(2);
|
||||
SET_TOP(top);
|
||||
SET_SECOND(second);
|
||||
FAST_DISPATCH();
|
||||
|
@ -1173,7 +1183,7 @@ main_loop:
|
|||
SET_TOP(Py_False);
|
||||
DISPATCH();
|
||||
}
|
||||
STACKADJ(-1);
|
||||
STACK_SHRINK(1);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -1569,7 +1579,7 @@ main_loop:
|
|||
PyObject *container = SECOND();
|
||||
PyObject *v = THIRD();
|
||||
int err;
|
||||
STACKADJ(-3);
|
||||
STACK_SHRINK(3);
|
||||
/* container[sub] = v */
|
||||
err = PyObject_SetItem(container, sub, v);
|
||||
Py_DECREF(v);
|
||||
|
@ -1584,7 +1594,7 @@ main_loop:
|
|||
PyObject *sub = TOP();
|
||||
PyObject *container = SECOND();
|
||||
int err;
|
||||
STACKADJ(-2);
|
||||
STACK_SHRINK(2);
|
||||
/* del container[sub] */
|
||||
err = PyObject_DelItem(container, sub);
|
||||
Py_DECREF(container);
|
||||
|
@ -2067,7 +2077,7 @@ main_loop:
|
|||
}
|
||||
} else if (unpack_iterable(seq, oparg, -1,
|
||||
stack_pointer + oparg)) {
|
||||
STACKADJ(oparg);
|
||||
STACK_GROW(oparg);
|
||||
} else {
|
||||
/* unpack_iterable() raised an exception */
|
||||
Py_DECREF(seq);
|
||||
|
@ -2097,7 +2107,7 @@ main_loop:
|
|||
PyObject *owner = TOP();
|
||||
PyObject *v = SECOND();
|
||||
int err;
|
||||
STACKADJ(-2);
|
||||
STACK_SHRINK(2);
|
||||
err = PyObject_SetAttr(owner, name, v);
|
||||
Py_DECREF(v);
|
||||
Py_DECREF(owner);
|
||||
|
@ -2420,7 +2430,7 @@ main_loop:
|
|||
err = PySet_Add(set, item);
|
||||
Py_DECREF(item);
|
||||
}
|
||||
STACKADJ(-oparg);
|
||||
STACK_SHRINK(oparg);
|
||||
if (err != 0) {
|
||||
Py_DECREF(set);
|
||||
goto error;
|
||||
|
@ -2641,7 +2651,7 @@ main_loop:
|
|||
PyObject *value = SECOND();
|
||||
PyObject *map;
|
||||
int err;
|
||||
STACKADJ(-2);
|
||||
STACK_SHRINK(2);
|
||||
map = PEEK(oparg); /* dict */
|
||||
assert(PyDict_CheckExact(map));
|
||||
err = PyDict_SetItem(map, key, value); /* map[key] = value */
|
||||
|
@ -2784,7 +2794,7 @@ main_loop:
|
|||
PyObject *cond = TOP();
|
||||
int err;
|
||||
if (cond == Py_True) {
|
||||
STACKADJ(-1);
|
||||
STACK_SHRINK(1);
|
||||
Py_DECREF(cond);
|
||||
FAST_DISPATCH();
|
||||
}
|
||||
|
@ -2794,7 +2804,7 @@ main_loop:
|
|||
}
|
||||
err = PyObject_IsTrue(cond);
|
||||
if (err > 0) {
|
||||
STACKADJ(-1);
|
||||
STACK_SHRINK(1);
|
||||
Py_DECREF(cond);
|
||||
}
|
||||
else if (err == 0)
|
||||
|
@ -2808,7 +2818,7 @@ main_loop:
|
|||
PyObject *cond = TOP();
|
||||
int err;
|
||||
if (cond == Py_False) {
|
||||
STACKADJ(-1);
|
||||
STACK_SHRINK(1);
|
||||
Py_DECREF(cond);
|
||||
FAST_DISPATCH();
|
||||
}
|
||||
|
@ -2821,7 +2831,7 @@ main_loop:
|
|||
JUMPTO(oparg);
|
||||
}
|
||||
else if (err == 0) {
|
||||
STACKADJ(-1);
|
||||
STACK_SHRINK(1);
|
||||
Py_DECREF(cond);
|
||||
}
|
||||
else
|
||||
|
@ -2907,7 +2917,7 @@ main_loop:
|
|||
PyErr_Clear();
|
||||
}
|
||||
/* iterator ended normally */
|
||||
STACKADJ(-1);
|
||||
STACK_SHRINK(1);
|
||||
Py_DECREF(iter);
|
||||
JUMPBY(oparg);
|
||||
PREDICT(POP_BLOCK);
|
||||
|
@ -3015,7 +3025,7 @@ main_loop:
|
|||
val = tb = Py_None;
|
||||
exc = TOP();
|
||||
if (exc == NULL) {
|
||||
STACKADJ(-1);
|
||||
STACK_SHRINK(1);
|
||||
exit_func = TOP();
|
||||
SET_TOP(exc);
|
||||
exc = Py_None;
|
||||
|
|
Loading…
Reference in New Issue