From 9d984fd2b097c8c29479d1c3eb740995fe1ccb0d Mon Sep 17 00:00:00 2001 From: Oren Milman Date: Tue, 12 Sep 2017 00:18:09 +0300 Subject: [PATCH] bpo-31416: Fix assertion failures in case of a bad warnings.filters or warnings.defaultaction. (#3496) Patch by Oren Milman. --- Lib/test/test_warnings/__init__.py | 15 +++++++++++++++ .../2017-09-11-12-54-35.bpo-31416.2hlQFd.rst | 2 ++ Python/_warnings.c | 19 ++++++++++++++++--- 3 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2017-09-11-12-54-35.bpo-31416.2hlQFd.rst diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py index 75539cf1c87..2d0c46f409a 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -805,6 +805,21 @@ class _WarningsTests(BaseTest, unittest.TestCase): with self.assertRaises(TypeError): wmod.warn_explicit('foo', Warning, 'bar', 1, registry=None) + @support.cpython_only + def test_issue31416(self): + # warn_explicit() shouldn't cause an assertion failure in case of a + # bad warnings.filters or warnings.defaultaction. + wmod = self.module + with original_warnings.catch_warnings(module=wmod): + wmod.filters = [(None, None, Warning, None, 0)] + with self.assertRaises(TypeError): + wmod.warn_explicit('foo', Warning, 'bar', 1) + + wmod.filters = [] + with support.swap_attr(wmod, 'defaultaction', None), \ + self.assertRaises(TypeError): + wmod.warn_explicit('foo', Warning, 'bar', 1) + class WarningsDisplayTests(BaseTest): diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-09-11-12-54-35.bpo-31416.2hlQFd.rst b/Misc/NEWS.d/next/Core and Builtins/2017-09-11-12-54-35.bpo-31416.2hlQFd.rst new file mode 100644 index 00000000000..148a5c8eda5 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-09-11-12-54-35.bpo-31416.2hlQFd.rst @@ -0,0 +1,2 @@ +Fix assertion failures in case of a bad warnings.filters or +warnings.defaultaction. Patch by Oren Milman. diff --git a/Python/_warnings.c b/Python/_warnings.c index 078bdcb0399..6dad0806867 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -110,7 +110,14 @@ get_default_action(void) } return _PyRuntime.warnings.default_action; } - + if (!PyUnicode_Check(default_action)) { + PyErr_Format(PyExc_TypeError, + MODULE_NAME ".defaultaction must be a string, " + "not '%.200s'", + Py_TYPE(default_action)->tp_name); + Py_DECREF(default_action); + return NULL; + } Py_DECREF(_PyRuntime.warnings.default_action); _PyRuntime.warnings.default_action = default_action; return default_action; @@ -164,6 +171,14 @@ get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno, mod = PyTuple_GET_ITEM(tmp_item, 3); ln_obj = PyTuple_GET_ITEM(tmp_item, 4); + if (!PyUnicode_Check(action)) { + PyErr_Format(PyExc_TypeError, + "action must be a string, not '%.200s'", + Py_TYPE(action)->tp_name); + Py_DECREF(tmp_item); + return NULL; + } + good_msg = check_matched(msg, text); if (good_msg == -1) { Py_DECREF(tmp_item); @@ -203,8 +218,6 @@ get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno, return action; } - PyErr_SetString(PyExc_ValueError, - MODULE_NAME ".defaultaction not found"); return NULL; }