Skip to content

Commit b64de46

Browse files
authored
bpo-32030: Cleanup "path config" code (#4663)
* Rename PyPathConfig structure to _PyPathConfig and move it to Include/internal/pystate.h * Rename path_config to _Py_path_config * _PyPathConfig: Rename program_name field to program_full_path * Add assert(str != NULL); to _PyMem_RawWcsdup(), _PyMem_RawStrdup() and _PyMem_Strdup(). * Rename calculate_path() to pathconfig_global_init(). The function now does nothing if it's already initiallized.
1 parent 8f5c28b commit b64de46

File tree

4 files changed

+136
-137
lines changed

4 files changed

+136
-137
lines changed

Include/internal/pystate.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,22 @@ struct _gilstate_runtime_state {
3737
#define _PyGILState_check_enabled _PyRuntime.gilstate.check_enabled
3838

3939

40+
typedef struct {
41+
/* Full path to the Python program */
42+
wchar_t *program_full_path;
43+
wchar_t *prefix;
44+
#ifdef MS_WINDOWS
45+
wchar_t *dll_path;
46+
#else
47+
wchar_t *exec_prefix;
48+
#endif
49+
/* Set by Py_SetPath(), or computed by _PyPathConfig_Init() */
50+
wchar_t *module_search_path;
51+
} _PyPathConfig;
52+
53+
#define _PyPathConfig_INIT {.module_search_path = NULL}
54+
55+
4056
/* Full Python runtime state */
4157

4258
typedef struct pyruntimestate {

Modules/getpath.c

Lines changed: 54 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* Return the initial module search path. */
22

33
#include "Python.h"
4+
#include "internal/pystate.h"
45
#include "osdefs.h"
56

67
#include <sys/types.h>
@@ -114,14 +115,6 @@ extern "C" {
114115
? _Py_INIT_USER_ERR("cannot decode " #NAME) \
115116
: _Py_INIT_NO_MEMORY()
116117

117-
118-
typedef struct {
119-
wchar_t *prefix;
120-
wchar_t *exec_prefix;
121-
wchar_t *program_name;
122-
wchar_t *module_search_path;
123-
} PyPathConfig;
124-
125118
typedef struct {
126119
wchar_t *path_env; /* PATH environment variable */
127120
wchar_t *home; /* PYTHONHOME environment variable */
@@ -142,7 +135,7 @@ typedef struct {
142135

143136
static const wchar_t delimiter[2] = {DELIM, '\0'};
144137
static const wchar_t separator[2] = {SEP, '\0'};
145-
static PyPathConfig path_config = {.module_search_path = NULL};
138+
static _PyPathConfig _Py_path_config = _PyPathConfig_INIT;
146139

147140

148141
/* Get file status. Encode the path to the locale encoding. */
@@ -592,10 +585,10 @@ calculate_reduce_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix)
592585

593586

594587
static _PyInitError
595-
calculate_program_name(PyCalculatePath *calculate, PyPathConfig *config)
588+
calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config)
596589
{
597-
wchar_t program_name[MAXPATHLEN+1];
598-
memset(program_name, 0, sizeof(program_name));
590+
wchar_t program_full_path[MAXPATHLEN+1];
591+
memset(program_full_path, 0, sizeof(program_full_path));
599592

600593
#ifdef __APPLE__
601594
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
@@ -612,7 +605,7 @@ calculate_program_name(PyCalculatePath *calculate, PyPathConfig *config)
612605
* $PATH isn't exported, you lose.
613606
*/
614607
if (wcschr(calculate->program_name, SEP)) {
615-
wcsncpy(program_name, calculate->program_name, MAXPATHLEN);
608+
wcsncpy(program_full_path, calculate->program_name, MAXPATHLEN);
616609
}
617610
#ifdef __APPLE__
618611
/* On Mac OS X, if a script uses an interpreter of the form
@@ -628,10 +621,10 @@ calculate_program_name(PyCalculatePath *calculate, PyPathConfig *config)
628621
else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) &&
629622
execpath[0] == SEP)
630623
{
631-
size_t r = mbstowcs(program_name, execpath, MAXPATHLEN+1);
624+
size_t r = mbstowcs(program_full_path, execpath, MAXPATHLEN+1);
632625
if (r == (size_t)-1 || r > MAXPATHLEN) {
633626
/* Could not convert execpath, or it's too long. */
634-
program_name[0] = '\0';
627+
program_full_path[0] = '\0';
635628
}
636629
}
637630
#endif /* __APPLE__ */
@@ -645,44 +638,44 @@ calculate_program_name(PyCalculatePath *calculate, PyPathConfig *config)
645638
if (len > MAXPATHLEN) {
646639
len = MAXPATHLEN;
647640
}
648-
wcsncpy(program_name, path, len);
649-
program_name[len] = '\0';
641+
wcsncpy(program_full_path, path, len);
642+
program_full_path[len] = '\0';
650643
}
651644
else {
652-
wcsncpy(program_name, path, MAXPATHLEN);
645+
wcsncpy(program_full_path, path, MAXPATHLEN);
653646
}
654647

655-
joinpath(program_name, calculate->program_name);
656-
if (isxfile(program_name)) {
648+
joinpath(program_full_path, calculate->program_name);
649+
if (isxfile(program_full_path)) {
657650
break;
658651
}
659652

660653
if (!delim) {
661-
program_name[0] = L'\0';
654+
program_full_path[0] = L'\0';
662655
break;
663656
}
664657
path = delim + 1;
665658
}
666659
}
667660
else {
668-
program_name[0] = '\0';
661+
program_full_path[0] = '\0';
669662
}
670-
if (program_name[0] != SEP && program_name[0] != '\0') {
671-
absolutize(program_name);
663+
if (program_full_path[0] != SEP && program_full_path[0] != '\0') {
664+
absolutize(program_full_path);
672665
}
673666

674-
config->program_name = _PyMem_RawWcsdup(program_name);
675-
if (config->program_name == NULL) {
667+
config->program_full_path = _PyMem_RawWcsdup(program_full_path);
668+
if (config->program_full_path == NULL) {
676669
return _Py_INIT_NO_MEMORY();
677670
}
678671
return _Py_INIT_OK();
679672
}
680673

681674

682675
static _PyInitError
683-
calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_name)
676+
calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_path)
684677
{
685-
wcsncpy(calculate->argv0_path, program_name, MAXPATHLEN);
678+
wcsncpy(calculate->argv0_path, program_full_path, MAXPATHLEN);
686679
calculate->argv0_path[MAXPATHLEN] = '\0';
687680

688681
#ifdef WITH_NEXT_FRAMEWORK
@@ -718,10 +711,10 @@ calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_name)
718711
if (!ismodule(calculate->argv0_path)) {
719712
/* We are in the build directory so use the name of the
720713
executable - we know that the absolute path is passed */
721-
wcsncpy(calculate->argv0_path, program_name, MAXPATHLEN);
714+
wcsncpy(calculate->argv0_path, program_full_path, MAXPATHLEN);
722715
}
723716
else {
724-
/* Use the location of the library as the program_name */
717+
/* Use the location of the library as the program_full_path */
725718
wcsncpy(calculate->argv0_path, wbuf, MAXPATHLEN);
726719
}
727720
PyMem_RawFree(wbuf);
@@ -730,15 +723,15 @@ calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_name)
730723

