From fa3933a3a0db03fdc7ae733519f655bd1d856cfa Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Thu, 6 Mar 2025 14:50:44 -0800 Subject: [PATCH 1/3] gh-130932: Fix incorrect exception handling in _PyModule_IsPossiblyShadowing I chose to not raise an exception here because I think it would be confusing for module attribute access to start raising something other than AttributeError if e.g. the cwd goes away Without the change in moduleobject.c ``` ./python.exe -m unittest test.test_import.ImportTests.test_script_shadowing_stdlib_cwd_failure ... Assertion failed: (PyErr_Occurred()), function _PyObject_SetAttributeErrorContext, file object.c, line 1253. ``` --- Lib/test/test_import/__init__.py | 21 +++++++++++++++++++++ Objects/moduleobject.c | 4 +++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index f58633e0ce8dda..6dc12762f3096c 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -1185,6 +1185,27 @@ class substr(str): for line in lines: self.assertRegex(line, rb"cannot import name 'Fraction' from 'fractions' \(.*\)") + def test_script_shadowing_stdlib_cwd_failure(self): + with os_helper.temp_dir() as tmp: + subtmp = os.path.join(tmp, "subtmp") + os.mkdir(subtmp) + with open(os.path.join(subtmp, "main.py"), "w", encoding='utf-8') as f: + f.write(f""" +import sys +assert sys.path[0] == '' + +import os +import shutil +shutil.rmtree(os.getcwd()) + +os.does_not_exist +""") + # Use -c to ensure sys.path[0] is "" + popen = script_helper.spawn_python("-c", "import main", cwd=subtmp) + stdout, stderr = popen.communicate() + expected_error = rb"AttributeError: module 'os' has no attribute 'does_not_exist'" + self.assertRegex(stdout, expected_error) + def test_script_shadowing_stdlib_sys_path_modification(self): script_errors = [ ( diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index 20a2b8ee3221f8..1af3ce6fe9bf65 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -921,7 +921,9 @@ _PyModule_IsPossiblyShadowing(PyObject *origin) if (sys_path_0[0] == L'\0') { // if sys.path[0] == "", treat it as if it were the current directory if (!_Py_wgetcwd(sys_path_0_buf, MAXPATHLEN)) { - return -1; + // If we failed to getcwd, don't raise an exception and instead + // let the caller proceed assuming no shadowing + return 0; } sys_path_0 = sys_path_0_buf; } From 818bb99b97da468ca2873a5ab46c4ed49da23602 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Thu, 6 Mar 2025 22:56:09 +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 --- .../2025-03-06-22-56-02.gh-issue-130932.QVHaKT.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-03-06-22-56-02.gh-issue-130932.QVHaKT.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-03-06-22-56-02.gh-issue-130932.QVHaKT.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-03-06-22-56-02.gh-issue-130932.QVHaKT.rst new file mode 100644 index 00000000000000..e12b5b88cb59ab --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-03-06-22-56-02.gh-issue-130932.QVHaKT.rst @@ -0,0 +1 @@ +Fix incorrect exception handling in ``_PyModule_IsPossiblyShadowing`` From 9260690fcf133fb52e0fe85d39f0dbee5b977cd7 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Thu, 6 Mar 2025 15:33:02 -0800 Subject: [PATCH 3/3] Skip test on Windows --- Lib/test/test_import/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index 6dc12762f3096c..bf2bf066ceeb9e 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -1185,6 +1185,7 @@ class substr(str): for line in lines: self.assertRegex(line, rb"cannot import name 'Fraction' from 'fractions' \(.*\)") + @unittest.skipIf(sys.platform == 'win32', 'Cannot delete cwd on Windows') def test_script_shadowing_stdlib_cwd_failure(self): with os_helper.temp_dir() as tmp: subtmp = os.path.join(tmp, "subtmp")