Skip to content

Commit 3f5409a

Browse files
authored
bpo-38234: Fix _PyConfig_InitPathConfig() (GH-16335) (GH-16336)
* _PyConfig_InitPathConfig() now starts by copying the global path configuration, and then override values set in PyConfig. * _PyPathConfig_Calculate() implementations no longer override _PyPathConfig fields which are already computed. For example, if _PyPathConfig.prefix is not NULL, leave it unchanged. * If Py_SetPath() has been called, _PyConfig_InitPathConfig() doesn't call _PyPathConfig_Calculate() anymore. * _PyPathConfig_Calculate() no longer uses PyConfig, except to initialize PyCalculatePath structure. * pathconfig_calculate(): remove useless temporary "_PyPathConfig new_config" variable. * calculate_module_search_path(): remove hack to workaround memory allocation failure, call Py_FatalError() instead. * Fix get_program_full_path(): handle memory allocation failure. (cherry picked from commit 9c42f8c)
1 parent c5c6425 commit 3f5409a

File tree

4 files changed

+316
-254
lines changed

4 files changed

+316
-254
lines changed
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
Python ignored path passed to :c:func:`Py_SetPath`, fix Python
2-
initialization to use the specified path.
1+
Python ignored arguments passed to :c:func:`Py_SetPath`,
2+
:c:func:`Py_SetPythonHome` and :c:func:`Py_SetProgramName`: fix Python
3+
initialization to use specified arguments.

Modules/getpath.c

Lines changed: 78 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ typedef struct {
133133

134134
int prefix_found; /* found platform independent libraries? */
135135
int exec_prefix_found; /* found the platform dependent libraries? */
136+
137+
int warnings;
138+
const wchar_t *pythonpath_env;
136139
} PyCalculatePath;
137140

