Skip to content

bpo-34170: Rework _PyCoreConfig_Read() to avoid side effect #8353

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jul 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions Include/internal/pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ struct _gilstate_runtime_state {
#define _PyGILState_check_enabled _PyRuntime.gilstate.check_enabled


typedef struct {
typedef struct _PyPathConfig {
/* Full path to the Python program */
wchar_t *program_full_path;
wchar_t *prefix;
Expand All @@ -59,11 +59,15 @@ typedef struct {

PyAPI_DATA(_PyPathConfig) _Py_path_config;

PyAPI_FUNC(_PyInitError) _PyPathConfig_Calculate(
PyAPI_FUNC(_PyInitError) _PyPathConfig_Calculate_impl(
_PyPathConfig *config,
const _PyCoreConfig *core_config);
PyAPI_FUNC(void) _PyPathConfig_Clear(_PyPathConfig *config);
PyAPI_FUNC(void) _PyPathConfig_ClearGlobal(void);

PyAPI_FUNC(_PyInitError) _Py_wstrlist_append(
int *len,
wchar_t ***list,
const wchar_t *str);

/* interpreter state */

Expand Down
9 changes: 8 additions & 1 deletion Include/pylifecycle.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *);
PyAPI_FUNC(int) _PyCoreConfig_Copy(
_PyCoreConfig *config,
const _PyCoreConfig *config2);
PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitPathConfig(_PyCoreConfig *config);
PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetPathConfig(
const _PyCoreConfig *config);

PyAPI_FUNC(_PyInitError) _PyMainInterpreterConfig_Read(
_PyMainInterpreterConfig *config,
Expand Down Expand Up @@ -116,7 +119,11 @@ PyAPI_FUNC(wchar_t *) Py_GetPrefix(void);
PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void);
PyAPI_FUNC(wchar_t *) Py_GetPath(void);
#ifdef Py_BUILD_CORE
PyAPI_FUNC(_PyInitError) _PyPathConfig_Init(const _PyCoreConfig *core_config);
struct _PyPathConfig;
typedef struct _PyPathConfig _PyPathConfig;

PyAPI_FUNC(_PyInitError) _PyPathConfig_SetGlobal(
const _PyPathConfig *config);
PyAPI_FUNC(PyObject*) _PyPathConfig_ComputeArgv0(int argc, wchar_t **argv);
PyAPI_FUNC(int) _Py_FindEnvConfigValue(
FILE *env_file,
Expand Down
3 changes: 3 additions & 0 deletions Include/pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ typedef struct {
wchar_t *base_prefix; /* sys.base_prefix */
wchar_t *exec_prefix; /* sys.exec_prefix */
wchar_t *base_exec_prefix; /* sys.base_exec_prefix */
#ifdef MS_WINDOWS
wchar_t *dll_path; /* Windows DLL path */
#endif

/* Private fields */
int _disable_importlib; /* Needed by freeze_importlib */
Expand Down
2 changes: 1 addition & 1 deletion Modules/getpath.c
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ calculate_path_impl(const _PyCoreConfig *core_config,


_PyInitError
_PyPathConfig_Calculate(_PyPathConfig *config, const _PyCoreConfig *core_config)
_PyPathConfig_Calculate_impl(_PyPathConfig *config, const _PyCoreConfig *core_config)
{
PyCalculatePath calculate;
memset(&calculate, 0, sizeof(calculate));
Expand Down
139 changes: 27 additions & 112 deletions Modules/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ pymain_free_raw(_PyMain *pymain)
configuration options set before Py_Initialize() which should
remain valid after Py_Finalize(), since
Py_Initialize()-Py_Finalize() can be called multiple times. */
_PyPathConfig_Clear(&_Py_path_config);
_PyPathConfig_ClearGlobal();

pymain_clear_config(pymain);

Expand Down Expand Up @@ -701,9 +701,13 @@ pymain_run_main_from_importer(_PyMain *pymain)
}


static _PyInitError
wstrlist_append(int *len, wchar_t ***list, const wchar_t *str)
_PyInitError
_Py_wstrlist_append(int *len, wchar_t ***list, const wchar_t *str)
{
if (*len == INT_MAX) {
/* len+1 would overflow */
return _Py_INIT_NO_MEMORY();
}
wchar_t *str2 = _PyMem_RawWcsdup(str);
if (str2 == NULL) {
return _Py_INIT_NO_MEMORY();
Expand All @@ -725,7 +729,7 @@ wstrlist_append(int *len, wchar_t ***list, const wchar_t *str)
static int
pymain_wstrlist_append(_PyMain *pymain, int *len, wchar_t ***list, const wchar_t *str)
{
_PyInitError err = wstrlist_append(len, list, str);
_PyInitError err = _Py_wstrlist_append(len, list, str);
if (_Py_INIT_FAILED(err)) {
pymain->err = err;
return -1;
Expand Down Expand Up @@ -972,9 +976,9 @@ static _PyInitError
config_add_warnings_optlist(_PyCoreConfig *config, int len, wchar_t **options)
{
for (int i = 0; i < len; i++) {
_PyInitError err = wstrlist_append(&config->nwarnoption,
&config->warnoptions,
options[i]);
_PyInitError err = _Py_wstrlist_append(&config->nwarnoption,
&config->warnoptions,
options[i]);
if (_Py_INIT_FAILED(err)) {
return err;
}
Expand Down Expand Up @@ -1006,9 +1010,9 @@ config_init_warnoptions(_PyCoreConfig *config, _Py_CommandLineDetails *cmdline)
*/

if (config->dev_mode) {
err = wstrlist_append(&config->nwarnoption,
&config->warnoptions,
L"default");
err = _Py_wstrlist_append(&config->nwarnoption,
&config->warnoptions,
L"default");
if (_Py_INIT_FAILED(err)) {
return err;
}
Expand Down Expand Up @@ -1040,9 +1044,9 @@ config_init_warnoptions(_PyCoreConfig *config, _Py_CommandLineDetails *cmdline)
else {
filter = L"default::BytesWarning";
}
err = wstrlist_append(&config->nwarnoption,
&config->warnoptions,
filter);
err = _Py_wstrlist_append(&config->nwarnoption,
&config->warnoptions,
filter);
if (_Py_INIT_FAILED(err)) {
return err;
}
Expand Down Expand Up @@ -1077,9 +1081,9 @@ cmdline_init_env_warnoptions(_Py_CommandLineDetails *cmdline)
warning != NULL;
warning = WCSTOK(NULL, L",", &context))
{
_PyInitError err = wstrlist_append(&cmdline->nenv_warnoption,
&cmdline->env_warnoptions,
warning);
_PyInitError err = _Py_wstrlist_append(&cmdline->nenv_warnoption,
&cmdline->env_warnoptions,
warning);
if (_Py_INIT_FAILED(err)) {
PyMem_RawFree(env);
return err;
Expand Down Expand Up @@ -2099,101 +2103,6 @@ config_init_locale(_PyCoreConfig *config)
}


static _PyInitError
config_init_module_search_paths(_PyCoreConfig *config)
{
assert(config->module_search_paths == NULL);
assert(config->nmodule_search_path < 0);

config->nmodule_search_path = 0;

const wchar_t *sys_path = Py_GetPath();
const wchar_t delim = DELIM;
const wchar_t *p = sys_path;
while (1) {
p = wcschr(sys_path, delim);
if (p == NULL) {
p = sys_path + wcslen(sys_path); /* End of string */
}

size_t path_len = (p - sys_path);
wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
if (path == NULL) {
return _Py_INIT_NO_MEMORY();
}
memcpy(path, sys_path, path_len * sizeof(wchar_t));
path[path_len] = L'\0';

_PyInitError err = wstrlist_append(&config->nmodule_search_path,
&config->module_search_paths,
path);
PyMem_RawFree(path);
if (_Py_INIT_FAILED(err)) {
return err;
}

if (*p == '\0') {
break;
}
sys_path = p + 1;
}
return _Py_INIT_OK();
}


static _PyInitError
config_init_path_config(_PyCoreConfig *config)
{
_PyInitError err = _PyPathConfig_Init(config);
if (_Py_INIT_FAILED(err)) {
return err;
}

if (config->nmodule_search_path < 0) {
err = config_init_module_search_paths(config);
if (_Py_INIT_FAILED(err)) {
return err;
}
}

if (config->executable == NULL) {
config->executable = _PyMem_RawWcsdup(Py_GetProgramFullPath());
if (config->executable == NULL) {
return _Py_INIT_NO_MEMORY();
}
}

if (config->prefix == NULL) {
config->prefix = _PyMem_RawWcsdup(Py_GetPrefix());
if (config->prefix == NULL) {
return _Py_INIT_NO_MEMORY();
}
}

if (config->exec_prefix == NULL) {
config->exec_prefix = _PyMem_RawWcsdup(Py_GetExecPrefix());
if (config->exec_prefix == NULL) {
return _Py_INIT_NO_MEMORY();
}
}

if (config->base_prefix == NULL) {
config->base_prefix = _PyMem_RawWcsdup(config->prefix);
if (config->base_prefix == NULL) {
return _Py_INIT_NO_MEMORY();
}
}

if (config->base_exec_prefix == NULL) {
config->base_exec_prefix = _PyMem_RawWcsdup(config->exec_prefix);
if (config->base_exec_prefix == NULL) {
return _Py_INIT_NO_MEMORY();
}
}

return _Py_INIT_OK();
}

/* Read configuration settings from standard locations
*
* This function doesn't make any changes to the interpreter state - it
Expand Down Expand Up @@ -2252,7 +2161,7 @@ _PyCoreConfig_Read(_PyCoreConfig *config)
}

if (!config->_disable_importlib) {
err = config_init_path_config(config);
err = _PyCoreConfig_InitPathConfig(config);
if (_Py_INIT_FAILED(err)) {
return err;
}
Expand Down Expand Up @@ -2294,6 +2203,9 @@ _PyCoreConfig_Clear(_PyCoreConfig *config)
CLEAR(config->prefix);
CLEAR(config->base_prefix);
CLEAR(config->exec_prefix);
#ifdef MS_WINDOWS
CLEAR(config->dll_path);
#endif
CLEAR(config->base_exec_prefix);
#undef CLEAR
#undef CLEAR_WSTRLIST
Expand Down Expand Up @@ -2356,6 +2268,9 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2)
COPY_STR_ATTR(prefix);
COPY_STR_ATTR(base_prefix);
COPY_STR_ATTR(exec_prefix);
#ifdef MS_WINDOWS
COPY_STR_ATTR(dll_path);
#endif
COPY_STR_ATTR(base_exec_prefix);

#undef COPY_ATTR
Expand Down
2 changes: 1 addition & 1 deletion PC/getpathp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1000,7 +1000,7 @@ calculate_free(PyCalculatePath *calculate)


_PyInitError
_PyPathConfig_Calculate(_PyPathConfig *config, const _PyCoreConfig *core_config)
_PyPathConfig_Calculate_impl(_PyPathConfig *config, const _PyCoreConfig *core_config)
{
PyCalculatePath calculate;
memset(&calculate, 0, sizeof(calculate));
Expand Down
Loading