From: Victor Stinner Date: Tue, 24 Sep 2019 15:44:15 +0000 (+0200) Subject: bpo-38234: Py_SetPath() uses the program full path (GH-16357) X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1ce152a42eaa917d7763bce93f1e1ca72530d7ca;p=python bpo-38234: Py_SetPath() uses the program full path (GH-16357) Py_SetPath() now sets sys.executable to the program full path (Py_GetProgramFullPath()), rather than to the program name (Py_GetProgramName()). Fix also memory leaks in pathconfig_set_from_config(). --- diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index 0f8ff3b0dd..0b7a84d031 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -472,8 +472,8 @@ Process-wide parameters dependent delimiter character, which is ``':'`` on Unix and Mac OS X, ``';'`` on Windows. - This also causes :data:`sys.executable` to be set only to the raw program - name (see :c:func:`Py_SetProgramName`) and for :data:`sys.prefix` and + This also causes :data:`sys.executable` to be set to the program + full path (see :c:func:`Py_GetProgramFullPath`) and for :data:`sys.prefix` and :data:`sys.exec_prefix` to be empty. It is up to the caller to modify these if required after calling :c:func:`Py_Initialize`. @@ -483,6 +483,10 @@ Process-wide parameters The path argument is copied internally, so the caller may free it after the call completes. + .. versionchanged:: 3.8 + The program full path is now used for :data:`sys.executable`, instead + of the program name. + .. c:function:: const char* Py_GetVersion() diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index c2455f487b..0995cb3b91 100755 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -1347,6 +1347,11 @@ Build and C API Changes parameter for indicating the number of positional-only arguments. (Contributed by Pablo Galindo in :issue:`37221`.) +* :c:func:`Py_SetPath` now sets :data:`sys.executable` to the program full + path (:c:func:`Py_GetProgramFullPath`) rather than to the program name + (:c:func:`Py_GetProgramName`). + (Contributed by Victor Stinner in :issue:`38234`.) + Deprecated ========== diff --git a/Misc/NEWS.d/next/C API/2019-09-24-17-09-48.bpo-38234.d0bhEA.rst b/Misc/NEWS.d/next/C API/2019-09-24-17-09-48.bpo-38234.d0bhEA.rst new file mode 100644 index 0000000000..ba4cc312e6 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2019-09-24-17-09-48.bpo-38234.d0bhEA.rst @@ -0,0 +1,3 @@ +:c:func:`Py_SetPath` now sets :data:`sys.executable` to the program full +path (:c:func:`Py_GetProgramFullPath`) rather than to the program name +(:c:func:`Py_GetProgramName`). diff --git a/Python/pathconfig.c b/Python/pathconfig.c index 7677a15579..8f76fa50c9 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -23,6 +23,7 @@ wchar_t *_Py_dll_path = NULL; static int copy_wstr(wchar_t **dst, const wchar_t *src) { + assert(*dst == NULL); if (src != NULL) { *dst = _PyMem_RawWcsdup(src); if (*dst == NULL) { @@ -172,6 +173,7 @@ pathconfig_set_from_config(_PyPathConfig *pathconfig, const PyConfig *config) _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); if (config->module_search_paths_set) { + PyMem_RawFree(pathconfig->module_search_path); pathconfig->module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM); if (pathconfig->module_search_path == NULL) { goto no_memory; @@ -180,6 +182,8 @@ pathconfig_set_from_config(_PyPathConfig *pathconfig, const PyConfig *config) #define COPY_CONFIG(PATH_ATTR, CONFIG_ATTR) \ if (config->CONFIG_ATTR) { \ + PyMem_RawFree(pathconfig->PATH_ATTR); \ + pathconfig->PATH_ATTR = NULL; \ if (copy_wstr(&pathconfig->PATH_ATTR, config->CONFIG_ATTR) < 0) { \ goto no_memory; \ } \ @@ -455,16 +459,15 @@ Py_SetPath(const wchar_t *path) PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - /* Getting the program name calls pathconfig_global_init() */ - wchar_t *program_name = _PyMem_RawWcsdup(Py_GetProgramName()); + /* Getting the program full path calls pathconfig_global_init() */ + wchar_t *program_full_path = _PyMem_RawWcsdup(Py_GetProgramFullPath()); PyMem_RawFree(_Py_path_config.program_full_path); PyMem_RawFree(_Py_path_config.prefix); PyMem_RawFree(_Py_path_config.exec_prefix); PyMem_RawFree(_Py_path_config.module_search_path); - /* Copy program_name to program_full_path */ - _Py_path_config.program_full_path = program_name; + _Py_path_config.program_full_path = program_full_path; _Py_path_config.prefix = _PyMem_RawWcsdup(L""); _Py_path_config.exec_prefix = _PyMem_RawWcsdup(L""); _Py_path_config.module_search_path = _PyMem_RawWcsdup(path);