https://github.com/python/cpython/commit/53be7d47b7712e642e6992a2896682884632b15e
commit: 53be7d47b7712e642e6992a2896682884632b15e
branch: main
author: T. Wouters <[email protected]>
committer: encukou <[email protected]>
date: 2026-10-09T13:59:27+02:00
summary:

gh-158918: Reduce C stack usage of `_PyModule_IsPossiblyShadowing`. (GH-158919)

Reduce C stack usage of `_PyModule_IsPossiblyShadowing`, which could
potentially cause stack overflows during module attribute access while
deeply recursing in agressively optimized builds.

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2026-10-06-14-12-49.gh-issue-158918.TDVkZx.rst
M Objects/moduleobject.c

diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2026-10-06-14-12-49.gh-issue-158918.TDVkZx.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-06-14-12-49.gh-issue-158918.TDVkZx.rst
new file mode 100644
index 000000000000000..8355186be58858a
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-06-14-12-49.gh-issue-158918.TDVkZx.rst
@@ -0,0 +1,3 @@
+Reduce C stack usage of ``_PyModule_IsPossiblyShadowing``, which could
+potentially cause stack overflows during module attribute access while
+deeply recursing in agressively optimized builds.
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c
index 164f24e69c69bae..7a5d14c538391dc 100644
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -1238,6 +1238,10 @@ _PyModuleSpec_GetFileOrigin(PyObject *spec, PyObject 
**p_origin)
 int
 _PyModule_IsPossiblyShadowing(PyObject *origin)
 {
+    int result = 0;
+    wchar_t *root = NULL;
+    wchar_t *sys_path_0_buf = NULL;
+
     // origin must be a unicode subtype
     // Returns 1 if the module at origin could be shadowing a module of the
     // same name later in the module search path. The condition we check is 
basically:
@@ -1256,24 +1260,21 @@ _PyModule_IsPossiblyShadowing(PyObject *origin)
     }
 
     // root = os.path.dirname(origin.removesuffix(os.sep + "__init__.py"))
-    wchar_t root[MAXPATHLEN + 1];
-    Py_ssize_t size = PyUnicode_AsWideChar(origin, root, MAXPATHLEN);
-    if (size < 0) {
+    root = PyUnicode_AsWideCharString(origin, NULL);
+    if (root == NULL) {
         return -1;
     }
-    assert(size <= MAXPATHLEN);
-    root[size] = L'\0';
 
     wchar_t *sep = wcsrchr(root, SEP);
     if (sep == NULL) {
-        return 0;
+        goto done;
     }
     // If it's a package then we need to look one directory further up
     if (wcscmp(sep + 1, L"__init__.py") == 0) {
         *sep = L'\0';
         sep = wcsrchr(root, SEP);
         if (sep == NULL) {
-            return 0;
+            goto done;
         }
     }
     *sep = L'\0';
@@ -1281,21 +1282,30 @@ _PyModule_IsPossiblyShadowing(PyObject *origin)
     // sys.path[0] or os.getcwd()
     wchar_t *sys_path_0 = config->sys_path_0;
     if (!sys_path_0) {
-        return 0;
+        goto done;
     }
 
-    wchar_t sys_path_0_buf[MAXPATHLEN];
     if (sys_path_0[0] == L'\0') {
         // if sys.path[0] == "", treat it as if it were the current directory
+        sys_path_0_buf = PyMem_Malloc(MAXPATHLEN * sizeof(wchar_t));
+        if (sys_path_0_buf == NULL) {
+            PyErr_NoMemory();
+            result = -1;
+            goto done;
+        }
         if (!_Py_wgetcwd(sys_path_0_buf, MAXPATHLEN)) {
             // If we failed to getcwd, don't raise an exception and instead
             // let the caller proceed assuming no shadowing
-            return 0;
+            goto done;
         }
         sys_path_0 = sys_path_0_buf;
     }
 
-    int result = wcscmp(sys_path_0, root) == 0;
+    result = (wcscmp(sys_path_0, root) == 0);
+
+done:
+    PyMem_Free(root);
+    PyMem_Free(sys_path_0_buf);
     return result;
 }
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to