From ebac19dad6263141d5db0a2c923efe049dba99d2 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 1 Dec 2017 20:09:52 +0100 Subject: [PATCH] bpo-32030: Don't call _PyPathConfig_Fini() in Py_FinalizeEx() (#4667) Changes: * _PyPathConfig_Fini() cannot be called in Py_FinalizeEx(). Py_Initialize() and Py_Finalize() can be called multiple times, but it must not "forget" parameters set by Py_SetProgramName(), Py_SetPath() or Py_SetPythonHome(), whereas _PyPathConfig_Fini() clear all these parameters. * config_get_program_name() and calculate_program_full_path() now also decode paths using Py_DecodeLocale() to use the surrogateescape error handler, rather than decoding using mbstowcs() which is strict. * Change _Py_CheckPython3() prototype: () => (void) * Truncate a few lines which were too long --- Include/pylifecycle.h | 2 +- Modules/getpath.c | 10 ++++++---- Modules/main.c | 30 ++++++++++++++++++------------ PC/getpathp.c | 19 +++++++++++++------ Python/pylifecycle.c | 2 -- 5 files changed, 38 insertions(+), 25 deletions(-) diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index d32c98b6985..3db88326aee 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -109,7 +109,7 @@ PyAPI_FUNC(void) _PyPathConfig_Fini(void); #endif PyAPI_FUNC(void) Py_SetPath(const wchar_t *); #ifdef MS_WINDOWS -int _Py_CheckPython3(); +int _Py_CheckPython3(void); #endif /* In their own files */ diff --git a/Modules/getpath.c b/Modules/getpath.c index 183717d8171..235badab230 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -625,11 +625,13 @@ calculate_program_full_path(const _PyMainInterpreterConfig *main_config, else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) && execpath[0] == SEP) { - size_t r = mbstowcs(program_full_path, execpath, MAXPATHLEN+1); - if (r == (size_t)-1 || r > MAXPATHLEN) { - /* Could not convert execpath, or it's too long. */ - program_full_path[0] = '\0'; + size_t len; + wchar_t *path = Py_DecodeLocale(execpath, &len); + if (path == NULL) { + return DECODE_LOCALE_ERR("executable path", len); } + wcsncpy(program_full_path, path, MAXPATHLEN); + PyMem_RawFree(path); } #endif /* __APPLE__ */ else if (calculate->path_env) { diff --git a/Modules/main.c b/Modules/main.c index caec97f8642..4659c5d670b 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -888,15 +888,12 @@ config_get_program_name(_PyMainInterpreterConfig *config) See Lib/plat-mac/bundlebuiler.py for details about the bootstrap script. */ if ((p = Py_GETENV("PYTHONEXECUTABLE")) && *p != '\0') { - wchar_t* buffer; - size_t len = strlen(p) + 1; - - buffer = PyMem_RawMalloc(len * sizeof(wchar_t)); - if (buffer == NULL) { - return _Py_INIT_NO_MEMORY(); + size_t len; + wchar_t* program_name = Py_DecodeLocale(p, &len); + if (program_name == NULL) { + return SET_DECODE_ERROR("PYTHONEXECUTABLE environment " + "variable", len); } - - mbstowcs(buffer, p, len); pymain->config.program_name = buffer; } #ifdef WITH_NEXT_FRAMEWORK @@ -907,11 +904,12 @@ config_get_program_name(_PyMainInterpreterConfig *config) * the argv0 of the stub executable */ size_t len; - wchar_t* wbuf = Py_DecodeLocale(pyvenv_launcher, &len); - if (wbuf == NULL) { - return SET_DECODE_ERROR("__PYVENV_LAUNCHER__", len); + wchar_t* program_name = Py_DecodeLocale(pyvenv_launcher, &len); + if (program_name == NULL) { + return SET_DECODE_ERROR("__PYVENV_LAUNCHER__ environment " + "variable", len); } - pymain->config.program_name = wbuf; + pymain->config.program_name = program_name; } } #endif /* WITH_NEXT_FRAMEWORK */ @@ -1666,6 +1664,14 @@ pymain_impl(_PyMain *pymain) other special meaning */ pymain->status = 120; } + + /* _PyPathConfig_Fini() cannot be called in Py_FinalizeEx(). + Py_Initialize() and Py_Finalize() can be called multiple times, but it + must not "forget" parameters set by Py_SetProgramName(), Py_SetPath() or + Py_SetPythonHome(), whereas _PyPathConfig_Fini() clear all these + parameters. */ + _PyPathConfig_Fini(); + return 0; } diff --git a/PC/getpathp.c b/PC/getpathp.c index 89d37a84133..f8cfd7e6978 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -721,12 +721,16 @@ static int get_pth_filename(wchar_t *spbuffer, _PyPathConfig *config) { if (config->dll_path[0]) { - if (!change_ext(spbuffer, config->dll_path, L"._pth") && exists(spbuffer)) { + if (!change_ext(spbuffer, config->dll_path, L"._pth") && + exists(spbuffer)) + { return 1; } } if (config->program_full_path[0]) { - if (!change_ext(spbuffer, config->program_full_path, L"._pth") && exists(spbuffer)) { + if (!change_ext(spbuffer, config->program_full_path, L"._pth") && + exists(spbuffer)) + { return 1; } } @@ -823,8 +827,10 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, #endif /* We only use the default relative PYTHONPATH if we haven't anything better to use! */ - int skipdefault = (main_config->module_search_path_env!=NULL || calculate->home!=NULL || \ - calculate->machine_path!=NULL || calculate->user_path!=NULL); + int skipdefault = (main_config->module_search_path_env != NULL || + calculate->home != NULL || + calculate->machine_path != NULL || + calculate->user_path != NULL); /* We need to construct a path from the following parts. (1) the PYTHONPATH environment variable, if set; @@ -882,7 +888,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, start_buf = buf; if (main_config->module_search_path_env) { - if (wcscpy_s(buf, bufsz - (buf - start_buf), main_config->module_search_path_env)) { + if (wcscpy_s(buf, bufsz - (buf - start_buf), + main_config->module_search_path_env)) { return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); @@ -1214,7 +1221,7 @@ Py_GetProgramFullPath(void) static int python3_checked = 0; static HANDLE hPython3; int -_Py_CheckPython3() +_Py_CheckPython3(void) { wchar_t py3path[MAXPATHLEN+1]; wchar_t *s; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index f0a49f91fb8..a1b29f2a0eb 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1273,8 +1273,6 @@ Py_FinalizeEx(void) call_ll_exitfuncs(); - _PyPathConfig_Fini(); - _PyRuntime_Finalize(); return status; }