From 256e3c31f5e25f2a4fa271b1da8fab8a87bae4db Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Tue, 17 Dec 2024 14:22:54 -0800 Subject: [PATCH 1/3] gh-128030: Avoid error from PyModule_GetFilenameObject for non-module I missed the extra `PyModule_Check` in #127660 because I was looking at 3.12 as the base implementation for import from. This meant that I missed the `PyModuleCheck` introduced in #112661. --- Lib/test/test_import/__init__.py | 23 +++++++++++++++++++++++ Python/ceval.c | 14 ++++++++------ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index 83efbc1e25e77a..c2cec6444cb43a 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -851,6 +851,29 @@ def test_frozen_module_from_import_error(self): stdout, stderr = popen.communicate() self.assertIn(expected_error, stdout) + def test_non_module_from_import_error(self): + prefix = """ +import sys +class NotAModule: ... +nm = NotAModule() +nm.symbol = 123 +sys.modules["not_a_module"] = nm +from not_a_module import symbol +""" + scripts = [ + prefix + "from not_a_module import missing_symbol", + prefix + "nm.__spec__ = []\nfrom not_a_module import missing_symbol", + ] + for script in scripts: + with self.subTest(script=script): + expected_error = ( + b"ImportError: cannot import name 'missing_symbol' from " + b"'' (unknown location)" + ) + popen = script_helper.spawn_python("-c", script) + stdout, stderr = popen.communicate() + self.assertIn(expected_error, stdout) + def test_script_shadowing_stdlib(self): script_errors = [ ( diff --git a/Python/ceval.c b/Python/ceval.c index fd891d7839151e..cfaa832bb18f5f 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2863,13 +2863,15 @@ _PyEval_ImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name) if (origin == NULL) { // Fall back to __file__ for diagnostics if we don't have // an origin that is a location - origin = PyModule_GetFilenameObject(v); - if (origin == NULL) { - if (!PyErr_ExceptionMatches(PyExc_SystemError)) { - goto done; + if (PyModule_Check(v)) { + origin = PyModule_GetFilenameObject(v); + if (origin == NULL) { + if (!PyErr_ExceptionMatches(PyExc_SystemError)) { + goto done; + } + // PyModule_GetFilenameObject raised "module filename missing" + _PyErr_Clear(tstate); } - // PyModule_GetFilenameObject raised "module filename missing" - _PyErr_Clear(tstate); } assert(origin == NULL || PyUnicode_Check(origin)); } From 389e3bc3d47bdb00c7b7db30fa616427045658d9 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 22:28:22 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2024-12-17-22-28-15.gh-issue-128030.H1ptOD.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2024-12-17-22-28-15.gh-issue-128030.H1ptOD.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-17-22-28-15.gh-issue-128030.H1ptOD.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-12-17-22-28-15.gh-issue-128030.H1ptOD.rst new file mode 100644 index 00000000000000..93d78632355b76 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-12-17-22-28-15.gh-issue-128030.H1ptOD.rst @@ -0,0 +1 @@ +Avoid error from calling ``PyModule_GetFilenameObject`` on a non-module object when importing a non-existent symbol from a non-module object. From f7dfafcbe34e7e99112485fa8a0886b8478ce7f1 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Tue, 17 Dec 2024 18:23:14 -0800 Subject: [PATCH 3/3] . --- Python/ceval.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index cfaa832bb18f5f..bfdf5687c287db 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2860,18 +2860,16 @@ _PyEval_ImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name) } } - if (origin == NULL) { + if (origin == NULL && PyModule_Check(v)) { // Fall back to __file__ for diagnostics if we don't have // an origin that is a location - if (PyModule_Check(v)) { - origin = PyModule_GetFilenameObject(v); - if (origin == NULL) { - if (!PyErr_ExceptionMatches(PyExc_SystemError)) { - goto done; - } - // PyModule_GetFilenameObject raised "module filename missing" - _PyErr_Clear(tstate); + origin = PyModule_GetFilenameObject(v); + if (origin == NULL) { + if (!PyErr_ExceptionMatches(PyExc_SystemError)) { + goto done; } + // PyModule_GetFilenameObject raised "module filename missing" + _PyErr_Clear(tstate); } assert(origin == NULL || PyUnicode_Check(origin)); }