From 979f31172890fcfa45e5e23c461b1517a49dbf3b Mon Sep 17 00:00:00 2001
From: Benjamin Peterson <benjamin@python.org>
Date: Sun, 15 Jun 2008 00:05:44 +0000
Subject: [PATCH] #3114 fix a bus error when deallocated exceptions were used

---
 Lib/test/test_exceptions.py | 19 +++++++++++++++++++
 Python/ceval.c              | 12 ++++++------
 2 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py
index 55a57baee1..753e33bab3 100644
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -5,6 +5,8 @@ import sys
 import unittest
 import pickle
 import weakref
+import gc
+import traceback
 
 from test.support import TESTFN, unlink, run_unittest
 
@@ -551,6 +553,23 @@ class ExceptionTests(unittest.TestCase):
             del g
             self.assertEquals(sys.exc_info()[0], TypeError)
 
+    def test_crash_3114(self):
+        # Bug #3114: in its destructor, MyObject retrieves a pointer to a
+        # deallocated exception instance or traceback.
+        class MyObject:
+            def __del__(self):
+                nonlocal e
+                e = sys.exc_info()
+        e = ()
+        try:
+            raise Exception(MyObject())
+        except:
+            pass
+        gc.collect()
+        [0]*10000
+        # Do something with the exception and its traceback
+        traceback.format_exception(*e)
+
 def test_main():
     run_unittest(ExceptionTests)
 
diff --git a/Python/ceval.c b/Python/ceval.c
index 6aaa52dc6b..4b1478433b 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -704,11 +704,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
 		PyObject *v = POP(); \
 		Py_XDECREF(v); \
 	} \
-	Py_XDECREF(tstate->exc_type); \
+	Py_CLEAR(tstate->exc_type); \
+	Py_CLEAR(tstate->exc_value); \
+	Py_CLEAR(tstate->exc_traceback); \
 	tstate->exc_type = POP(); \
-	Py_XDECREF(tstate->exc_value); \
 	tstate->exc_value = POP(); \
-	Py_XDECREF(tstate->exc_traceback); \
 	tstate->exc_traceback = POP();
 
 #define SAVE_EXC_STATE() \
@@ -716,9 +716,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
 		Py_XINCREF(tstate->exc_type); \
 		Py_XINCREF(tstate->exc_value); \
 		Py_XINCREF(tstate->exc_traceback); \
-		Py_XDECREF(f->f_exc_type); \
-		Py_XDECREF(f->f_exc_value); \
-		Py_XDECREF(f->f_exc_traceback); \
+		Py_CLEAR(f->f_exc_type); \
+		Py_CLEAR(f->f_exc_value); \
+		Py_CLEAR(f->f_exc_traceback); \
 		f->f_exc_type = tstate->exc_type; \
 		f->f_exc_value = tstate->exc_value; \
 		f->f_exc_traceback = tstate->exc_traceback; \
-- 
2.49.0