]> granicus.if.org Git - python/commitdiff
Issue 24374: Plug refleak in set_coroutine_wrapper
authorYury Selivanov <yselivanov@sprymix.com>
Thu, 4 Jun 2015 14:16:51 +0000 (10:16 -0400)
committerYury Selivanov <yselivanov@sprymix.com>
Thu, 4 Jun 2015 14:16:51 +0000 (10:16 -0400)
Lib/test/test_coroutines.py
Python/ceval.c

index 670852d20c06eee1b1628b89200c23f49edd6613..e3a33041c596fdcd57cd8de335b878ed61118b94 100644 (file)
@@ -1006,10 +1006,10 @@ class SysSetCoroWrapperTest(unittest.TestCase):
 
         sys.set_coroutine_wrapper(wrapper)
         try:
-            with self.assertRaisesRegex(
+            with silence_coro_gc(), self.assertRaisesRegex(
                 RuntimeError,
                 "coroutine wrapper.*\.wrapper at 0x.*attempted to "
-                "recursively wrap <coroutine.*\.wrap"):
+                "recursively wrap .* wrap .*"):
 
                 foo()
         finally:
index 96ed6ed4ee2831099977cf98f399ed16d8333844..641f9db317dda30c8edf0ef18ecb88ac53f985a9 100644 (file)
@@ -146,8 +146,6 @@ static void format_exc_unbound(PyCodeObject *co, int oparg);
 static PyObject * unicode_concatenate(PyObject *, PyObject *,
                                       PyFrameObject *, unsigned char *);
 static PyObject * special_lookup(PyObject *, _Py_Identifier *);
-static PyObject * apply_coroutine_wrapper(PyObject *);
-
 
 #define NAME_ERROR_MSG \
     "name '%.200s' is not defined"
@@ -3923,6 +3921,18 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
 
     if (co->co_flags & CO_GENERATOR) {
         PyObject *gen;
+        PyObject *coro_wrapper = tstate->coroutine_wrapper;
+        int is_coro = co->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE);
+
+        if (is_coro && tstate->in_coroutine_wrapper) {
+            assert(coro_wrapper != NULL);
+            PyErr_Format(PyExc_RuntimeError,
+                         "coroutine wrapper %.200R attempted "
+                         "to recursively wrap %.200R",
+                         coro_wrapper,
+                         co);
+            goto fail;
+        }
 
         /* Don't need to keep the reference to f_back, it will be set
          * when the generator is resumed. */
@@ -3936,8 +3946,13 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
         if (gen == NULL)
             return NULL;
 
-        if (co->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))
-            return apply_coroutine_wrapper(gen);
+        if (is_coro && coro_wrapper != NULL) {
+            PyObject *wrapped;
+            tstate->in_coroutine_wrapper = 1;
+            wrapped = PyObject_CallFunction(coro_wrapper, "N", gen);
+            tstate->in_coroutine_wrapper = 0;
+            return wrapped;
+        }
 
         return gen;
     }
@@ -5232,33 +5247,6 @@ unicode_concatenate(PyObject *v, PyObject *w,
     return res;
 }
 
-static PyObject *
-apply_coroutine_wrapper(PyObject *gen)
-{
-    PyObject *wrapped;
-    PyThreadState *tstate = PyThreadState_GET();
-    PyObject *wrapper = tstate->coroutine_wrapper;
-
-    if (tstate->in_coroutine_wrapper) {
-        assert(wrapper != NULL);
-        PyErr_Format(PyExc_RuntimeError,
-                     "coroutine wrapper %.200R attempted "
-                     "to recursively wrap %.200R",
-                     wrapper,
-                     gen);
-        return NULL;
-    }
-
-    if (wrapper == NULL) {
-        return gen;
-    }
-
-    tstate->in_coroutine_wrapper = 1;
-    wrapped = PyObject_CallFunction(wrapper, "N", gen);
-    tstate->in_coroutine_wrapper = 0;
-    return wrapped;
-}
-
 #ifdef DYNAMIC_EXECUTION_PROFILE
 
 static PyObject *