]> granicus.if.org Git - python/commitdiff
port 8d05f697acd4 (#11627)
authorBenjamin Peterson <benjamin@python.org>
Fri, 15 Jul 2011 19:15:40 +0000 (14:15 -0500)
committerBenjamin Peterson <benjamin@python.org>
Fri, 15 Jul 2011 19:15:40 +0000 (14:15 -0500)
Lib/test/test_exceptions.py
Misc/NEWS
Python/ceval.c

index a19c82d0665344072e22d16983225254155ee321..5526fb77eb8e68b3fa47d599fae1a92eeb697189 100644 (file)
@@ -464,6 +464,14 @@ class ExceptionTests(unittest.TestCase):
             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
index 4f1f1cf0617685161de3146d9db51944648bed33..867ef9ce6cc9a26ae631b210fd6c3f841ea74e47 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -9,6 +9,9 @@ What's New in Python 2.7.3?
 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
index 10dd3a1f290fff76ce4d857b53b7f14ac62e4a93..06ada972743aebcf410697d5ad79306758c5dbbb 100644 (file)
@@ -3515,9 +3515,17 @@ do_raise(PyObject *type, PyObject *value, PyObject *tb)
         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) {