From 1966f1c98f32c482b16f1a9c1a36fc8e0628486b Mon Sep 17 00:00:00 2001 From: Collin Winter Date: Sat, 1 Sep 2007 20:26:44 +0000 Subject: Fix refleaks exposed by test_raise. --- Lib/test/test_raise.py | 24 ++++++++++++++++++++++++ Objects/exceptions.c | 6 +++++- Python/ceval.c | 4 ++-- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_raise.py b/Lib/test/test_raise.py index 0e19972..27a5cbc 100644 --- a/Lib/test/test_raise.py +++ b/Lib/test/test_raise.py @@ -37,6 +37,18 @@ class TestRaise(unittest.TestCase): else: self.fail("No exception raised") + def test_erroneous_exception(self): + class MyException(Exception): + def __init__(self): + raise RuntimeError() + + try: + raise MyException + except RuntimeError: + pass + else: + self.fail("No exception raised") + class TestCause(unittest.TestCase): def test_invalid_cause(self): @@ -64,6 +76,18 @@ class TestCause(unittest.TestCase): else: self.fail("No exception raised") + def test_erroneous_cause(self): + class MyException(Exception): + def __init__(self): + raise RuntimeError() + + try: + raise IndexError from MyException + except RuntimeError: + pass + else: + self.fail("No exception raised") + class TestTraceback(unittest.TestCase): def test_sets_traceback(self): diff --git a/Objects/exceptions.c b/Objects/exceptions.c index cbc41e8..ce536fd 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -28,7 +28,7 @@ BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; /* the dict is created on the fly in PyObject_GenericSetAttr */ self->dict = NULL; - self->traceback = NULL; + self->traceback = self->cause = self->context = NULL; self->args = PyTuple_New(0); if (!self->args) { @@ -58,6 +58,8 @@ BaseException_clear(PyBaseExceptionObject *self) Py_CLEAR(self->dict); Py_CLEAR(self->args); Py_CLEAR(self->traceback); + Py_CLEAR(self->cause); + Py_CLEAR(self->context); return 0; } @@ -75,6 +77,8 @@ BaseException_traverse(PyBaseExceptionObject *self, visitproc visit, void *arg) Py_VISIT(self->dict); Py_VISIT(self->args); Py_VISIT(self->traceback); + Py_VISIT(self->cause); + Py_VISIT(self->context); return 0; } diff --git a/Python/ceval.c b/Python/ceval.c index 24d4dec..fa08fe6 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2967,7 +2967,6 @@ do_raise(PyObject *exc, PyObject *cause) /* Not something you can raise. You get an exception anyway, just not what you specified :-) */ Py_DECREF(exc); - Py_XDECREF(cause); PyErr_SetString(PyExc_TypeError, "exceptions must derive from BaseException"); goto raise_error; @@ -2980,12 +2979,12 @@ do_raise(PyObject *exc, PyObject *cause) fixed_cause = PyObject_CallObject(cause, NULL); if (fixed_cause == NULL) goto raise_error; + Py_DECREF(cause); } else if (PyExceptionInstance_Check(cause)) { fixed_cause = cause; } else { - Py_DECREF(cause); PyErr_SetString(PyExc_TypeError, "exception causes must derive from BaseException"); goto raise_error; @@ -3000,6 +2999,7 @@ raise_error: Py_XDECREF(value); Py_XDECREF(type); Py_XDECREF(tb); + Py_XDECREF(cause); return WHY_EXCEPTION; } -- cgit v0.12