Commit b2d61bde authored by Brett Cannon's avatar Brett Cannon

The _lsprof module could crash the interpreter if it was given an external

timer that did not return a float and a timer was still running when the
Profiler object was garbage collected.

Fixes issue 3895.
Code review by Benjamin Peterson.
parent 09c01782
"""Test suite for the cProfile module."""
import sys
from test.test_support import run_unittest
from test.test_support import run_unittest, TESTFN, unlink
# rip off all interesting stuff from test_profile
import cProfile
......@@ -10,6 +10,20 @@ from test.test_profile import ProfileTest, regenerate_expected_output
class CProfileTest(ProfileTest):
profilerclass = cProfile.Profile
# Issue 3895.
def test_bad_counter_during_dealloc(self):
import _lsprof
# Must use a file as StringIO doesn't trigger the bug.
sys.stderr = open(TESTFN, 'w')
try:
obj = _lsprof.Profiler(lambda: int)
obj.enable()
obj = _lsprof.Profiler(1)
obj.disable()
finally:
sys.stderr = sys.__stderr__
unlink(TESTFN)
def test_main():
run_unittest(CProfileTest)
......
......@@ -23,6 +23,10 @@ Core and Builtins
Library
-------
- Issue #3895: It was possible to crash the interpreter when an external timer
was used with cProfile that returned an object that could not be converted
into a float.
- Issue #3950: Made turtle respect scale factors.
- Issue #3547: Fixed ctypes structures bitfields of varying integer
......
......@@ -150,7 +150,16 @@ static PY_LONG_LONG CallExternalTimer(ProfilerObject *pObj)
}
Py_DECREF(o);
if (PyErr_Occurred()) {
PyErr_WriteUnraisable((PyObject *) pObj);
PyObject *context = (PyObject *)pObj;
/* May have been called by profiler_dealloc(). */
if (Py_REFCNT(context) < 1) {
context = PyString_FromString("profiler calling an "
"external timer");
if (context == NULL) {
return 0;
}
}
PyErr_WriteUnraisable(context);
return 0;
}
return result;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment