Commit 1ce152a4 authored by Victor Stinner's avatar Victor Stinner Committed by GitHub

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().
parent b0e1ae5f
...@@ -472,8 +472,8 @@ Process-wide parameters ...@@ -472,8 +472,8 @@ Process-wide parameters
dependent delimiter character, which is ``':'`` on Unix and Mac OS X, ``';'`` dependent delimiter character, which is ``':'`` on Unix and Mac OS X, ``';'``
on Windows. on Windows.
This also causes :data:`sys.executable` to be set only to the raw program This also causes :data:`sys.executable` to be set to the program
name (see :c:func:`Py_SetProgramName`) and for :data:`sys.prefix` and 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 :data:`sys.exec_prefix` to be empty. It is up to the caller to modify these
if required after calling :c:func:`Py_Initialize`. if required after calling :c:func:`Py_Initialize`.
...@@ -483,6 +483,10 @@ Process-wide parameters ...@@ -483,6 +483,10 @@ Process-wide parameters
The path argument is copied internally, so the caller may free it after the The path argument is copied internally, so the caller may free it after the
call completes. 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() .. c:function:: const char* Py_GetVersion()
......
...@@ -1347,6 +1347,11 @@ Build and C API Changes ...@@ -1347,6 +1347,11 @@ Build and C API Changes
parameter for indicating the number of positional-only arguments. parameter for indicating the number of positional-only arguments.
(Contributed by Pablo Galindo in :issue:`37221`.) (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 Deprecated
========== ==========
......
: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`).
...@@ -23,6 +23,7 @@ wchar_t *_Py_dll_path = NULL; ...@@ -23,6 +23,7 @@ wchar_t *_Py_dll_path = NULL;
static int static int
copy_wstr(wchar_t **dst, const wchar_t *src) copy_wstr(wchar_t **dst, const wchar_t *src)
{ {
assert(*dst == NULL);
if (src != NULL) { if (src != NULL) {
*dst = _PyMem_RawWcsdup(src); *dst = _PyMem_RawWcsdup(src);
if (*dst == NULL) { if (*dst == NULL) {
...@@ -172,6 +173,7 @@ pathconfig_set_from_config(_PyPathConfig *pathconfig, const PyConfig *config) ...@@ -172,6 +173,7 @@ pathconfig_set_from_config(_PyPathConfig *pathconfig, const PyConfig *config)
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (config->module_search_paths_set) { if (config->module_search_paths_set) {
PyMem_RawFree(pathconfig->module_search_path);
pathconfig->module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM); pathconfig->module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM);
if (pathconfig->module_search_path == NULL) { if (pathconfig->module_search_path == NULL) {
goto no_memory; goto no_memory;
...@@ -180,6 +182,8 @@ pathconfig_set_from_config(_PyPathConfig *pathconfig, const PyConfig *config) ...@@ -180,6 +182,8 @@ pathconfig_set_from_config(_PyPathConfig *pathconfig, const PyConfig *config)
#define COPY_CONFIG(PATH_ATTR, CONFIG_ATTR) \ #define COPY_CONFIG(PATH_ATTR, CONFIG_ATTR) \
if (config->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) { \ if (copy_wstr(&pathconfig->PATH_ATTR, config->CONFIG_ATTR) < 0) { \
goto no_memory; \ goto no_memory; \
} \ } \
...@@ -455,16 +459,15 @@ Py_SetPath(const wchar_t *path) ...@@ -455,16 +459,15 @@ Py_SetPath(const wchar_t *path)
PyMemAllocatorEx old_alloc; PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
/* Getting the program name calls pathconfig_global_init() */ /* Getting the program full path calls pathconfig_global_init() */
wchar_t *program_name = _PyMem_RawWcsdup(Py_GetProgramName()); wchar_t *program_full_path = _PyMem_RawWcsdup(Py_GetProgramFullPath());
PyMem_RawFree(_Py_path_config.program_full_path); PyMem_RawFree(_Py_path_config.program_full_path);
PyMem_RawFree(_Py_path_config.prefix); PyMem_RawFree(_Py_path_config.prefix);
PyMem_RawFree(_Py_path_config.exec_prefix); PyMem_RawFree(_Py_path_config.exec_prefix);
PyMem_RawFree(_Py_path_config.module_search_path); PyMem_RawFree(_Py_path_config.module_search_path);
/* Copy program_name to program_full_path */ _Py_path_config.program_full_path = program_full_path;
_Py_path_config.program_full_path = program_name;
_Py_path_config.prefix = _PyMem_RawWcsdup(L""); _Py_path_config.prefix = _PyMem_RawWcsdup(L"");
_Py_path_config.exec_prefix = _PyMem_RawWcsdup(L""); _Py_path_config.exec_prefix = _PyMem_RawWcsdup(L"");
_Py_path_config.module_search_path = _PyMem_RawWcsdup(path); _Py_path_config.module_search_path = _PyMem_RawWcsdup(path);
......
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