Skip to content

Commit 1966f1c

Browse files
committed
Fix refleaks exposed by test_raise.
1 parent 1963ad3 commit 1966f1c

3 files changed

Lines changed: 31 additions & 3 deletions

File tree

Lib/test/test_raise.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ def test_reraise(self):
3737
else:
3838
self.fail("No exception raised")
3939

40+
def test_erroneous_exception(self):
41+
class MyException(Exception):
42+
def __init__(self):
43+
raise RuntimeError()
44+
45+
try:
46+
raise MyException
47+
except RuntimeError:
48+
pass
49+
else:
50+
self.fail("No exception raised")
51+
4052

4153
class TestCause(unittest.TestCase):
4254
def test_invalid_cause(self):
@@ -64,6 +76,18 @@ def test_instance_cause(self):
6476
else:
6577
self.fail("No exception raised")
6678

79+
def test_erroneous_cause(self):
80+
class MyException(Exception):
81+
def __init__(self):
82+
raise RuntimeError()
83+
84+
try:
85+
raise IndexError from MyException
86+
except RuntimeError:
87+
pass
88+
else:
89+
self.fail("No exception raised")
90+
6791

6892
class TestTraceback(unittest.TestCase):
6993
def test_sets_traceback(self):

Objects/exceptions.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2828
return NULL;
2929
/* the dict is created on the fly in PyObject_GenericSetAttr */
3030
self->dict = NULL;
31-
self->traceback = NULL;
31+
self->traceback = self->cause = self->context = NULL;
3232

3333
self->args = PyTuple_New(0);
3434
if (!self->args) {
@@ -58,6 +58,8 @@ BaseException_clear(PyBaseExceptionObject *self)
5858
Py_CLEAR(self->dict);
5959
Py_CLEAR(self->args);
6060
Py_CLEAR(self->traceback);
61+
Py_CLEAR(self->cause);
62+
Py_CLEAR(self->context);
6163
return 0;
6264
}
6365

@@ -75,6 +77,8 @@ BaseException_traverse(PyBaseExceptionObject *self, visitproc visit, void *arg)
7577
Py_VISIT(self->dict);
7678
Py_VISIT(self->args);
7779
Py_VISIT(self->traceback);
80+
Py_VISIT(self->cause);
81+
Py_VISIT(self->context);
7882
return 0;
7983
}
8084

Python/ceval.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2967,7 +2967,6 @@ do_raise(PyObject *exc, PyObject *cause)
29672967
/* Not something you can raise. You get an exception
29682968
anyway, just not what you specified :-) */
29692969
Py_DECREF(exc);
2970-
Py_XDECREF(cause);
29712970
PyErr_SetString(PyExc_TypeError,
29722971
"exceptions must derive from BaseException");
29732972
goto raise_error;
@@ -2980,12 +2979,12 @@ do_raise(PyObject *exc, PyObject *cause)
29802979
fixed_cause = PyObject_CallObject(cause, NULL);
29812980
if (fixed_cause == NULL)
29822981
goto raise_error;
2982+
Py_DECREF(cause);
29832983
}
29842984
else if (PyExceptionInstance_Check(cause)) {
29852985
fixed_cause = cause;
29862986
}
29872987
else {
2988-
Py_DECREF(cause);
29892988
PyErr_SetString(PyExc_TypeError,
29902989
"exception causes must derive from BaseException");
29912990
goto raise_error;
@@ -3000,6 +2999,7 @@ do_raise(PyObject *exc, PyObject *cause)
30002999
Py_XDECREF(value);
30013000
Py_XDECREF(type);
30023001
Py_XDECREF(tb);
3002+
Py_XDECREF(cause);
30033003
return WHY_EXCEPTION;
30043004
}
30053005

0 commit comments

Comments
 (0)