]> granicus.if.org Git - python/commitdiff
Issue #23996: Avoid a crash when a delegated generator raises an unnormalized StopIte...
authorAntoine Pitrou <solipsis@pitrou.net>
Sun, 26 Apr 2015 16:46:40 +0000 (18:46 +0200)
committerAntoine Pitrou <solipsis@pitrou.net>
Sun, 26 Apr 2015 16:46:40 +0000 (18:46 +0200)
Misc/NEWS
Objects/genobject.c

index 2616bf7d932525294adeaaf20bd4914ecbd309d7..e84e142857d37243423a2caa85cb22cd5a942700 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ Release date: tba
 Core and Builtins
 -----------------
 
+- Issue #23996: Avoid a crash when a delegated generator raises an
+  unnormalized StopIteration exception.  Patch by Stefan Behnel.
+
 - Issue #24022: Fix tokenizer crash when processing undecodable source code.
 
 - Issue #23309: Avoid a deadlock at shutdown if a daemon thread is aborted
index 08d30bf4b7b7e71d0f382bd9dae393eb5490749d..f125847bd796fc79e79174abf6d6284539e85efb 100644 (file)
@@ -396,13 +396,30 @@ _PyGen_FetchStopIterationValue(PyObject **pvalue) {
 
     if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
         PyErr_Fetch(&et, &ev, &tb);
-        Py_XDECREF(et);
-        Py_XDECREF(tb);
         if (ev) {
-            value = ((PyStopIterationObject *)ev)->value;
-            Py_INCREF(value);
-            Py_DECREF(ev);
+            /* exception will usually be normalised already */
+            if (Py_TYPE(ev) == (PyTypeObject *) et
+                || PyObject_IsInstance(ev, PyExc_StopIteration)) {
+                value = ((PyStopIterationObject *)ev)->value;
+                Py_INCREF(value);
+                Py_DECREF(ev);
+            } else if (et == PyExc_StopIteration) {
+                /* avoid normalisation and take ev as value */
+                value = ev;
+            } else {
+                /* normalisation required */
+                PyErr_NormalizeException(&et, &ev, &tb);
+                if (!PyObject_IsInstance(ev, PyExc_StopIteration)) {
+                    PyErr_Restore(et, ev, tb);
+                    return -1;
+                }
+                value = ((PyStopIterationObject *)ev)->value;
+                Py_INCREF(value);
+                Py_DECREF(ev);
+            }
         }
+        Py_XDECREF(et);
+        Py_XDECREF(tb);
     } else if (PyErr_Occurred()) {
         return -1;
     }