summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_lltrace.py31
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2018-07-28-10-34-00.bpo-34113.eZ5FWV.rst2
-rw-r--r--Python/ceval.c44
3 files changed, 60 insertions, 17 deletions
diff --git a/Lib/test/test_lltrace.py b/Lib/test/test_lltrace.py
new file mode 100644
index 0000000..49fae81
--- /dev/null
+++ b/Lib/test/test_lltrace.py
@@ -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()
diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-07-28-10-34-00.bpo-34113.eZ5FWV.rst b/Misc/NEWS.d/next/Core and Builtins/2018-07-28-10-34-00.bpo-34113.eZ5FWV.rst
new file mode 100644
index 0000000..f4c80f9
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2018-07-28-10-34-00.bpo-34113.eZ5FWV.rst
@@ -0,0 +1,2 @@
+Fixed crash on debug builds when opcode stack was adjusted with negative
+numbers. Patch by Constantin Petrisor.
diff --git a/Python/ceval.c b/Python/ceval.c
index 8f0e0e0..46da295 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -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;