[Python-checkins] bpo-36236: Handle removed cwd at Python init (GH-12424)

Victor Stinner webhook-mailer at python.org
Tue Mar 19 11:09:37 EDT 2019


https://github.com/python/cpython/commit/dcf617152e1d4c4a5e7965733928858a9c0936ca
commit: dcf617152e1d4c4a5e7965733928858a9c0936ca
branch: master
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2019-03-19T16:09:27+01:00
summary:

bpo-36236: Handle removed cwd at Python init (GH-12424)

At Python initialization, the current directory is no longer
prepended to sys.path if it has been removed.

Rename _PyPathConfig_ComputeArgv0() to
_PyPathConfig_ComputeSysPath0() to avoid confusion between argv[0]
and sys.path[0].

files:
A Misc/NEWS.d/next/Core and Builtins/2019-03-19-03-08-26.bpo-36236.5qN9qK.rst
M Include/internal/pycore_pathconfig.h
M Modules/main.c
M Python/pathconfig.c
M Python/sysmodule.c

diff --git a/Include/internal/pycore_pathconfig.h b/Include/internal/pycore_pathconfig.h
index d0938df54145..80d86a0dd1b5 100644
--- a/Include/internal/pycore_pathconfig.h
+++ b/Include/internal/pycore_pathconfig.h
@@ -44,7 +44,9 @@ PyAPI_FUNC(_PyInitError) _PyPathConfig_SetGlobal(
 PyAPI_FUNC(_PyInitError) _PyPathConfig_Calculate_impl(
     _PyPathConfig *config,
     const _PyCoreConfig *core_config);
-PyAPI_FUNC(PyObject*) _PyPathConfig_ComputeArgv0(const _PyWstrList *argv);
+PyAPI_FUNC(int) _PyPathConfig_ComputeSysPath0(
+    const _PyWstrList *argv,
+    PyObject **path0);
 PyAPI_FUNC(int) _Py_FindEnvConfigValue(
     FILE *env_file,
     const wchar_t *key,
diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-03-19-03-08-26.bpo-36236.5qN9qK.rst b/Misc/NEWS.d/next/Core and Builtins/2019-03-19-03-08-26.bpo-36236.5qN9qK.rst
new file mode 100644
index 000000000000..e1c1182d181a
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2019-03-19-03-08-26.bpo-36236.5qN9qK.rst	
@@ -0,0 +1,2 @@
+At Python initialization, the current directory is no longer prepended to
+:data:`sys.path` if it has been removed.
diff --git a/Modules/main.c b/Modules/main.c
index 99396b73c650..df4eca5aae84 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -780,18 +780,20 @@ pymain_run_python(PyInterpreterState *interp, int *exitcode)
         }
     }
     else if (!config->preconfig.isolated) {
-        PyObject *path0 = _PyPathConfig_ComputeArgv0(&config->argv);
-        if (path0 == NULL) {
-            err = _Py_INIT_NO_MEMORY();
-            goto done;
-        }
+        PyObject *path0 = NULL;
+        if (_PyPathConfig_ComputeSysPath0(&config->argv, &path0)) {
+            if (path0 == NULL) {
+                err = _Py_INIT_NO_MEMORY();
+                goto done;
+            }
 
-        if (pymain_sys_path_add_path0(interp, path0) < 0) {
+            if (pymain_sys_path_add_path0(interp, path0) < 0) {
+                Py_DECREF(path0);
+                err = _Py_INIT_EXIT(1);
+                goto done;
+            }
             Py_DECREF(path0);
-            err = _Py_INIT_EXIT(1);
-            goto done;
         }
-        Py_DECREF(path0);
     }
 
     PyCompilerFlags cf = {.cf_flags = 0, .cf_feature_version = PY_MINOR_VERSION};
diff --git a/Python/pathconfig.c b/Python/pathconfig.c
index f1818eb30765..743e1cd1ac0b 100644
--- a/Python/pathconfig.c
+++ b/Python/pathconfig.c
@@ -566,9 +566,18 @@ Py_GetProgramName(void)
     return _Py_path_config.program_name;
 }
 
-/* Compute argv[0] which will be prepended to sys.argv */
-PyObject*
-_PyPathConfig_ComputeArgv0(const _PyWstrList *argv)
+/* Compute module search path from argv[0] or the current working
+   directory ("-m module" case) which will be prepended to sys.argv:
+   sys.path[0].
+
+   Return 1 if the path is correctly resolved, but *path0_p can be NULL
+   if the Unicode object fail to be created.
+
+   Return 0 if it fails to resolve the full path (and *path0_p will be NULL),
+   for example if the current working directory has been removed (bpo-36236).
+   */
+int
+_PyPathConfig_ComputeSysPath0(const _PyWstrList *argv, PyObject **path0_p)
 {
     assert(_PyWstrList_CheckConsistency(argv));
 
@@ -588,6 +597,8 @@ _PyPathConfig_ComputeArgv0(const _PyWstrList *argv)
     wchar_t fullpath[MAX_PATH];
 #endif
 
+    assert(*path0_p == NULL);
+
     if (argv->length > 0) {
         argv0 = argv->items[0];
         have_module_arg = (wcscmp(argv0, L"-m") == 0);
@@ -595,14 +606,17 @@ _PyPathConfig_ComputeArgv0(const _PyWstrList *argv)
     }
 
     if (have_module_arg) {
-        #if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
-            _Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath));
+#if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
+            if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
+                *path0_p = NULL;
+                return 0;
+            }
             argv0 = fullpath;
             n = wcslen(argv0);
-        #else
+#else
             argv0 = L".";
             n = 1;
-        #endif
+#endif
     }
 
 #ifdef HAVE_READLINK
@@ -675,7 +689,8 @@ _PyPathConfig_ComputeArgv0(const _PyWstrList *argv)
     }
 #endif /* All others */
 
-    return PyUnicode_FromWideChar(argv0, n);
+    *path0_p = PyUnicode_FromWideChar(argv0, n);
+    return 1;
 }
 
 
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index b3330a01f7c1..4351a7fb370d 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -2781,19 +2781,21 @@ PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)
         /* If argv[0] is not '-c' nor '-m', prepend argv[0] to sys.path.
            If argv[0] is a symlink, use the real path. */
         const _PyWstrList argv_list = {.length = argc, .items = argv};
-        PyObject *argv0 = _PyPathConfig_ComputeArgv0(&argv_list);
-        if (argv0 == NULL) {
-            Py_FatalError("can't compute path0 from argv");
-        }
+        PyObject *path0 = NULL;
+        if (_PyPathConfig_ComputeSysPath0(&argv_list, &path0)) {
+            if (path0 == NULL) {
+                Py_FatalError("can't compute path0 from argv");
+            }
 
-        PyObject *sys_path = _PySys_GetObjectId(&PyId_path);
-        if (sys_path != NULL) {
-            if (PyList_Insert(sys_path, 0, argv0) < 0) {
-                Py_DECREF(argv0);
-                Py_FatalError("can't prepend path0 to sys.path");
+            PyObject *sys_path = _PySys_GetObjectId(&PyId_path);
+            if (sys_path != NULL) {
+                if (PyList_Insert(sys_path, 0, path0) < 0) {
+                    Py_DECREF(path0);
+                    Py_FatalError("can't prepend path0 to sys.path");
+                }
             }
+            Py_DECREF(path0);
         }
-        Py_DECREF(argv0);
     }
 }
 



More information about the Python-checkins mailing list