summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2015-05-03 15:28:46 (GMT)
committerBenjamin Peterson <benjamin@python.org>2015-05-03 15:28:46 (GMT)
commit8c59816b70a30d8ec2ff4e60a8b4a747f8ff75db (patch)
treec09195c80d4594c6261c072ca9dda43b2201f469
parentb9c04db64fd0315a30c4360d7ad33b975d5fbfc1 (diff)
parentdeff2b76ec3824ff238ad0812c29aca95534ecb4 (diff)
downloadcpython-8c59816b70a30d8ec2ff4e60a8b4a747f8ff75db.zip
cpython-8c59816b70a30d8ec2ff4e60a8b4a747f8ff75db.tar.gz
cpython-8c59816b70a30d8ec2ff4e60a8b4a747f8ff75db.tar.bz2
merge 3.3 (#24096)
-rw-r--r--Lib/test/test_warnings.py12
-rw-r--r--Misc/NEWS3
-rw-r--r--Python/_warnings.c37
3 files changed, 42 insertions, 10 deletions
diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py
index fb01b83..ddcea8e 100644
--- a/Lib/test/test_warnings.py
+++ b/Lib/test/test_warnings.py
@@ -247,6 +247,18 @@ class FilterTests(BaseTest):
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
index b787c84..b8d2ab1 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ Release date: tba
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
index bef5647..6dff0a2 100644
--- a/Python/_warnings.c
+++ b/Python/_warnings.c
@@ -101,7 +101,7 @@ get_default_action(void)
}
-/* 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 @@ get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno,
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 @@ get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno,
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 @@ warn_explicit(PyObject *category, PyObject *message,
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 @@ warn_explicit(PyObject *category, PyObject *message,
Py_INCREF(result);
cleanup:
+ Py_XDECREF(item);
Py_XDECREF(key);
Py_XDECREF(text);
Py_XDECREF(lineno_obj);