[Python-checkins] cpython (2.7): port 8d05f697acd4 (#11627)

benjamin.peterson python-checkins at python.org
Fri Jul 15 21:10:55 CEST 2011


http://hg.python.org/cpython/rev/45b1ae1ef318
changeset:   71354:45b1ae1ef318
branch:      2.7
parent:      71333:16bc59d37866
user:        Benjamin Peterson <benjamin at python.org>
date:        Fri Jul 15 14:15:40 2011 -0500
summary:
  port 8d05f697acd4 (#11627)

files:
  Lib/test/test_exceptions.py |   8 ++++++++
  Misc/NEWS                   |   3 +++
  Python/ceval.c              |  12 ++++++++++--
  3 files changed, 21 insertions(+), 2 deletions(-)


diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -464,6 +464,14 @@
             self.assertTrue(e is RuntimeError, e)
             self.assertIn("maximum recursion depth exceeded", str(v))
 
+    def test_new_returns_invalid_instance(self):
+        # See issue #11627.
+        class MyException(Exception):
+            def __new__(cls, *args):
+                return object()
+
+        with self.assertRaises(TypeError):
+            raise MyException
 
 
 # Helper class used by TestSameStrAndUnicodeMsg
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -9,6 +9,9 @@
 Core and Builtins
 -----------------
 
+- Issue #11627: Fix segfault when __new__ on a exception returns a non-exception
+  class.
+
 - Issue #12149: Update the method cache after a type's dictionnary gets
   cleared by the garbage collector.  This fixes a segfault when an instance
   and its type get caught in a reference cycle, and the instance's
diff --git a/Python/ceval.c b/Python/ceval.c
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -3515,9 +3515,17 @@
         Py_DECREF(tmp);
     }
 
-    if (PyExceptionClass_Check(type))
+    if (PyExceptionClass_Check(type)) {
         PyErr_NormalizeException(&type, &value, &tb);
-
+        if (!PyExceptionInstance_Check(value)) {
+            PyErr_Format(PyExc_TypeError,
+                         "calling %s() should have returned an instance of "
+                         "BaseException, not '%s'",
+                         ((PyTypeObject *)type)->tp_name,
+                         Py_TYPE(value)->tp_name);
+            goto raise_error;
+        }
+    }
     else if (PyExceptionInstance_Check(type)) {
         /* Raising an instance.  The value should be a dummy. */
         if (value != Py_None) {

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list