731724
#if HAVE_READLINK
732725
wchar_t tmpbuffer[MAXPATHLEN+1];
733-
int linklen = _Py_wreadlink(program_name, tmpbuffer, MAXPATHLEN);
726+
int linklen = _Py_wreadlink(program_full_path, tmpbuffer, MAXPATHLEN);
734727
while (linklen != -1) {
735728
if (tmpbuffer[0] == SEP) {
736729
/* tmpbuffer should never be longer than MAXPATHLEN,
737730
but extra check does not hurt */
738731
wcsncpy(calculate->argv0_path, tmpbuffer, MAXPATHLEN);
739732
}
740733
else {
741-
/* Interpret relative to program_name */
734+
/* Interpret relative to program_full_path */
742735
reduce(calculate->argv0_path);
743736
joinpath(calculate->argv0_path, tmpbuffer);
744737
}
@@ -819,7 +812,7 @@ calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix)
819812
static _PyInitError
820813
calculate_module_search_path(PyCalculatePath *calculate,
821814
const wchar_t *prefix, const wchar_t *exec_prefix,
822-
PyPathConfig *config)
815+
_PyPathConfig *config)
823816
{
824817
/* Calculate size of return buffer */
825818
size_t bufsz = 0;
@@ -955,14 +948,14 @@ calculate_free(PyCalculatePath *calculate)
955948

956949

957950
static _PyInitError
958-
calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config)
951+
calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config)
959952
{
960-
_PyInitError err = calculate_program_name(calculate, config);
953+
_PyInitError err = calculate_program_full_path(calculate, config);
961954
if (_Py_INIT_FAILED(err)) {
962955
return err;
963956
}
964957

965-
err = calculate_argv0_path(calculate, config->program_name);
958+
err = calculate_argv0_path(calculate, config->program_full_path);
966959
if (_Py_INIT_FAILED(err)) {
967960
return err;
968961
}
@@ -1011,7 +1004,7 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config)
10111004

