Skip to content

Commit

Permalink
gh-126220: Fix crash on calls to _lsprof.Profiler methods with 0 ar…
Browse files Browse the repository at this point in the history
…gs (backportable) (GH-126271)

(cherry picked from commit 28b148f)

Co-authored-by: sobolevn <[email protected]>
Co-authored-by: Erlend E. Aasland <[email protected]>
  • Loading branch information
2 people authored and miss-islington committed Nov 1, 2024
1 parent ce5bb3c commit 4197d40
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 0 deletions.
16 changes: 16 additions & 0 deletions Lib/test/test_cprofile.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,22 @@ def test_bad_counter_during_dealloc(self):

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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix crash in :class:`!cProfile.Profile` and :class:`!_lsprof.Profiler` when their
callbacks were directly called with 0 arguments.
24 changes: 24 additions & 0 deletions Modules/_lsprof.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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);

Expand Down Expand Up @@ -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];
Expand All @@ -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];
Expand Down

0 comments on commit 4197d40

Please sign in to comment.