From c3741f95a89eca7c733ccce800b898810598be2c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 14 May 2018 17:25:43 -0400 Subject: [PATCH 1/2] bpo-33509: Fix _warnings for module_globals=None Don't crash on warnings.warn_explicit() if module_globals is None. --- Lib/test/test_warnings/__init__.py | 19 +++++++++++++++++++ .../2018-05-14-17-31-02.bpo-33509.pIUfTd.rst | 2 ++ Python/_warnings.c | 9 ++++++++- 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2018-05-14-17-31-02.bpo-33509.pIUfTd.rst diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py index 31ab94b74716d0..940db5c143c930 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -218,6 +218,25 @@ def test_once(self): 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 00000000000000..3d80a8c7f3eb93 --- /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 0568af4df5a80b..4fa20a2ce4fa59 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -883,6 +883,13 @@ get_source_line(PyObject *module_globals, int lineno) PyObject *source_list; PyObject *source_line; + 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; + } + /* Check/get the requisite pieces needed for the loader. */ loader = _PyDict_GetItemIdWithError(module_globals, &PyId___loader__); if (loader == NULL) { @@ -951,7 +958,7 @@ 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) { source_line = get_source_line(module_globals, lineno); if (source_line == NULL && PyErr_Occurred()) { return NULL; From 5091291a0ff170d0a0722c230782c90a35845f55 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 15 May 2018 11:07:34 -0400 Subject: [PATCH 2/2] Move PyDict_Check() and fix a typo --- Python/_warnings.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Python/_warnings.c b/Python/_warnings.c index 4fa20a2ce4fa59..29e475d67d1f61 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -883,13 +883,6 @@ get_source_line(PyObject *module_globals, int lineno) PyObject *source_list; PyObject *source_line; - 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; - } - /* Check/get the requisite pieces needed for the loader. */ loader = _PyDict_GetItemIdWithError(module_globals, &PyId___loader__); if (loader == NULL) { @@ -959,6 +952,13 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) return NULL; 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;