10121005

10131006
static void
1014-
pathconfig_clear(PyPathConfig *config)
1007+
pathconfig_clear(_PyPathConfig *config)
10151008
{
10161009
#define CLEAR(ATTR) \
10171010
do { \
@@ -1021,7 +1014,7 @@ pathconfig_clear(PyPathConfig *config)
10211014

10221015
CLEAR(config->prefix);
10231016
CLEAR(config->exec_prefix);
1024-
CLEAR(config->program_name);
1017+
CLEAR(config->program_full_path);
10251018
CLEAR(config->module_search_path);
10261019
#undef CLEAR
10271020
}
@@ -1032,7 +1025,7 @@ pathconfig_clear(PyPathConfig *config)
10321025
_PyInitError
10331026
_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config)
10341027
{
1035-
if (path_config.module_search_path) {
1028+
if (_Py_path_config.module_search_path) {
10361029
/* Already initialized */
10371030
return _Py_INIT_OK();
10381031
}
@@ -1045,7 +1038,7 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config)
10451038
goto done;
10461039
}
10471040

1048-
PyPathConfig new_path_config;
1041+
_PyPathConfig new_path_config;
10491042
memset(&new_path_config, 0, sizeof(new_path_config));
10501043

10511044
err = calculate_path_impl(&calculate, &new_path_config);
@@ -1054,7 +1047,7 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config)
10541047
goto done;
10551048
}
10561049

1057-
path_config = new_path_config;
1050+
_Py_path_config = new_path_config;
10581051
err = _Py_INIT_OK();
10591052

10601053
done:
@@ -1064,8 +1057,13 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config)
10641057

10651058

10661059
static void
1067-
calculate_path(void)
1060+
pathconfig_global_init(void)
10681061
{
1062+
if (_Py_path_config.module_search_path) {
1063+
/* Already initialized */
1064+
return;
1065+
}
1066+
10691067
_PyInitError err;
10701068
_PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT;
10711069

@@ -1084,7 +1082,7 @@ calculate_path(void)
10841082
void
10851083
_PyPathConfig_Fini(void)
10861084
{
1087-
pathconfig_clear(&path_config);
1085+
pathconfig_clear(&_Py_path_config);
10881086
}
10891087

10901088

@@ -1093,58 +1091,50 @@ void
10931091
Py_SetPath(const wchar_t *path)
10941092
{
10951093
if (path == NULL) {
1096-
pathconfig_clear(&path_config);
1094+
pathconfig_clear(&_Py_path_config);
10971095
return;
10981096
}
10991097

1100-
PyPathConfig new_config;
1101-
new_config.program_name = _PyMem_RawWcsdup(Py_GetProgramName());
1098+
_PyPathConfig new_config;
1099+
new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
11021100
new_config.exec_prefix = _PyMem_RawWcsdup(L"");
11031101
new_config.prefix = _PyMem_RawWcsdup(L"");
11041102
new_config.module_search_path = _PyMem_RawWcsdup(path);
11051103

1106-
pathconfig_clear(&path_config);
1107-
path_config = new_config;
1104+
pathconfig_clear(&_Py_path_config);
1105+
_Py_path_config = new_config;
11081106
}
11091107

11101108

11111109
wchar_t *
11121110
Py_GetPath(void)
11131111
{
1114-
if (!path_config.module_search_path) {
1115-
calculate_path();
1116-
}
1117-
return path_config.module_search_path;
1112+
pathconfig_global_init();
1113+
return _Py_path_config.module_search_path;
11181114
}
11191115

11201116

11211117
wchar_t *
11221118
Py_GetPrefix(void)
11231119
{
1124-
if (!path_config.module_search_path) {
1125-
calculate_path();
1126-
}
1127-
return path_config.prefix;
1120+
pathconfig_global_init();
1121+
return _Py_path_config.prefix;
11281122
}
11291123

11301124

11311125
wchar_t *
11321126
Py_GetExecPrefix(void)
11331127
{
1134-
if (!path_config.module_search_path) {
1135-
calculate_path();
1136-
}
1137-
return path_config.exec_prefix;
1128+
pathconfig_global_init();
1129+
return _Py_path_config.exec_prefix;
11381130
}
11391131

11401132

11411133
wchar_t *
11421134
Py_GetProgramFullPath(void)
11431135
{
1144-
if (!path_config.module_search_path) {
1145-
calculate_path();
1146-
}
1147-
return path_config.program_name;
1136+
pathconfig_global_init();
1137+
return _Py_path_config.program_full_path;
11481138
}
11491139

11501140
#ifdef __cplusplus

Objects/obmalloc.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,8 @@ PyMem_Free(void *ptr)
564564
wchar_t*
565565
_PyMem_RawWcsdup(const wchar_t *str)
566566
{
567+
assert(str != NULL);
568+
567569
size_t len = wcslen(str);
568570
if (len > (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t) - 1) {
569571
return NULL;
@@ -582,27 +584,25 @@ _PyMem_RawWcsdup(const wchar_t *str)
582584
char *
583585
_PyMem_RawStrdup(const char *str)
584586
{
585-
size_t size;
586-
char *copy;
587-
588-
size = strlen(str) + 1;
589-
copy = PyMem_RawMalloc(size);
590-
if (copy == NULL)
587+
assert(str != NULL);
588+
size_t size = strlen(str) + 1;
589+
char *copy = PyMem_RawMalloc(size);
590+
if (copy == NULL) {
591591
return NULL;
592+
}
592593
memcpy(copy, str, size);
593594
return copy;
594595
}
595596

596597
char *
597598
_PyMem_Strdup(const char *str)
598599
{
599-
size_t size;
600-
char *copy;
601-
602-
size = strlen(str) + 1;
603-
copy = PyMem_Malloc(size);
604-
if (copy == NULL)
600+
assert(str != NULL);
601+
size_t size = strlen(str) + 1;
602+
char *copy = PyMem_Malloc(size);
603+
if (copy == NULL) {
605604
return NULL;
605+
}
606606
memcpy(copy, str, size);
607607
return copy;
608608
}

0 commit comments

Comments
 (0)