[Python-checkins] cpython (merge 3.4 -> default): merge 3.4 (#24096)

benjamin.peterson python-checkins at python.org
Sun May 3 17:30:07 CEST 2015


https://hg.python.org/cpython/rev/bfea101f9402
changeset:   95872:bfea101f9402
parent:      95869:1eaaf27b3956
parent:      95871:47f4c3a5d86a
user:        Benjamin Peterson <benjamin at python.org>
date:        Sun May 03 11:29:58 2015 -0400
summary:
  merge 3.4 (#24096)

files:
  Lib/test/test_warnings.py |  12 ++++++++
  Misc/NEWS                 |   3 ++
  Python/_warnings.c        |  37 +++++++++++++++++++-------
  3 files changed, 42 insertions(+), 10 deletions(-)


diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py
--- a/Lib/test/test_warnings.py
+++ b/Lib/test/test_warnings.py
@@ -247,6 +247,18 @@
             self.assertEqual(str(w[-1].message), text)
             self.assertTrue(w[-1].category is UserWarning)
 
+    def test_mutate_filter_list(self):
+        class X:
+            def match(self, a):
+                L[:] = []
+
+        L = [("default",X(),UserWarning,X(),0) for i in range(2)]
+        with original_warnings.catch_warnings(record=True,
+                module=self.module) as w:
+            self.module.filters = L
+            self.module.warn_explicit(UserWarning("b"), None, "f.py", 42)
+            self.assertEqual(str(w[-1].message), "b")
+
 class CFilterTests(FilterTests, unittest.TestCase):
     module = c_warnings
 
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
 Core and Builtins
 -----------------
 
+- Issue #24096: Make warnings.warn_explicit more robust against mutation of the
+  warnings.filters list.
+
 - Issue #23996: Avoid a crash when a delegated generator raises an
   unnormalized StopIteration exception.  Patch by Stefan Behnel.
 
diff --git a/Python/_warnings.c b/Python/_warnings.c
--- a/Python/_warnings.c
+++ b/Python/_warnings.c
@@ -101,7 +101,7 @@
 }
 
 
-/* The item is a borrowed reference. */
+/* The item is a new reference. */
 static PyObject*
 get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno,
            PyObject *module, PyObject **item)
@@ -132,14 +132,15 @@
         Py_ssize_t ln;
         int is_subclass, good_msg, good_mod;
 
-        tmp_item = *item = PyList_GET_ITEM(_filters, i);
-        if (PyTuple_Size(tmp_item) != 5) {
+        tmp_item = PyList_GET_ITEM(_filters, i);
+        if (!PyTuple_Check(tmp_item) || PyTuple_GET_SIZE(tmp_item) != 5) {
             PyErr_Format(PyExc_ValueError,
                          MODULE_NAME ".filters item %zd isn't a 5-tuple", i);
             return NULL;
         }
 
         /* Python code: action, msg, cat, mod, ln = item */
+        Py_INCREF(tmp_item);
         action = PyTuple_GET_ITEM(tmp_item, 0);
         msg = PyTuple_GET_ITEM(tmp_item, 1);
         cat = PyTuple_GET_ITEM(tmp_item, 2);
@@ -147,28 +148,43 @@
         ln_obj = PyTuple_GET_ITEM(tmp_item, 4);
 
         good_msg = check_matched(msg, text);
-        if (good_msg == -1)
+        if (good_msg == -1) {
+            Py_DECREF(tmp_item);
             return NULL;
+        }
 
         good_mod = check_matched(mod, module);
-        if (good_mod == -1)
+        if (good_mod == -1) {
+            Py_DECREF(tmp_item);
             return NULL;
+        }
 
         is_subclass = PyObject_IsSubclass(category, cat);
-        if (is_subclass == -1)
+        if (is_subclass == -1) {
+            Py_DECREF(tmp_item);
             return NULL;
+        }
 
         ln = PyLong_AsSsize_t(ln_obj);
-        if (ln == -1 && PyErr_Occurred())
+        if (ln == -1 && PyErr_Occurred()) {
+            Py_DECREF(tmp_item);
             return NULL;
+        }
 
-        if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln))
+        if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) {
+            *item = tmp_item;
             return action;
+        }
+
+        Py_DECREF(tmp_item);
     }
 
     action = get_default_action();
-    if (action != NULL)
+    if (action != NULL) {
+        Py_INCREF(Py_None);
+        *item = Py_None;
         return action;
+    }
 
     PyErr_SetString(PyExc_ValueError,
                     MODULE_NAME ".defaultaction not found");
@@ -349,7 +365,7 @@
               PyObject *module, PyObject *registry, PyObject *sourceline)
 {
     PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;
-    PyObject *item = Py_None;
+    PyObject *item = NULL;
     PyObject *action;
     int rc;
 
@@ -488,6 +504,7 @@
     Py_INCREF(result);
 
  cleanup:
+    Py_XDECREF(item);
     Py_XDECREF(key);
     Py_XDECREF(text);
     Py_XDECREF(lineno_obj);

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


More information about the Python-checkins mailing list