From: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> Date: Fri, 1 Nov 2024 22:18:50 +0000 (+0100) Subject: [3.12] gh-126220: Fix crash on calls to `_lsprof.Profiler` methods with 0 args (backp... X-Git-Tag: v3.12.8~124 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b5c19bdba8f58cba80a1101ce8aad90be3486571;p=thirdparty%2FPython%2Fcpython.git [3.12] gh-126220: Fix crash on calls to `_lsprof.Profiler` methods with 0 args (backportable) (GH-126271) (#126311) gh-126220: Fix crash on calls to `_lsprof.Profiler` methods with 0 args (backportable) (GH-126271) (cherry picked from commit 28b148fb32e4548b461137d18d1ab6d366395d36) Co-authored-by: sobolevn Co-authored-by: Erlend E. Aasland --- diff --git a/Lib/test/test_cprofile.py b/Lib/test/test_cprofile.py index 14d69b6f5f3f..3b7fd034276a 100644 --- a/Lib/test/test_cprofile.py +++ b/Lib/test/test_cprofile.py @@ -30,6 +30,22 @@ class CProfileTest(ProfileTest): self.assertEqual(cm.unraisable.exc_type, TypeError) + def test_crash_with_not_enough_args(self): + # gh-126220 + import _lsprof + + for profile in [_lsprof.Profiler(), cProfile.Profile()]: + for method in [ + "_pystart_callback", + "_pyreturn_callback", + "_ccall_callback", + "_creturn_callback", + ]: + with self.subTest(profile=profile, method=method): + method_obj = getattr(profile, method) + with self.assertRaises(TypeError): + method_obj() # should not crash + def test_evil_external_timer(self): # gh-120289 # Disabling profiler in external timer should not crash diff --git a/Misc/NEWS.d/next/Library/2024-10-31-14-06-28.gh-issue-126220.uJAJCU.rst b/Misc/NEWS.d/next/Library/2024-10-31-14-06-28.gh-issue-126220.uJAJCU.rst new file mode 100644 index 000000000000..555f2f3bafbf --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-10-31-14-06-28.gh-issue-126220.uJAJCU.rst @@ -0,0 +1,2 @@ +Fix crash in :class:`!cProfile.Profile` and :class:`!_lsprof.Profiler` when their +callbacks were directly called with 0 arguments. diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index 2c82b18c0e18..d11689906e57 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -604,6 +604,12 @@ setBuiltins(ProfilerObject *pObj, int nvalue) PyObject* pystart_callback(ProfilerObject* self, PyObject *const *args, Py_ssize_t size) { + if (size < 2) { + PyErr_Format(PyExc_TypeError, + "_pystart_callback expected 2 arguments, got %zd", + size); + return NULL; + } PyObject* code = args[0]; ptrace_enter_call((PyObject*)self, (void *)code, (PyObject *)code); @@ -612,6 +618,12 @@ PyObject* pystart_callback(ProfilerObject* self, PyObject *const *args, Py_ssize PyObject* pyreturn_callback(ProfilerObject* self, PyObject *const *args, Py_ssize_t size) { + if (size < 3) { + PyErr_Format(PyExc_TypeError, + "_pyreturn_callback expected 3 arguments, got %zd", + size); + return NULL; + } PyObject* code = args[0]; ptrace_leave_call((PyObject*)self, (void *)code); @@ -647,6 +659,12 @@ PyObject* get_cfunc_from_callable(PyObject* callable, PyObject* self_arg, PyObje PyObject* ccall_callback(ProfilerObject* self, PyObject *const *args, Py_ssize_t size) { + if (size < 4) { + PyErr_Format(PyExc_TypeError, + "_ccall_callback expected 4 arguments, got %zd", + size); + return NULL; + } if (self->flags & POF_BUILTINS) { PyObject* callable = args[2]; PyObject* self_arg = args[3]; @@ -665,6 +683,12 @@ PyObject* ccall_callback(ProfilerObject* self, PyObject *const *args, Py_ssize_t PyObject* creturn_callback(ProfilerObject* self, PyObject *const *args, Py_ssize_t size) { + if (size < 4) { + PyErr_Format(PyExc_TypeError, + "_creturn_callback expected 4 arguments, got %zd", + size); + return NULL; + } if (self->flags & POF_BUILTINS) { PyObject* callable = args[2]; PyObject* self_arg = args[3];