diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py index 31ab94b7471..940db5c143c 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -218,6 +218,25 @@ class FilterTests(BaseTest): 42) self.assertEqual(len(w), 0) + def test_module_globals(self): + with original_warnings.catch_warnings(record=True, + module=self.module) as w: + # bpo-33509: module_globals=None must not crash + self.module.warn_explicit('msg', UserWarning, "filename", 42, + module_globals=None) + self.assertEqual(len(w), 1) + + # Invalid module_globals type + with self.assertRaises(TypeError): + self.module.warn_explicit('msg', UserWarning, "filename", 42, + module_globals=True) + self.assertEqual(len(w), 1) + + # Empty module_globals + self.module.warn_explicit('msg', UserWarning, "filename", 42, + module_globals={}) + self.assertEqual(len(w), 2) + def test_inheritance(self): with original_warnings.catch_warnings(module=self.module) as w: self.module.resetwarnings() diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-14-17-31-02.bpo-33509.pIUfTd.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-14-17-31-02.bpo-33509.pIUfTd.rst new file mode 100644 index 00000000000..3d80a8c7f3e --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-14-17-31-02.bpo-33509.pIUfTd.rst @@ -0,0 +1,2 @@ +Fix module_globals parameter of warnings.warn_explicit(): don't crash if +module_globals is not a dict. diff --git a/Python/_warnings.c b/Python/_warnings.c index 0568af4df5a..29e475d67d1 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -951,7 +951,14 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) ®istry, &module_globals, &sourceobj)) return NULL; - if (module_globals) { + if (module_globals && module_globals != Py_None) { + if (!PyDict_Check(module_globals)) { + PyErr_Format(PyExc_TypeError, + "module_globals must be a dict, not '%.200s'", + Py_TYPE(module_globals)->tp_name); + return NULL; + } + source_line = get_source_line(module_globals, lineno); if (source_line == NULL && PyErr_Occurred()) { return NULL;