mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
bpo-34170: Rework _PyCoreConfig_Read() to avoid side effect (GH-8353)
Rework _PyCoreConfig_Read() function which *reads* core configuration to not *modify* the path configuration. A new _PyCoreConfig_SetPathConfig() function now recreates the path configuration from the core configuration. This function is now called very late in _Py_InitializeCore(), just before calling initimport(). Changes: * Add _PyCoreConfig.dll_path * Py_SetPath() now fails with a fatal python error on memory allocation failure. * Rename _PyPathConfig_Calculate() to _PyPathConfig_Calculate_impl() * Replace _PyPathConfig_Init() with _PyPathConfig_Calculate(): the function now requires a _PyPathConfig * Add _PyPathConfig_SetGlobal() to set the _Py_path_config global variable. * Add _PyCoreConfig_InitPathConfig(): compute the path configuration * Add _PyCoreConfig_SetPathConfig(): set path configuration from core configuration * Rename wstrlist_append() to _Py_wstrlist_append() * _Py_wstrlist_append() now handles integer overflow.
This commit is contained in:
parent
94487d4570
commit
b1147e43da
8 changed files with 358 additions and 146 deletions
|
@ -37,7 +37,7 @@ struct _gilstate_runtime_state {
|
||||||
#define _PyGILState_check_enabled _PyRuntime.gilstate.check_enabled
|
#define _PyGILState_check_enabled _PyRuntime.gilstate.check_enabled
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct _PyPathConfig {
|
||||||
/* Full path to the Python program */
|
/* Full path to the Python program */
|
||||||
wchar_t *program_full_path;
|
wchar_t *program_full_path;
|
||||||
wchar_t *prefix;
|
wchar_t *prefix;
|
||||||
|
@ -59,11 +59,15 @@ typedef struct {
|
||||||
|
|
||||||
PyAPI_DATA(_PyPathConfig) _Py_path_config;
|
PyAPI_DATA(_PyPathConfig) _Py_path_config;
|
||||||
|
|
||||||
PyAPI_FUNC(_PyInitError) _PyPathConfig_Calculate(
|
PyAPI_FUNC(_PyInitError) _PyPathConfig_Calculate_impl(
|
||||||
_PyPathConfig *config,
|
_PyPathConfig *config,
|
||||||
const _PyCoreConfig *core_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 */
|
/* interpreter state */
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,9 @@ PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *);
|
||||||
PyAPI_FUNC(int) _PyCoreConfig_Copy(
|
PyAPI_FUNC(int) _PyCoreConfig_Copy(
|
||||||
_PyCoreConfig *config,
|
_PyCoreConfig *config,
|
||||||
const _PyCoreConfig *config2);
|
const _PyCoreConfig *config2);
|
||||||
|
PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitPathConfig(_PyCoreConfig *config);
|
||||||
|
PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetPathConfig(
|
||||||
|
const _PyCoreConfig *config);
|
||||||
|
|
||||||
PyAPI_FUNC(_PyInitError) _PyMainInterpreterConfig_Read(
|
PyAPI_FUNC(_PyInitError) _PyMainInterpreterConfig_Read(
|
||||||
_PyMainInterpreterConfig *config,
|
_PyMainInterpreterConfig *config,
|
||||||
|
@ -116,7 +119,11 @@ PyAPI_FUNC(wchar_t *) Py_GetPrefix(void);
|
||||||
PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void);
|
PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void);
|
||||||
PyAPI_FUNC(wchar_t *) Py_GetPath(void);
|
PyAPI_FUNC(wchar_t *) Py_GetPath(void);
|
||||||
#ifdef Py_BUILD_CORE
|
#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(PyObject*) _PyPathConfig_ComputeArgv0(int argc, wchar_t **argv);
|
||||||
PyAPI_FUNC(int) _Py_FindEnvConfigValue(
|
PyAPI_FUNC(int) _Py_FindEnvConfigValue(
|
||||||
FILE *env_file,
|
FILE *env_file,
|
||||||
|
|
|
@ -71,6 +71,9 @@ typedef struct {
|
||||||
wchar_t *base_prefix; /* sys.base_prefix */
|
wchar_t *base_prefix; /* sys.base_prefix */
|
||||||
wchar_t *exec_prefix; /* sys.exec_prefix */
|
wchar_t *exec_prefix; /* sys.exec_prefix */
|
||||||
wchar_t *base_exec_prefix; /* sys.base_exec_prefix */
|
wchar_t *base_exec_prefix; /* sys.base_exec_prefix */
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
wchar_t *dll_path; /* Windows DLL path */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Private fields */
|
/* Private fields */
|
||||||
int _disable_importlib; /* Needed by freeze_importlib */
|
int _disable_importlib; /* Needed by freeze_importlib */
|
||||||
|
|
|
@ -946,7 +946,7 @@ calculate_path_impl(const _PyCoreConfig *core_config,
|
||||||
|
|
||||||
|
|
||||||
_PyInitError
|
_PyInitError
|
||||||
_PyPathConfig_Calculate(_PyPathConfig *config, const _PyCoreConfig *core_config)
|
_PyPathConfig_Calculate_impl(_PyPathConfig *config, const _PyCoreConfig *core_config)
|
||||||
{
|
{
|
||||||
PyCalculatePath calculate;
|
PyCalculatePath calculate;
|
||||||
memset(&calculate, 0, sizeof(calculate));
|
memset(&calculate, 0, sizeof(calculate));
|
||||||
|
|
139
Modules/main.c
139
Modules/main.c
|
@ -650,7 +650,7 @@ pymain_free_raw(_PyMain *pymain)
|
||||||
configuration options set before Py_Initialize() which should
|
configuration options set before Py_Initialize() which should
|
||||||
remain valid after Py_Finalize(), since
|
remain valid after Py_Finalize(), since
|
||||||
Py_Initialize()-Py_Finalize() can be called multiple times. */
|
Py_Initialize()-Py_Finalize() can be called multiple times. */
|
||||||
_PyPathConfig_Clear(&_Py_path_config);
|
_PyPathConfig_ClearGlobal();
|
||||||
|
|
||||||
pymain_clear_config(pymain);
|
pymain_clear_config(pymain);
|
||||||
|
|
||||||
|
@ -701,9 +701,13 @@ error:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static _PyInitError
|
_PyInitError
|
||||||
wstrlist_append(int *len, wchar_t ***list, const wchar_t *str)
|
_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);
|
wchar_t *str2 = _PyMem_RawWcsdup(str);
|
||||||
if (str2 == NULL) {
|
if (str2 == NULL) {
|
||||||
return _Py_INIT_NO_MEMORY();
|
return _Py_INIT_NO_MEMORY();
|
||||||
|
@ -725,7 +729,7 @@ wstrlist_append(int *len, wchar_t ***list, const wchar_t *str)
|
||||||
static int
|
static int
|
||||||
pymain_wstrlist_append(_PyMain *pymain, int *len, wchar_t ***list, const wchar_t *str)
|
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)) {
|
if (_Py_INIT_FAILED(err)) {
|
||||||
pymain->err = err;
|
pymain->err = err;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -972,9 +976,9 @@ static _PyInitError
|
||||||
config_add_warnings_optlist(_PyCoreConfig *config, int len, wchar_t **options)
|
config_add_warnings_optlist(_PyCoreConfig *config, int len, wchar_t **options)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
_PyInitError err = wstrlist_append(&config->nwarnoption,
|
_PyInitError err = _Py_wstrlist_append(&config->nwarnoption,
|
||||||
&config->warnoptions,
|
&config->warnoptions,
|
||||||
options[i]);
|
options[i]);
|
||||||
if (_Py_INIT_FAILED(err)) {
|
if (_Py_INIT_FAILED(err)) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1006,9 +1010,9 @@ config_init_warnoptions(_PyCoreConfig *config, _Py_CommandLineDetails *cmdline)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (config->dev_mode) {
|
if (config->dev_mode) {
|
||||||
err = wstrlist_append(&config->nwarnoption,
|
err = _Py_wstrlist_append(&config->nwarnoption,
|
||||||
&config->warnoptions,
|
&config->warnoptions,
|
||||||
L"default");
|
L"default");
|
||||||
if (_Py_INIT_FAILED(err)) {
|
if (_Py_INIT_FAILED(err)) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1040,9 +1044,9 @@ config_init_warnoptions(_PyCoreConfig *config, _Py_CommandLineDetails *cmdline)
|
||||||
else {
|
else {
|
||||||
filter = L"default::BytesWarning";
|
filter = L"default::BytesWarning";
|
||||||
}
|
}
|
||||||
err = wstrlist_append(&config->nwarnoption,
|
err = _Py_wstrlist_append(&config->nwarnoption,
|
||||||
&config->warnoptions,
|
&config->warnoptions,
|
||||||
filter);
|
filter);
|
||||||
if (_Py_INIT_FAILED(err)) {
|
if (_Py_INIT_FAILED(err)) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1077,9 +1081,9 @@ cmdline_init_env_warnoptions(_Py_CommandLineDetails *cmdline)
|
||||||
warning != NULL;
|
warning != NULL;
|
||||||
warning = WCSTOK(NULL, L",", &context))
|
warning = WCSTOK(NULL, L",", &context))
|
||||||
{
|
{
|
||||||
_PyInitError err = wstrlist_append(&cmdline->nenv_warnoption,
|
_PyInitError err = _Py_wstrlist_append(&cmdline->nenv_warnoption,
|
||||||
&cmdline->env_warnoptions,
|
&cmdline->env_warnoptions,
|
||||||
warning);
|
warning);
|
||||||
if (_Py_INIT_FAILED(err)) {
|
if (_Py_INIT_FAILED(err)) {
|
||||||
PyMem_RawFree(env);
|
PyMem_RawFree(env);
|
||||||
return err;
|
return err;
|
||||||
|
@ -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
|
/* Read configuration settings from standard locations
|
||||||
*
|
*
|
||||||
* This function doesn't make any changes to the interpreter state - it
|
* This function doesn't make any changes to the interpreter state - it
|
||||||
|
@ -2252,7 +2161,7 @@ _PyCoreConfig_Read(_PyCoreConfig *config)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config->_disable_importlib) {
|
if (!config->_disable_importlib) {
|
||||||
err = config_init_path_config(config);
|
err = _PyCoreConfig_InitPathConfig(config);
|
||||||
if (_Py_INIT_FAILED(err)) {
|
if (_Py_INIT_FAILED(err)) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -2294,6 +2203,9 @@ _PyCoreConfig_Clear(_PyCoreConfig *config)
|
||||||
CLEAR(config->prefix);
|
CLEAR(config->prefix);
|
||||||
CLEAR(config->base_prefix);
|
CLEAR(config->base_prefix);
|
||||||
CLEAR(config->exec_prefix);
|
CLEAR(config->exec_prefix);
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
CLEAR(config->dll_path);
|
||||||
|
#endif
|
||||||
CLEAR(config->base_exec_prefix);
|
CLEAR(config->base_exec_prefix);
|
||||||
#undef CLEAR
|
#undef CLEAR
|
||||||
#undef CLEAR_WSTRLIST
|
#undef CLEAR_WSTRLIST
|
||||||
|
@ -2356,6 +2268,9 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2)
|
||||||
COPY_STR_ATTR(prefix);
|
COPY_STR_ATTR(prefix);
|
||||||
COPY_STR_ATTR(base_prefix);
|
COPY_STR_ATTR(base_prefix);
|
||||||
COPY_STR_ATTR(exec_prefix);
|
COPY_STR_ATTR(exec_prefix);
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
COPY_STR_ATTR(dll_path);
|
||||||
|
#endif
|
||||||
COPY_STR_ATTR(base_exec_prefix);
|
COPY_STR_ATTR(base_exec_prefix);
|
||||||
|
|
||||||
#undef COPY_ATTR
|
#undef COPY_ATTR
|
||||||
|
|
|
@ -1000,7 +1000,7 @@ calculate_free(PyCalculatePath *calculate)
|
||||||
|
|
||||||
|
|
||||||
_PyInitError
|
_PyInitError
|
||||||
_PyPathConfig_Calculate(_PyPathConfig *config, const _PyCoreConfig *core_config)
|
_PyPathConfig_Calculate_impl(_PyPathConfig *config, const _PyCoreConfig *core_config)
|
||||||
{
|
{
|
||||||
PyCalculatePath calculate;
|
PyCalculatePath calculate;
|
||||||
memset(&calculate, 0, sizeof(calculate));
|
memset(&calculate, 0, sizeof(calculate));
|
||||||
|
|
|
@ -13,7 +13,23 @@ extern "C" {
|
||||||
_PyPathConfig _Py_path_config = _PyPathConfig_INIT;
|
_PyPathConfig _Py_path_config = _PyPathConfig_INIT;
|
||||||
|
|
||||||
|
|
||||||
void
|
static int
|
||||||
|
copy_wstr(wchar_t **dst, const wchar_t *src)
|
||||||
|
{
|
||||||
|
if (src != NULL) {
|
||||||
|
*dst = _PyMem_RawWcsdup(src);
|
||||||
|
if (*dst == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*dst = NULL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
_PyPathConfig_Clear(_PyPathConfig *config)
|
_PyPathConfig_Clear(_PyPathConfig *config)
|
||||||
{
|
{
|
||||||
/* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
|
/* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
|
||||||
|
@ -44,16 +60,11 @@ _PyPathConfig_Clear(_PyPathConfig *config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix()
|
/* Calculate the path configuration: initialize path_config from core_config */
|
||||||
and Py_GetProgramFullPath() */
|
static _PyInitError
|
||||||
_PyInitError
|
_PyPathConfig_Calculate(_PyPathConfig *path_config,
|
||||||
_PyPathConfig_Init(const _PyCoreConfig *core_config)
|
const _PyCoreConfig *core_config)
|
||||||
{
|
{
|
||||||
if (_Py_path_config.module_search_path) {
|
|
||||||
/* Already initialized */
|
|
||||||
return _Py_INIT_OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
_PyInitError err;
|
_PyInitError err;
|
||||||
_PyPathConfig new_config = _PyPathConfig_INIT;
|
_PyPathConfig new_config = _PyPathConfig_INIT;
|
||||||
|
|
||||||
|
@ -62,31 +73,67 @@ _PyPathConfig_Init(const _PyCoreConfig *core_config)
|
||||||
|
|
||||||
/* Calculate program_full_path, prefix, exec_prefix (Unix)
|
/* Calculate program_full_path, prefix, exec_prefix (Unix)
|
||||||
or dll_path (Windows), and module_search_path */
|
or dll_path (Windows), and module_search_path */
|
||||||
err = _PyPathConfig_Calculate(&new_config, core_config);
|
err = _PyPathConfig_Calculate_impl(&new_config, core_config);
|
||||||
if (_Py_INIT_FAILED(err)) {
|
if (_Py_INIT_FAILED(err)) {
|
||||||
_PyPathConfig_Clear(&new_config);
|
goto err;
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy home and program_name from core_config */
|
/* Copy home and program_name from core_config */
|
||||||
if (core_config->home != NULL) {
|
if (copy_wstr(&new_config.home, core_config->home) < 0) {
|
||||||
new_config.home = _PyMem_RawWcsdup(core_config->home);
|
err = _Py_INIT_NO_MEMORY();
|
||||||
if (new_config.home == NULL) {
|
goto err;
|
||||||
err = _Py_INIT_NO_MEMORY();
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
if (copy_wstr(&new_config.program_name, core_config->program_name) < 0) {
|
||||||
new_config.home = NULL;
|
err = _Py_INIT_NO_MEMORY();
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_config.program_name = _PyMem_RawWcsdup(core_config->program_name);
|
_PyPathConfig_Clear(path_config);
|
||||||
if (new_config.program_name == NULL) {
|
*path_config = new_config;
|
||||||
err = _Py_INIT_NO_MEMORY();
|
|
||||||
goto done;
|
err = _Py_INIT_OK();
|
||||||
}
|
goto done;
|
||||||
|
|
||||||
|
err:
|
||||||
|
_PyPathConfig_Clear(&new_config);
|
||||||
|
|
||||||
|
done:
|
||||||
|
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_PyInitError
|
||||||
|
_PyPathConfig_SetGlobal(const _PyPathConfig *config)
|
||||||
|
{
|
||||||
|
_PyInitError err;
|
||||||
|
_PyPathConfig new_config = _PyPathConfig_INIT;
|
||||||
|
|
||||||
|
PyMemAllocatorEx old_alloc;
|
||||||
|
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||||
|
|
||||||
|
#define COPY_ATTR(ATTR) \
|
||||||
|
do { \
|
||||||
|
if (copy_wstr(&new_config.ATTR, config->ATTR) < 0) { \
|
||||||
|
_PyPathConfig_Clear(&new_config); \
|
||||||
|
err = _Py_INIT_NO_MEMORY(); \
|
||||||
|
goto done; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
COPY_ATTR(program_full_path);
|
||||||
|
COPY_ATTR(prefix);
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
COPY_ATTR(dll_path);
|
||||||
|
#else
|
||||||
|
COPY_ATTR(exec_prefix);
|
||||||
|
#endif
|
||||||
|
COPY_ATTR(module_search_path);
|
||||||
|
COPY_ATTR(program_name);
|
||||||
|
COPY_ATTR(home);
|
||||||
|
|
||||||
_PyPathConfig_Clear(&_Py_path_config);
|
_PyPathConfig_Clear(&_Py_path_config);
|
||||||
|
/* Steal new_config strings; don't clear new_config */
|
||||||
_Py_path_config = new_config;
|
_Py_path_config = new_config;
|
||||||
|
|
||||||
err = _Py_INIT_OK();
|
err = _Py_INIT_OK();
|
||||||
|
@ -97,15 +144,228 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_PyPathConfig_ClearGlobal(void)
|
||||||
|
{
|
||||||
|
_PyPathConfig_Clear(&_Py_path_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static wchar_t*
|
||||||
|
wstrlist_join(wchar_t sep, int count, wchar_t **list)
|
||||||
|
{
|
||||||
|
size_t len = 1; /* NUL terminator */
|
||||||
|
for (int i=0; i < count; i++) {
|
||||||
|
if (i != 0) {
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
len += wcslen(list[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t *text = PyMem_RawMalloc(len * sizeof(wchar_t));
|
||||||
|
if (text == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
wchar_t *str = text;
|
||||||
|
for (int i=0; i < count; i++) {
|
||||||
|
wchar_t *path = list[i];
|
||||||
|
if (i != 0) {
|
||||||
|
*str++ = SEP;
|
||||||
|
}
|
||||||
|
len = wcslen(path);
|
||||||
|
memcpy(str, path, len * sizeof(wchar_t));
|
||||||
|
str += len;
|
||||||
|
}
|
||||||
|
*str = L'\0';
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Set the global path configuration from core_config. */
|
||||||
|
_PyInitError
|
||||||
|
_PyCoreConfig_SetPathConfig(const _PyCoreConfig *core_config)
|
||||||
|
{
|
||||||
|
PyMemAllocatorEx old_alloc;
|
||||||
|
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||||
|
|
||||||
|
_PyInitError err;
|
||||||
|
_PyPathConfig path_config = _PyPathConfig_INIT;
|
||||||
|
|
||||||
|
path_config.module_search_path = wstrlist_join(DELIM,
|
||||||
|
core_config->nmodule_search_path,
|
||||||
|
core_config->module_search_paths);
|
||||||
|
if (path_config.module_search_path == NULL) {
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copy_wstr(&path_config.program_full_path, core_config->executable) < 0) {
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
if (copy_wstr(&path_config.prefix, core_config->prefix) < 0) {
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
if (copy_wstr(&path_config.dll_path, core_config->dll_path) < 0) {
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (copy_wstr(&path_config.exec_prefix, core_config->exec_prefix) < 0) {
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (copy_wstr(&path_config.program_name, core_config->program_name) < 0) {
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
if (copy_wstr(&path_config.home, core_config->home) < 0) {
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = _PyPathConfig_SetGlobal(&path_config);
|
||||||
|
if (_Py_INIT_FAILED(err)) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = _Py_INIT_OK();
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
no_memory:
|
||||||
|
err = _Py_INIT_NO_MEMORY();
|
||||||
|
|
||||||
|
done:
|
||||||
|
_PyPathConfig_Clear(&path_config);
|
||||||
|
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static _PyInitError
|
||||||
|
core_config_init_module_search_paths(_PyCoreConfig *config,
|
||||||
|
_PyPathConfig *path_config)
|
||||||
|
{
|
||||||
|
assert(config->module_search_paths == NULL);
|
||||||
|
assert(config->nmodule_search_path < 0);
|
||||||
|
|
||||||
|
config->nmodule_search_path = 0;
|
||||||
|
|
||||||
|
const wchar_t *sys_path = path_config->module_search_path;
|
||||||
|
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 = _Py_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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_PyInitError
|
||||||
|
_PyCoreConfig_InitPathConfig(_PyCoreConfig *config)
|
||||||
|
{
|
||||||
|
_PyPathConfig path_config = _PyPathConfig_INIT;
|
||||||
|
_PyInitError err;
|
||||||
|
|
||||||
|
err = _PyPathConfig_Calculate(&path_config, config);
|
||||||
|
if (_Py_INIT_FAILED(err)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->nmodule_search_path < 0) {
|
||||||
|
err = core_config_init_module_search_paths(config, &path_config);
|
||||||
|
if (_Py_INIT_FAILED(err)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->executable == NULL) {
|
||||||
|
if (copy_wstr(&config->executable,
|
||||||
|
path_config.program_full_path) < 0) {
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->prefix == NULL) {
|
||||||
|
if (copy_wstr(&config->prefix, path_config.prefix) < 0) {
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->exec_prefix == NULL) {
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
wchar_t *exec_prefix = path_config.prefix;
|
||||||
|
#else
|
||||||
|
wchar_t *exec_prefix = path_config.exec_prefix;
|
||||||
|
#endif
|
||||||
|
if (copy_wstr(&config->exec_prefix, exec_prefix) < 0) {
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
if (config->dll_path == NULL) {
|
||||||
|
if (copy_wstr(&config->dll_path, path_config.dll_path) < 0) {
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (config->base_prefix == NULL) {
|
||||||
|
if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->base_exec_prefix == NULL) {
|
||||||
|
if (copy_wstr(&config->base_exec_prefix, config->exec_prefix) < 0) {
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_PyPathConfig_Clear(&path_config);
|
||||||
|
return _Py_INIT_OK();
|
||||||
|
|
||||||
|
no_memory:
|
||||||
|
err = _Py_INIT_NO_MEMORY();
|
||||||
|
|
||||||
|
error:
|
||||||
|
_PyPathConfig_Clear(&path_config);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pathconfig_global_init(void)
|
pathconfig_global_init(void)
|
||||||
{
|
{
|
||||||
if (_Py_path_config.module_search_path) {
|
if (_Py_path_config.module_search_path != NULL) {
|
||||||
/* Already initialized */
|
/* Already initialized */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_PyInitError err;
|
_PyInitError err;
|
||||||
|
_PyPathConfig path_config = _PyPathConfig_INIT;
|
||||||
_PyCoreConfig config = _PyCoreConfig_INIT;
|
_PyCoreConfig config = _PyCoreConfig_INIT;
|
||||||
|
|
||||||
err = _PyCoreConfig_Read(&config);
|
err = _PyCoreConfig_Read(&config);
|
||||||
|
@ -113,15 +373,22 @@ pathconfig_global_init(void)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = _PyPathConfig_Init(&config);
|
err = _PyPathConfig_Calculate(&path_config, &config);
|
||||||
if (_Py_INIT_FAILED(err)) {
|
if (_Py_INIT_FAILED(err)) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = _PyPathConfig_SetGlobal(&path_config);
|
||||||
|
if (_Py_INIT_FAILED(err)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
_PyPathConfig_Clear(&path_config);
|
||||||
_PyCoreConfig_Clear(&config);
|
_PyCoreConfig_Clear(&config);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
_PyPathConfig_Clear(&path_config);
|
||||||
_PyCoreConfig_Clear(&config);
|
_PyCoreConfig_Clear(&config);
|
||||||
_Py_FatalInitError(err);
|
_Py_FatalInitError(err);
|
||||||
}
|
}
|
||||||
|
@ -142,13 +409,18 @@ Py_SetPath(const wchar_t *path)
|
||||||
|
|
||||||
_PyPathConfig new_config;
|
_PyPathConfig new_config;
|
||||||
new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
|
new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
|
||||||
|
int alloc_error = (new_config.program_full_path == NULL);
|
||||||
new_config.prefix = _PyMem_RawWcsdup(L"");
|
new_config.prefix = _PyMem_RawWcsdup(L"");
|
||||||
|
alloc_error |= (new_config.prefix == NULL);
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
new_config.dll_path = _PyMem_RawWcsdup(L"");
|
new_config.dll_path = _PyMem_RawWcsdup(L"");
|
||||||
|
alloc_error |= (new_config.dll_path == NULL);
|
||||||
#else
|
#else
|
||||||
new_config.exec_prefix = _PyMem_RawWcsdup(L"");
|
new_config.exec_prefix = _PyMem_RawWcsdup(L"");
|
||||||
|
alloc_error |= (new_config.exec_prefix == NULL);
|
||||||
#endif
|
#endif
|
||||||
new_config.module_search_path = _PyMem_RawWcsdup(path);
|
new_config.module_search_path = _PyMem_RawWcsdup(path);
|
||||||
|
alloc_error |= (new_config.module_search_path == NULL);
|
||||||
|
|
||||||
/* steal the home and program_name values (to leave them unchanged) */
|
/* steal the home and program_name values (to leave them unchanged) */
|
||||||
new_config.home = _Py_path_config.home;
|
new_config.home = _Py_path_config.home;
|
||||||
|
@ -160,6 +432,10 @@ Py_SetPath(const wchar_t *path)
|
||||||
_Py_path_config = new_config;
|
_Py_path_config = new_config;
|
||||||
|
|
||||||
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||||
|
|
||||||
|
if (alloc_error) {
|
||||||
|
Py_FatalError("Py_SetPath() failed: out of memory");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -759,6 +759,13 @@ _Py_InitializeCore(const _PyCoreConfig *core_config)
|
||||||
if (!_PyContext_Init())
|
if (!_PyContext_Init())
|
||||||
return _Py_INIT_ERR("can't init context");
|
return _Py_INIT_ERR("can't init context");
|
||||||
|
|
||||||
|
if (!core_config->_disable_importlib) {
|
||||||
|
err = _PyCoreConfig_SetPathConfig(core_config);
|
||||||
|
if (_Py_INIT_FAILED(err)) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* This call sets up builtin and frozen import support */
|
/* This call sets up builtin and frozen import support */
|
||||||
if (!interp->core_config._disable_importlib) {
|
if (!interp->core_config._disable_importlib) {
|
||||||
err = initimport(interp, sysmod);
|
err = initimport(interp, sysmod);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue