Skip to content

Commit 8c59816

Browse files
committed
merge 3.3 (#24096)
2 parents b9c04db + deff2b7 commit 8c59816

File tree

3 files changed

+42
-10
lines changed

3 files changed

+42
-10
lines changed

Lib/test/test_warnings.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,18 @@ def test_filterwarnings(self):
247247
self.assertEqual(str(w[-1].message), text)
248248
self.assertTrue(w[-1].category is UserWarning)
249249

250+
def test_mutate_filter_list(self):
251+
class X:
252+
def match(self, a):
253+
L[:] = []
254+
255+
L = [("default",X(),UserWarning,X(),0) for i in range(2)]
256+
with original_warnings.catch_warnings(record=True,
257+
module=self.module) as w:
258+
self.module.filters = L
259+
self.module.warn_explicit(UserWarning("b"), None, "f.py", 42)
260+
self.assertEqual(str(w[-1].message), "b")
261+
250262
class CFilterTests(FilterTests, unittest.TestCase):
251263
module = c_warnings
252264

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ Release date: tba
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #24096: Make warnings.warn_explicit more robust against mutation of the
14+
warnings.filters list.
15+
1316
- Issue #23996: Avoid a crash when a delegated generator raises an
1417
unnormalized StopIteration exception. Patch by Stefan Behnel.
1518

Python/_warnings.c

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ get_default_action(void)
101101
}
102102

103103

104-
/* The item is a borrowed reference. */
104+
/* The item is a new reference. */
105105
static PyObject*
106106
get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno,
107107
PyObject *module, PyObject **item)
@@ -132,43 +132,59 @@ get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno,
132132
Py_ssize_t ln;
133133
int is_subclass, good_msg, good_mod;
134134

135-
tmp_item = *item = PyList_GET_ITEM(_filters, i);
136-
if (PyTuple_Size(tmp_item) != 5) {
135+
tmp_item = PyList_GET_ITEM(_filters, i);
136+
if (!PyTuple_Check(tmp_item) || PyTuple_GET_SIZE(tmp_item) != 5) {
137137
PyErr_Format(PyExc_ValueError,
138138
MODULE_NAME ".filters item %zd isn't a 5-tuple", i);
139139
return NULL;
140140
}
141141

142142
/* Python code: action, msg, cat, mod, ln = item */
143+
Py_INCREF(tmp_item);
143144
action = PyTuple_GET_ITEM(tmp_item, 0);
144145
msg = PyTuple_GET_ITEM(tmp_item, 1);
145146
cat = PyTuple_GET_ITEM(tmp_item, 2);
146147
mod = PyTuple_GET_ITEM(tmp_item, 3);
147148
ln_obj = PyTuple_GET_ITEM(tmp_item, 4);
148149

149150
good_msg = check_matched(msg, text);
150-
if (good_msg == -1)
151+
if (good_msg == -1) {
152+
Py_DECREF(tmp_item);
151153
return NULL;
154+
}
152155

153156
good_mod = check_matched(mod, module);
154-
if (good_mod == -1)
157+
if (good_mod == -1) {
158+
Py_DECREF(tmp_item);
155159
return NULL;
160+
}
156161

157162
is_subclass = PyObject_IsSubclass(category, cat);
158-
if (is_subclass == -1)
163+
if (is_subclass == -1) {
164+
Py_DECREF(tmp_item);
159165
return NULL;
166+
}
160167

161168
ln = PyLong_AsSsize_t(ln_obj);
162-
if (ln == -1 && PyErr_Occurred())
169+
if (ln == -1 && PyErr_Occurred()) {
170+
Py_DECREF(tmp_item);
163171
return NULL;
172+
}
164173

165-
if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln))
174+
if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) {
175+
*item = tmp_item;
166176
return action;
177+
}
178+
179+
Py_DECREF(tmp_item);
167180
}
168181

169182
action = get_default_action();
170-
if (action != NULL)
183+
if (action != NULL) {
184+
Py_INCREF(Py_None);
185+
*item = Py_None;
171186
return action;
187+
}
172188

173189
PyErr_SetString(PyExc_ValueError,
174190
MODULE_NAME ".defaultaction not found");
@@ -349,7 +365,7 @@ warn_explicit(PyObject *category, PyObject *message,
349365
PyObject *module, PyObject *registry, PyObject *sourceline)
350366
{
351367
PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;
352-
PyObject *item = Py_None;
368+
PyObject *item = NULL;
353369
PyObject *action;
354370
int rc;
355371

@@ -488,6 +504,7 @@ warn_explicit(PyObject *category, PyObject *message,
488504
Py_INCREF(result);
489505

490506
cleanup:
507+
Py_XDECREF(item);
491508
Py_XDECREF(key);
492509
Py_XDECREF(text);
493510
Py_XDECREF(lineno_obj);

0 commit comments

Comments
 (0)