cpython: 47f4c3a5d86a (original) (raw)
--- 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:[](#l1.8)
def match(self, a):[](#l1.9)
L[:] = [][](#l1.10)
L = [("default",X(),UserWarning,X(),0) for i in range(2)][](#l1.12)
with original_warnings.catch_warnings(record=True,[](#l1.13)
module=self.module) as w:[](#l1.14)
self.module.filters = L[](#l1.15)
self.module.warn_explicit(UserWarning("b"), None, "f.py", 42)[](#l1.16)
self.assertEqual(str(w[-1].message), "b")[](#l1.17)
+ class CFilterTests(FilterTests, unittest.TestCase): module = c_warnings
--- 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
- Issue #23996: Avoid a crash when a delegated generator raises an unnormalized StopIteration exception. Patch by Stefan Behnel.
--- 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 Py_ssize_t ln; int is_subclass, good_msg, good_mod;
tmp_item = *item = PyList_GET_ITEM(_filters, i);[](#l3.16)
if (PyTuple_Size(tmp_item) != 5) {[](#l3.17)
tmp_item = PyList_GET_ITEM(_filters, i);[](#l3.18)
if (!PyTuple_Check(tmp_item) || PyTuple_GET_SIZE(tmp_item) != 5) {[](#l3.19) PyErr_Format(PyExc_ValueError,[](#l3.20) MODULE_NAME ".filters item %zd isn't a 5-tuple", i);[](#l3.21) return NULL;[](#l3.22) }[](#l3.23)
/* Python code: action, msg, cat, mod, ln = item */
Py_INCREF(tmp_item);[](#l3.26) action = PyTuple_GET_ITEM(tmp_item, 0);[](#l3.27) msg = PyTuple_GET_ITEM(tmp_item, 1);[](#l3.28) cat = PyTuple_GET_ITEM(tmp_item, 2);[](#l3.29)
@@ -147,28 +148,43 @@ get_filter(PyObject *category, PyObject ln_obj = PyTuple_GET_ITEM(tmp_item, 4); good_msg = check_matched(msg, text);
if (good_msg == -1)[](#l3.34)
if (good_msg == -1) {[](#l3.35)
Py_DECREF(tmp_item);[](#l3.36) return NULL;[](#l3.37)
}[](#l3.38)
good_mod = check_matched(mod, module);
if (good_mod == -1)[](#l3.41)
if (good_mod == -1) {[](#l3.42)
Py_DECREF(tmp_item);[](#l3.43) return NULL;[](#l3.44)
}[](#l3.45)
is_subclass = PyObject_IsSubclass(category, cat);
if (is_subclass == -1)[](#l3.48)
if (is_subclass == -1) {[](#l3.49)
Py_DECREF(tmp_item);[](#l3.50) return NULL;[](#l3.51)
}[](#l3.52)
ln = PyLong_AsSsize_t(ln_obj);
if (ln == -1 && PyErr_Occurred())[](#l3.55)
if (ln == -1 && PyErr_Occurred()) {[](#l3.56)
Py_DECREF(tmp_item);[](#l3.57) return NULL;[](#l3.58)
}[](#l3.59)
if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln))[](#l3.61)
if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) {[](#l3.62)
*item = tmp_item;[](#l3.63) return action;[](#l3.64)
}[](#l3.65)
- if (action != NULL) {
Py_INCREF(Py_None);[](#l3.73)
*item = Py_None;[](#l3.74) return action;[](#l3.75)
- }
PyErr_SetString(PyExc_ValueError, MODULE_NAME ".defaultaction not found"); @@ -349,7 +365,7 @@ warn_explicit(PyObject *category, PyObje PyObject *module, PyObject *registry, PyObject *sourceline) { PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;