Commit dcf61715 authored by Victor Stinner's avatar Victor Stinner Committed by GitHub

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].
parent f5f336a8
...@@ -44,7 +44,9 @@ PyAPI_FUNC(_PyInitError) _PyPathConfig_SetGlobal( ...@@ -44,7 +44,9 @@ PyAPI_FUNC(_PyInitError) _PyPathConfig_SetGlobal(
PyAPI_FUNC(_PyInitError) _PyPathConfig_Calculate_impl( PyAPI_FUNC(_PyInitError) _PyPathConfig_Calculate_impl(
_PyPathConfig *config, _PyPathConfig *config,
const _PyCoreConfig *core_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( PyAPI_FUNC(int) _Py_FindEnvConfigValue(
FILE *env_file, FILE *env_file,
const wchar_t *key, const wchar_t *key,
......
At Python initialization, the current directory is no longer prepended to
:data:`sys.path` if it has been removed.
...@@ -780,7 +780,8 @@ pymain_run_python(PyInterpreterState *interp, int *exitcode) ...@@ -780,7 +780,8 @@ pymain_run_python(PyInterpreterState *interp, int *exitcode)
} }
} }
else if (!config->preconfig.isolated) { else if (!config->preconfig.isolated) {
PyObject *path0 = _PyPathConfig_ComputeArgv0(&config->argv); PyObject *path0 = NULL;
if (_PyPathConfig_ComputeSysPath0(&config->argv, &path0)) {
if (path0 == NULL) { if (path0 == NULL) {
err = _Py_INIT_NO_MEMORY(); err = _Py_INIT_NO_MEMORY();
goto done; goto done;
...@@ -793,6 +794,7 @@ pymain_run_python(PyInterpreterState *interp, int *exitcode) ...@@ -793,6 +794,7 @@ pymain_run_python(PyInterpreterState *interp, int *exitcode)
} }
Py_DECREF(path0); Py_DECREF(path0);
} }
}
PyCompilerFlags cf = {.cf_flags = 0, .cf_feature_version = PY_MINOR_VERSION}; PyCompilerFlags cf = {.cf_flags = 0, .cf_feature_version = PY_MINOR_VERSION};
......
...@@ -566,9 +566,18 @@ Py_GetProgramName(void) ...@@ -566,9 +566,18 @@ Py_GetProgramName(void)
return _Py_path_config.program_name; return _Py_path_config.program_name;
} }
/* Compute argv[0] which will be prepended to sys.argv */ /* Compute module search path from argv[0] or the current working
PyObject* directory ("-m module" case) which will be prepended to sys.argv:
_PyPathConfig_ComputeArgv0(const _PyWstrList *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)); assert(_PyWstrList_CheckConsistency(argv));
...@@ -588,6 +597,8 @@ _PyPathConfig_ComputeArgv0(const _PyWstrList *argv) ...@@ -588,6 +597,8 @@ _PyPathConfig_ComputeArgv0(const _PyWstrList *argv)
wchar_t fullpath[MAX_PATH]; wchar_t fullpath[MAX_PATH];
#endif #endif
assert(*path0_p == NULL);
if (argv->length > 0) { if (argv->length > 0) {
argv0 = argv->items[0]; argv0 = argv->items[0];
have_module_arg = (wcscmp(argv0, L"-m") == 0); have_module_arg = (wcscmp(argv0, L"-m") == 0);
...@@ -595,14 +606,17 @@ _PyPathConfig_ComputeArgv0(const _PyWstrList *argv) ...@@ -595,14 +606,17 @@ _PyPathConfig_ComputeArgv0(const _PyWstrList *argv)
} }
if (have_module_arg) { if (have_module_arg) {
#if defined(HAVE_REALPATH) || defined(MS_WINDOWS) #if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath)); if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
*path0_p = NULL;
return 0;
}
argv0 = fullpath; argv0 = fullpath;
n = wcslen(argv0); n = wcslen(argv0);
#else #else
argv0 = L"."; argv0 = L".";
n = 1; n = 1;
#endif #endif
} }
#ifdef HAVE_READLINK #ifdef HAVE_READLINK
...@@ -675,7 +689,8 @@ _PyPathConfig_ComputeArgv0(const _PyWstrList *argv) ...@@ -675,7 +689,8 @@ _PyPathConfig_ComputeArgv0(const _PyWstrList *argv)
} }
#endif /* All others */ #endif /* All others */
return PyUnicode_FromWideChar(argv0, n); *path0_p = PyUnicode_FromWideChar(argv0, n);
return 1;
} }
......
...@@ -2781,19 +2781,21 @@ PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) ...@@ -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 not '-c' nor '-m', prepend argv[0] to sys.path.
If argv[0] is a symlink, use the real path. */ If argv[0] is a symlink, use the real path. */
const _PyWstrList argv_list = {.length = argc, .items = argv}; const _PyWstrList argv_list = {.length = argc, .items = argv};
PyObject *argv0 = _PyPathConfig_ComputeArgv0(&argv_list); PyObject *path0 = NULL;
if (argv0 == NULL) { if (_PyPathConfig_ComputeSysPath0(&argv_list, &path0)) {
if (path0 == NULL) {
Py_FatalError("can't compute path0 from argv"); Py_FatalError("can't compute path0 from argv");
} }
PyObject *sys_path = _PySys_GetObjectId(&PyId_path); PyObject *sys_path = _PySys_GetObjectId(&PyId_path);
if (sys_path != NULL) { if (sys_path != NULL) {
if (PyList_Insert(sys_path, 0, argv0) < 0) { if (PyList_Insert(sys_path, 0, path0) < 0) {
Py_DECREF(argv0); Py_DECREF(path0);
Py_FatalError("can't prepend path0 to sys.path"); Py_FatalError("can't prepend path0 to sys.path");
} }
} }
Py_DECREF(argv0); Py_DECREF(path0);
}
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment