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
diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h
index d32c98b..3db8832 100644
--- a/Include/pylifecycle.h
+++ b/Include/pylifecycle.h
@@ -109,7 +109,7 @@
#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 183717d..235bada 100644
--- a/Modules/getpath.c
+++ b/Modules/getpath.c
@@ -625,11 +625,13 @@
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 caec97f..4659c5d 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -888,15 +888,12 @@
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 @@
* 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 @@
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 89d37a8..f8cfd7e 100644
--- a/PC/getpathp.c
+++ b/PC/getpathp.c
@@ -721,12 +721,16 @@
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 @@
#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 @@
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 @@
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 f0a49f9..a1b29f2 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -1273,8 +1273,6 @@
call_ll_exitfuncs();
- _PyPathConfig_Fini();
-
_PyRuntime_Finalize();
return status;
}