https://github.com/python/cpython/commit/d32160aab15e3d4a5c9c09537605e61f2ba418a6 commit: d32160aab15e3d4a5c9c09537605e61f2ba418a6 branch: 3.15 author: Miss Islington (bot) <[email protected]> committer: pablogsal <[email protected]> date: 2026-09-24T16:29:21Z summary:
[3.15] gh-157639: Fix use-after-free when an external timer re-enters the profiler (GH-157648) (#158113) gh-157639: Fix use-after-free when an external timer re-enters the profiler (GH-157648) * gh-157639: Fix use-after-free when an external timer re-enters the profiler * Suppress the cProfile link in the NEWS entry * Add braces around the external timer guards, per PEP 7 * Simplify the external timer test setup * Do not call the external timer while deallocating the profiler (cherry picked from commit a6fa91cab267ea634a3cc2f3f7eeb22697b1358f) Co-authored-by: Lazizbek Ergashev <[email protected]> files: A Misc/NEWS.d/next/Library/2026-09-17-03-20-24.gh-issue-157639.VP3kc4.rst M Lib/test/test_profiling/test_tracing_profiler.py M Modules/_lsprof.c diff --git a/Lib/test/test_profiling/test_tracing_profiler.py b/Lib/test/test_profiling/test_tracing_profiler.py index 6a4d968f12ef15..50de9af86e86d0 100644 --- a/Lib/test/test_profiling/test_tracing_profiler.py +++ b/Lib/test/test_profiling/test_tracing_profiler.py @@ -85,6 +85,27 @@ def __call__(self): profiler_with_evil_timer.clear() self.assertEqual(cm.unraisable.exc_type, RuntimeError) + def test_enable_in_external_timer(self): + # gh-157639: Enabling the profiler from an external timer should not crash + import _lsprof + + # the timer re-arms monitoring from inside disable(), so the tool + # id stays claimed once the profiler is torn down + self.addCleanup(sys.monitoring.free_tool_id, sys.monitoring.PROFILER_ID) + + def timer(): + try: + profiler.enable() + except Exception: + pass + return 0 + + profiler = _lsprof.Profiler(timer=timer) + profiler.enable() + (lambda: None)() + profiler.disable() + profiler.clear() + def test_profile_enable_disable(self): prof = self.profilerclass() # Make sure we clean ourselves up if the test fails for some reason. diff --git a/Misc/NEWS.d/next/Library/2026-09-17-03-20-24.gh-issue-157639.VP3kc4.rst b/Misc/NEWS.d/next/Library/2026-09-17-03-20-24.gh-issue-157639.VP3kc4.rst new file mode 100644 index 00000000000000..de1fd1286d7a57 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-09-17-03-20-24.gh-issue-157639.VP3kc4.rst @@ -0,0 +1,3 @@ +Fix a crash in :mod:`!cProfile` when an external timer re-enters the +profiler. Profiling events raised while the external timer runs are now +ignored. diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index 4e50ca64f59af2..65857c495f2339 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -363,6 +363,12 @@ ptrace_enter_call(PyObject *self, void *key, PyObject *userObj) ProfilerEntry *profEntry; ProfilerContext *pContext; + /* Events raised by the external timer must be ignored: it can run + arbitrary code while a context is still being unwound. */ + if (pObj->flags & POF_EXT_TIMER) { + return; + } + /* In the case of entering a generator expression frame via a * throw (gen_send_ex(.., 1)), we may already have an * Exception set here. We must not mess around with this @@ -405,6 +411,10 @@ ptrace_leave_call(PyObject *self, void *key) ProfilerEntry *profEntry; ProfilerContext *pContext; + if (pObj->flags & POF_EXT_TIMER) { + return; + } + pContext = pObj->currentProfilerContext; if (pContext == NULL) return; @@ -980,10 +990,13 @@ profiler_dealloc(PyObject *op) } } + /* Drop the external timer before flushing: it is Python code, and the + profiler can be deallocated by the garbage collector. */ + Py_CLEAR(self->externalTimer); + flush_unmatched(self); clearEntries(self); Py_XDECREF(self->missing); - Py_XDECREF(self->externalTimer); PyTypeObject *tp = Py_TYPE(self); tp->tp_free(self); Py_DECREF(tp); _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
