Skip to content

Commit b5c19bd

Browse files
miss-islingtonsobolevnerlend-aasland
authored
[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 28b148f) Co-authored-by: sobolevn <mail@sobolevn.me> Co-authored-by: Erlend E. Aasland <erlend.aasland@protonmail.com>
1 parent ce5bb3c commit b5c19bd

File tree

3 files changed

+42
-0
lines changed

3 files changed

+42
-0
lines changed

Lib/test/test_cprofile.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,22 @@ def test_bad_counter_during_dealloc(self):
3030

3131
self.assertEqual(cm.unraisable.exc_type, TypeError)
3232

33+
def test_crash_with_not_enough_args(self):
34+
# gh-126220
35+
import _lsprof
36+
37+
for profile in [_lsprof.Profiler(), cProfile.Profile()]:
38+
for method in [
39+
"_pystart_callback",
40+
"_pyreturn_callback",
41+
"_ccall_callback",
42+
"_creturn_callback",
43+
]:
44+
with self.subTest(profile=profile, method=method):
45+
method_obj = getattr(profile, method)
46+
with self.assertRaises(TypeError):
47+
method_obj() # should not crash
48+
3349
def test_evil_external_timer(self):
3450
# gh-120289
3551
# Disabling profiler in external timer should not crash
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix crash in :class:`!cProfile.Profile` and :class:`!_lsprof.Profiler` when their
2+
callbacks were directly called with 0 arguments.

Modules/_lsprof.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,12 @@ setBuiltins(ProfilerObject *pObj, int nvalue)
604604

605605
PyObject* pystart_callback(ProfilerObject* self, PyObject *const *args, Py_ssize_t size)
606606
{
607+
if (size < 2) {
608+
PyErr_Format(PyExc_TypeError,
609+
"_pystart_callback expected 2 arguments, got %zd",
610+
size);
611+
return NULL;
612+
}
607613
PyObject* code = args[0];
608614
ptrace_enter_call((PyObject*)self, (void *)code, (PyObject *)code);
609615

@@ -612,6 +618,12 @@ PyObject* pystart_callback(ProfilerObject* self, PyObject *const *args, Py_ssize
612618

613619
PyObject* pyreturn_callback(ProfilerObject* self, PyObject *const *args, Py_ssize_t size)
614620
{
621+
if (size < 3) {
622+
PyErr_Format(PyExc_TypeError,
623+
"_pyreturn_callback expected 3 arguments, got %zd",
624+
size);
625+
return NULL;
626+
}
615627
PyObject* code = args[0];
616628
ptrace_leave_call((PyObject*)self, (void *)code);
617629

@@ -647,6 +659,12 @@ PyObject* get_cfunc_from_callable(PyObject* callable, PyObject* self_arg, PyObje
647659

648660
PyObject* ccall_callback(ProfilerObject* self, PyObject *const *args, Py_ssize_t size)
649661
{
662+
if (size < 4) {
663+
PyErr_Format(PyExc_TypeError,
664+
"_ccall_callback expected 4 arguments, got %zd",
665+
size);
666+
return NULL;
667+
}
650668
if (self->flags & POF_BUILTINS) {
651669
PyObject* callable = args[2];
652670
PyObject* self_arg = args[3];
@@ -665,6 +683,12 @@ PyObject* ccall_callback(ProfilerObject* self, PyObject *const *args, Py_ssize_t
665683

666684
PyObject* creturn_callback(ProfilerObject* self, PyObject *const *args, Py_ssize_t size)
667685
{
686+
if (size < 4) {
687+
PyErr_Format(PyExc_TypeError,
688+
"_creturn_callback expected 4 arguments, got %zd",
689+
size);
690+
return NULL;
691+
}
668692
if (self->flags & POF_BUILTINS) {
669693
PyObject* callable = args[2];
670694
PyObject* self_arg = args[3];

0 commit comments

Comments
 (0)