diff options
author | jdemeyer <jdemeyer@cage.ugent.be> | 2018-07-21 08:30:59 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2018-07-21 08:30:59 (GMT) |
commit | 56868f940e0cc0b35d33c0070107ff3bed2d8766 (patch) | |
tree | cf89ed80def829ba86fee5c2c2db623db134fc34 | |
parent | a692efe4733f98831cb51a9683877b152f754d14 (diff) | |
download | cpython-56868f940e0cc0b35d33c0070107ff3bed2d8766.zip cpython-56868f940e0cc0b35d33c0070107ff3bed2d8766.tar.gz cpython-56868f940e0cc0b35d33c0070107ff3bed2d8766.tar.bz2 |
bpo-34126: Fix crashes while profiling invalid calls. (GH-8300)
-rw-r--r-- | Lib/test/test_sys_setprofile.py | 16 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2018-07-16-20-55-29.bpo-34126.mBVmgc.rst | 2 | ||||
-rw-r--r-- | Python/ceval.c | 14 |
3 files changed, 28 insertions, 4 deletions
diff --git a/Lib/test/test_sys_setprofile.py b/Lib/test/test_sys_setprofile.py index a3e1d31..16467e7 100644 --- a/Lib/test/test_sys_setprofile.py +++ b/Lib/test/test_sys_setprofile.py @@ -334,6 +334,22 @@ class ProfileSimulatorTestCase(TestCaseBase): (1, 'return', j_ident), ]) + # Test an invalid call (bpo-34126) + def test_unbound_method_no_args(self): + def f(p): + dict.get() + f_ident = ident(f) + self.check_events(f, [(1, 'call', f_ident), + (1, 'return', f_ident)]) + + # Test an invalid call (bpo-34126) + def test_unbound_method_invalid_args(self): + def f(p): + dict.get(print, 42) + f_ident = ident(f) + self.check_events(f, [(1, 'call', f_ident), + (1, 'return', f_ident)]) + def ident(function): if hasattr(function, "f_code"): diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-07-16-20-55-29.bpo-34126.mBVmgc.rst b/Misc/NEWS.d/next/Core and Builtins/2018-07-16-20-55-29.bpo-34126.mBVmgc.rst new file mode 100644 index 0000000..7cfc439 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-07-16-20-55-29.bpo-34126.mBVmgc.rst @@ -0,0 +1,2 @@ +Fix crashes when profiling certain invalid calls of unbound methods. +Patch by Jeroen Demeyer. diff --git a/Python/ceval.c b/Python/ceval.c index 90ad591..465e030 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4566,10 +4566,16 @@ call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *kwnames) } else if (Py_TYPE(func) == &PyMethodDescr_Type) { PyThreadState *tstate = PyThreadState_GET(); - if (tstate->use_tracing && tstate->c_profilefunc) { - // We need to create PyCFunctionObject for tracing. - PyMethodDescrObject *descr = (PyMethodDescrObject*)func; - func = PyCFunction_NewEx(descr->d_method, stack[0], NULL); + if (nargs > 0 && tstate->use_tracing) { + /* We need to create a temporary bound method as argument + for profiling. + + If nargs == 0, then this cannot work because we have no + "self". In any case, the call itself would raise + TypeError (foo needs an argument), so we just skip + profiling. */ + PyObject *self = stack[0]; + func = Py_TYPE(func)->tp_descr_get(func, self, (PyObject*)Py_TYPE(self)); if (func == NULL) { return NULL; } |