138141
static const wchar_t delimiter[2] = {DELIM, '\0'};
@@ -365,17 +368,16 @@ add_exe_suffix(wchar_t *progpath, size_t progpathlen)
365368
bytes long.
366369
*/
367370
static PyStatus
368-
search_for_prefix(const PyConfig *config, PyCalculatePath *calculate,
369-
wchar_t *prefix, size_t prefix_len,
370-
int *found)
371+
search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
372+
wchar_t *prefix, size_t prefix_len, int *found)
371373
{
372374
PyStatus status;
373375
size_t n;
374376
wchar_t *vpath;
375377

376378
/* If PYTHONHOME is set, we believe it unconditionally */
377-
if (config->home) {
378-
if (safe_wcscpy(prefix, config->home, prefix_len) < 0) {
379+
if (pathconfig->home) {
380+
if (safe_wcscpy(prefix, pathconfig->home, prefix_len) < 0) {
379381
return PATHLEN_ERR();
380382
}
381383
wchar_t *delim = wcschr(prefix, DELIM);
@@ -482,19 +484,19 @@ search_for_prefix(const PyConfig *config, PyCalculatePath *calculate,
482484

483485

484486
static PyStatus
485-
calculate_prefix(const PyConfig *config,
486-
PyCalculatePath *calculate, wchar_t *prefix, size_t prefix_len)
487+
calculate_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
488+
wchar_t *prefix, size_t prefix_len)
487489
{
488490
PyStatus status;
489491

490-
status = search_for_prefix(config, calculate, prefix, prefix_len,
491-
&calculate->prefix_found);
492+
status = search_for_prefix(calculate, pathconfig, prefix, prefix_len,
493+
&calculate->prefix_found);
492494
if (_PyStatus_EXCEPTION(status)) {
493495
return status;
494496
}
495497

496498
if (!calculate->prefix_found) {
497-
if (config->pathconfig_warnings) {
499+
if (calculate->warnings) {
498500
fprintf(stderr,
499501
"Could not find platform independent libraries <prefix>\n");
500502
}
@@ -544,24 +546,23 @@ calculate_reduce_prefix(PyCalculatePath *calculate,
544546
MAXPATHLEN bytes long.
545547
*/
546548
static PyStatus
547-
search_for_exec_prefix(const PyConfig *config,
548-
PyCalculatePath *calculate,
549+
search_for_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
549550
wchar_t *exec_prefix, size_t exec_prefix_len,
550551
int *found)
551552
{
552553
PyStatus status;
553554
size_t n;
554555

555556
/* If PYTHONHOME is set, we believe it unconditionally */
556-
if (config->home) {
557-
wchar_t *delim = wcschr(config->home, DELIM);
557+
if (pathconfig->home) {
558+
wchar_t *delim = wcschr(pathconfig->home, DELIM);
558559
if (delim) {
559560
if (safe_wcscpy(exec_prefix, delim+1, exec_prefix_len) < 0) {
560561
return PATHLEN_ERR();
561562
}
562563
}
563564
else {
564-
if (safe_wcscpy(exec_prefix, config->home, exec_prefix_len) < 0) {
565+
if (safe_wcscpy(exec_prefix, pathconfig->home, exec_prefix_len) < 0) {
565566
return PATHLEN_ERR();
566567
}
567568
}
@@ -668,21 +669,20 @@ search_for_exec_prefix(const PyConfig *config,
668669

669670

670671
static PyStatus
671-
calculate_exec_prefix(const PyConfig *config,
672-
PyCalculatePath *calculate,
672+
calculate_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
673673
wchar_t *exec_prefix, size_t exec_prefix_len)
674674
{
675675
PyStatus status;
676676

677-
status = search_for_exec_prefix(config, calculate,
678-
exec_prefix, exec_prefix_len,
679-
&calculate->exec_prefix_found);
677+
status = search_for_exec_prefix(calculate, pathconfig,
678+
exec_prefix, exec_prefix_len,
679+
&calculate->exec_prefix_found);
680680
if (_PyStatus_EXCEPTION(status)) {
681681
return status;
682682
}
683683

684684
if (!calculate->exec_prefix_found) {
685-
if (config->pathconfig_warnings) {
685+
if (calculate->warnings) {
686686
fprintf(stderr,
687687
"Could not find platform dependent libraries <exec_prefix>\n");
688688
}
@@ -721,8 +721,7 @@ calculate_reduce_exec_prefix(PyCalculatePath *calculate,
721721

722722

723723
static PyStatus
724-
calculate_program_full_path(const PyConfig *config,
725-
PyCalculatePath *calculate, _PyPathConfig *pathconfig)
724+
calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
726725
{
727726
PyStatus status;
728727
wchar_t program_full_path[MAXPATHLEN + 1];
@@ -743,8 +742,8 @@ calculate_program_full_path(const PyConfig *config,
743742
* other way to find a directory to start the search from. If
744743
* $PATH isn't exported, you lose.
745744
*/
746-
if (wcschr(config->program_name, SEP)) {
747-
if (safe_wcscpy(program_full_path, config->program_name,
745+
if (wcschr(pathconfig->program_name, SEP)) {
746+
if (safe_wcscpy(program_full_path, pathconfig->program_name,
748747
program_full_path_len) < 0) {
749748
return PATHLEN_ERR();
750749
}
@@ -795,8 +794,8 @@ calculate_program_full_path(const PyConfig *config,
795794
}
796795
}
797796

798-
status = joinpath(program_full_path, config->program_name,
799-
program_full_path_len);
797+
status = joinpath(program_full_path, pathconfig->program_name,
798+
program_full_path_len);
800799
if (_PyStatus_EXCEPTION(status)) {
801800
return status;
802801
}
@@ -1030,15 +1029,14 @@ calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix)
10301029

10311030

10321031
static PyStatus
1033-
calculate_module_search_path(const PyConfig *config,
1034-
PyCalculatePath *calculate,
1035-
const wchar_t *prefix, const wchar_t *exec_prefix,
1036-
_PyPathConfig *pathconfig)
1032+
calculate_module_search_path(PyCalculatePath *calculate,
1033+
_PyPathConfig *pathconfig,
1034+
const wchar_t *prefix, const wchar_t *exec_prefix)
10371035
{
10381036
/* Calculate size of return buffer */
10391037
size_t bufsz = 0;
1040-
if (config->pythonpath_env != NULL) {
1041-
bufsz += wcslen(config->pythonpath_env) + 1;
1038+
if (calculate->pythonpath_env != NULL) {
1039+
bufsz += wcslen(calculate->pythonpath_env) + 1;
10421040
}
10431041

10441042
wchar_t *defpath = calculate->pythonpath;
@@ -1072,8 +1070,8 @@ calculate_module_search_path(const PyConfig *config,
10721070
buf[0] = '\0';
10731071

10741072
/* Run-time value of $PYTHONPATH goes first */
1075-
if (config->pythonpath_env) {
1076-
wcscpy(buf, config->pythonpath_env);
1073+
if (calculate->pythonpath_env) {
1074+
wcscpy(buf, calculate->pythonpath_env);
10771075
wcscat(buf, delimiter);
10781076
}
10791077

@@ -1149,6 +1147,10 @@ calculate_init(PyCalculatePath *calculate,
11491147
if (!calculate->lib_python) {
11501148
return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
11511149
}
1150+
1151+
calculate->warnings = config->pathconfig_warnings;
1152+
calculate->pythonpath_env = config->pythonpath_env;
1153+
11521154
return _PyStatus_OK();
11531155
}
11541156

@@ -1165,14 +1167,15 @@ calculate_free(PyCalculatePath *calculate)
11651167

11661168

11671169
static PyStatus
1168-
calculate_path_impl(const PyConfig *config,
1169-
PyCalculatePath *calculate, _PyPathConfig *pathconfig)
1170+
calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
11701171
{
11711172
PyStatus status;
11721173

1173-
status = calculate_program_full_path(config, calculate, pathconfig);
1174-
if (_PyStatus_EXCEPTION(status)) {
1175-
return status;
1174+
if (pathconfig->program_full_path == NULL) {
1175+
status = calculate_program_full_path(calculate, pathconfig);
1176+
if (_PyStatus_EXCEPTION(status)) {
1177+
return status;
1178+
}
11761179
}
11771180

11781181
status = calculate_argv0_path(calculate, pathconfig->program_full_path);
@@ -1187,8 +1190,8 @@ calculate_path_impl(const PyConfig *config,
11871190

11881191
wchar_t prefix[MAXPATHLEN+1];
11891192
memset(prefix, 0, sizeof(prefix));
1190-
status = calculate_prefix(config, calculate,
1191-
prefix, Py_ARRAY_LENGTH(prefix));
1193+
status = calculate_prefix(calculate, pathconfig,
1194+
prefix, Py_ARRAY_LENGTH(prefix));
11921195
if (_PyStatus_EXCEPTION(status)) {
11931196
return status;
11941197
}
@@ -1200,52 +1203,65 @@ calculate_path_impl(const PyConfig *config,
12001203

12011204
wchar_t exec_prefix[MAXPATHLEN+1];
12021205
memset(exec_prefix, 0, sizeof(exec_prefix));
1203-
status = calculate_exec_prefix(config, calculate,
1204-
exec_prefix, Py_ARRAY_LENGTH(exec_prefix));
1206+
status = calculate_exec_prefix(calculate, pathconfig,
1207+
exec_prefix, Py_ARRAY_LENGTH(exec_prefix));
12051208
if (_PyStatus_EXCEPTION(status)) {
12061209
return status;
12071210
}
12081211

12091212
if ((!calculate->prefix_found || !calculate->exec_prefix_found) &&
1210-
config->pathconfig_warnings)
1213+
calculate->warnings)
12111214
{
12121215
fprintf(stderr,
12131216
"Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
12141217
}
12151218

12161219
if (pathconfig->module_search_path == NULL) {
1217-
status = calculate_module_search_path(config, calculate,
1218-
prefix, exec_prefix, pathconfig);
1220+
status = calculate_module_search_path(calculate, pathconfig,
1221+
prefix, exec_prefix);
12191222
if (_PyStatus_EXCEPTION(status)) {
12201223
return status;
12211224
}
12221225
}
12231226

1224-
status = calculate_reduce_prefix(calculate, prefix, Py_ARRAY_LENGTH(prefix));
1225-
if (_PyStatus_EXCEPTION(status)) {
1226-
return status;
1227-
}
1228-
1229-
pathconfig->prefix = _PyMem_RawWcsdup(prefix);
12301227
if (pathconfig->prefix == NULL) {
1231-
return _PyStatus_NO_MEMORY();
1232-
}
1228+
status = calculate_reduce_prefix(calculate, prefix, Py_ARRAY_LENGTH(prefix));
1229+
if (_PyStatus_EXCEPTION(status)) {
1230+
return status;
1231+
}
12331232

1234-
status = calculate_reduce_exec_prefix(calculate,
1235-
exec_prefix, Py_ARRAY_LENGTH(exec_prefix));
1236-
if (_PyStatus_EXCEPTION(status)) {
1237-
return status;
1233+
pathconfig->prefix = _PyMem_RawWcsdup(prefix);
1234+
if (pathconfig->prefix == NULL) {
1235+
return _PyStatus_NO_MEMORY();
1236+
}
12381237
}
12391238

1240-
pathconfig->exec_prefix = _PyMem_RawWcsdup(exec_prefix);
12411239
if (pathconfig->exec_prefix == NULL) {
1242-
return _PyStatus_NO_MEMORY();
1240+
status = calculate_reduce_exec_prefix(calculate,
1241+
exec_prefix,
1242+
Py_ARRAY_LENGTH(exec_prefix));
1243+
if (_PyStatus_EXCEPTION(status)) {
1244+
return status;
1245+
}
1246+
1247+
pathconfig->exec_prefix = _PyMem_RawWcsdup(exec_prefix);
1248+
if (pathconfig->exec_prefix == NULL) {
1249+
return _PyStatus_NO_MEMORY();
1250+
}
12431251
}
12441252

12451253
return _PyStatus_OK();
12461254
}
12471255

12481256

1257+
/* Calculate 'pathconfig' attributes:
1258+
1259+
- program_full_path
1260+
- module_search_path
1261+
- prefix
1262+
- exec_prefix
1263+
1264+
If an attribute is already set (non NULL), it is left unchanged. */
12491265
PyStatus
12501266
_PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config)
12511267
{
@@ -1258,7 +1274,7 @@ _PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config)
12581274
goto done;
12591275
}
12601276

1261-
status = calculate_path_impl(config, &calculate, pathconfig);
1277+
status = calculate_path(&calculate, pathconfig);
12621278
if (_PyStatus_EXCEPTION(status)) {
12631279
goto done;
12641280
}

0 commit comments

Comments
 (0)