Skip to content

Commit 1ce152a

Browse files
authored
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().
1 parent b0e1ae5 commit 1ce152a

File tree

4 files changed

+21
-6
lines changed

4 files changed

+21
-6
lines changed

Doc/c-api/init.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -472,8 +472,8 @@ Process-wide parameters
472472
dependent delimiter character, which is ``':'`` on Unix and Mac OS X, ``';'``
473473
on Windows.
474474
475-
This also causes :data:`sys.executable` to be set only to the raw program
476-
name (see :c:func:`Py_SetProgramName`) and for :data:`sys.prefix` and
475+
This also causes :data:`sys.executable` to be set to the program
476+
full path (see :c:func:`Py_GetProgramFullPath`) and for :data:`sys.prefix` and
477477
:data:`sys.exec_prefix` to be empty. It is up to the caller to modify these
478478
if required after calling :c:func:`Py_Initialize`.
479479
@@ -483,6 +483,10 @@ Process-wide parameters
483483
The path argument is copied internally, so the caller may free it after the
484484
call completes.
485485
486+
.. versionchanged:: 3.8
487+
The program full path is now used for :data:`sys.executable`, instead
488+
of the program name.
489+
486490
487491
.. c:function:: const char* Py_GetVersion()
488492

Doc/whatsnew/3.8.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,6 +1347,11 @@ Build and C API Changes
13471347
parameter for indicating the number of positional-only arguments.
13481348
(Contributed by Pablo Galindo in :issue:`37221`.)
13491349

1350+
* :c:func:`Py_SetPath` now sets :data:`sys.executable` to the program full
1351+
path (:c:func:`Py_GetProgramFullPath`) rather than to the program name
1352+
(:c:func:`Py_GetProgramName`).
1353+
(Contributed by Victor Stinner in :issue:`38234`.)
1354+
13501355

13511356
Deprecated
13521357
==========
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:c:func:`Py_SetPath` now sets :data:`sys.executable` to the program full
2+
path (:c:func:`Py_GetProgramFullPath`) rather than to the program name
3+
(:c:func:`Py_GetProgramName`).

Python/pathconfig.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ wchar_t *_Py_dll_path = NULL;
2323
static int
2424
copy_wstr(wchar_t **dst, const wchar_t *src)
2525
{
26+
assert(*dst == NULL);
2627
if (src != NULL) {
2728
*dst = _PyMem_RawWcsdup(src);
2829
if (*dst == NULL) {
@@ -172,6 +173,7 @@ pathconfig_set_from_config(_PyPathConfig *pathconfig, const PyConfig *config)
172173
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
173174

174175
if (config->module_search_paths_set) {
176+
PyMem_RawFree(pathconfig->module_search_path);
175177
pathconfig->module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM);
176178
if (pathconfig->module_search_path == NULL) {
177179
goto no_memory;
@@ -180,6 +182,8 @@ pathconfig_set_from_config(_PyPathConfig *pathconfig, const PyConfig *config)
180182

181183
#define COPY_CONFIG(PATH_ATTR, CONFIG_ATTR) \
182184
if (config->CONFIG_ATTR) { \
185+
PyMem_RawFree(pathconfig->PATH_ATTR); \
186+
pathconfig->PATH_ATTR = NULL; \
183187
if (copy_wstr(&pathconfig->PATH_ATTR, config->CONFIG_ATTR) < 0) { \
184188
goto no_memory; \
185189
} \
@@ -455,16 +459,15 @@ Py_SetPath(const wchar_t *path)
455459
PyMemAllocatorEx old_alloc;
456460
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
457461

458-
/* Getting the program name calls pathconfig_global_init() */
459-
wchar_t *program_name = _PyMem_RawWcsdup(Py_GetProgramName());
462+
/* Getting the program full path calls pathconfig_global_init() */
463+
wchar_t *program_full_path = _PyMem_RawWcsdup(Py_GetProgramFullPath());
460464

461465
PyMem_RawFree(_Py_path_config.program_full_path);
462466
PyMem_RawFree(_Py_path_config.prefix);
463467
PyMem_RawFree(_Py_path_config.exec_prefix);
464468
PyMem_RawFree(_Py_path_config.module_search_path);
465469

466-
/* Copy program_name to program_full_path */
467-
_Py_path_config.program_full_path = program_name;
470+
_Py_path_config.program_full_path = program_full_path;
468471
_Py_path_config.prefix = _PyMem_RawWcsdup(L"");
469472
_Py_path_config.exec_prefix = _PyMem_RawWcsdup(L"");
470473
_Py_path_config.module_search_path = _PyMem_RawWcsdup(path);

0 commit comments

Comments
 (0)