bpo-36763: Use PyConfig_Clear() (GH-14445)

Stop using "static PyConfig", PyConfig must now always use
dynamically allocated strings: use PyConfig_SetString(),
PyConfig_SetArgv() and PyConfig_Clear().
This commit is contained in:
Victor Stinner 2019-07-01 19:52:45 +02:00 committed by GitHub
parent e6b64b756f
commit 67310023f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 151 additions and 186 deletions

View File

@ -695,10 +695,19 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'pycache_prefix': 'conf_pycache_prefix', 'pycache_prefix': 'conf_pycache_prefix',
'program_name': './conf_program_name', 'program_name': './conf_program_name',
'argv': ['-c', 'arg2'], 'argv': ['-c', 'arg2', ],
'parse_argv': 1, 'parse_argv': 1,
'xoptions': ['xoption1=3', 'xoption2=', 'xoption3'], 'xoptions': [
'warnoptions': ['error::ResourceWarning', 'default::BytesWarning'], 'config_xoption1=3',
'config_xoption2=',
'config_xoption3',
'cmdline_xoption',
],
'warnoptions': [
'config_warnoption',
'cmdline_warnoption',
'default::BytesWarning',
],
'run_command': 'pass\n', 'run_command': 'pass\n',
'site_import': 0, 'site_import': 0,

View File

@ -62,7 +62,7 @@ pymain_init(const _PyArgv *args)
PyConfig config; PyConfig config;
status = PyConfig_InitPythonConfig(&config); status = PyConfig_InitPythonConfig(&config);
if (_PyStatus_EXCEPTION(status)) { if (_PyStatus_EXCEPTION(status)) {
return status; goto done;
} }
/* pass NULL as the config: config is read from command line arguments, /* pass NULL as the config: config is read from command line arguments,
@ -74,14 +74,18 @@ pymain_init(const _PyArgv *args)
status = PyConfig_SetArgv(&config, args->argc, args->wchar_argv); status = PyConfig_SetArgv(&config, args->argc, args->wchar_argv);
} }
if (_PyStatus_EXCEPTION(status)) { if (_PyStatus_EXCEPTION(status)) {
return status; goto done;
} }
status = Py_InitializeFromConfig(&config); status = Py_InitializeFromConfig(&config);
if (_PyStatus_EXCEPTION(status)) { if (_PyStatus_EXCEPTION(status)) {
return status; goto done;
} }
return _PyStatus_OK(); status = _PyStatus_OK();
done:
PyConfig_Clear(&config);
return status;
} }

View File

@ -88,7 +88,7 @@ main(int argc, char *argv[])
config.site_import = 0; config.site_import = 0;
status = PyConfig_SetString(&config, &config.program_name, status = PyConfig_SetString(&config, &config.program_name,
L"./_freeze_importlib"); L"./_freeze_importlib");
if (PyStatus_Exception(status)) { if (PyStatus_Exception(status)) {
PyConfig_Clear(&config); PyConfig_Clear(&config);
Py_ExitStatusException(status); Py_ExitStatusException(status);

View File

@ -329,6 +329,56 @@ static int test_init_initialize_config(void)
} }
static void config_set_string(PyConfig *config, wchar_t **config_str, const wchar_t *str)
{
PyStatus status = PyConfig_SetString(config, config_str, str);
if (PyStatus_Exception(status)) {
PyConfig_Clear(config);
Py_ExitStatusException(status);
}
}
static void config_set_argv(PyConfig *config, Py_ssize_t argc, wchar_t * const *argv)
{
PyStatus status = PyConfig_SetArgv(config, argc, argv);
if (PyStatus_Exception(status)) {
PyConfig_Clear(config);
Py_ExitStatusException(status);
}
}
static void
config_set_wide_string_list(PyConfig *config, PyWideStringList *list,
Py_ssize_t length, wchar_t **items)
{
PyStatus status = PyConfig_SetWideStringList(config, list, length, items);
if (PyStatus_Exception(status)) {
PyConfig_Clear(config);
Py_ExitStatusException(status);
}
}
static void config_set_program_name(PyConfig *config)
{
/* Use path starting with "./" avoids a search along the PATH */
const wchar_t *program_name = L"./_testembed";
config_set_string(config, &config->program_name, program_name);
}
static void init_from_config_clear(PyConfig *config)
{
PyStatus status = Py_InitializeFromConfig(config);
PyConfig_Clear(config);
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}
}
static int check_init_compat_config(int preinit) static int check_init_compat_config(int preinit)
{ {
PyStatus status; PyStatus status;
@ -345,12 +395,8 @@ static int check_init_compat_config(int preinit)
PyConfig config; PyConfig config;
_PyConfig_InitCompatConfig(&config); _PyConfig_InitCompatConfig(&config);
config.program_name = L"./_testembed"; config_set_program_name(&config);
init_from_config_clear(&config);
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}
dump_config(); dump_config();
Py_Finalize(); Py_Finalize();
@ -438,7 +484,6 @@ static int test_init_from_config(void)
Py_ExitStatusException(status); Py_ExitStatusException(status);
} }
/* Test Py_InitializeFromConfig() */
PyConfig config; PyConfig config;
_PyConfig_InitCompatConfig(&config); _PyConfig_InitCompatConfig(&config);
config.install_signal_handlers = 0; config.install_signal_handlers = 0;
@ -468,34 +513,37 @@ static int test_init_from_config(void)
config.malloc_stats = 1; config.malloc_stats = 1;
putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix"); putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
config.pycache_prefix = L"conf_pycache_prefix"; config_set_string(&config, &config.pycache_prefix, L"conf_pycache_prefix");
Py_SetProgramName(L"./globalvar"); Py_SetProgramName(L"./globalvar");
config.program_name = L"./conf_program_name"; config_set_string(&config, &config.program_name, L"./conf_program_name");
static wchar_t* argv[] = { wchar_t* argv[] = {
L"python3", L"python3",
L"-W",
L"cmdline_warnoption",
L"-X",
L"cmdline_xoption",
L"-c", L"-c",
L"pass", L"pass",
L"arg2", L"arg2",
}; };
config.argv.length = Py_ARRAY_LENGTH(argv); config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
config.argv.items = argv;
config.parse_argv = 1; config.parse_argv = 1;
static wchar_t* xoptions[3] = { wchar_t* xoptions[3] = {
L"xoption1=3", L"config_xoption1=3",
L"xoption2=", L"config_xoption2=",
L"xoption3", L"config_xoption3",
}; };
config.xoptions.length = Py_ARRAY_LENGTH(xoptions); config_set_wide_string_list(&config, &config.xoptions,
config.xoptions.items = xoptions; Py_ARRAY_LENGTH(xoptions), xoptions);
static wchar_t* warnoptions[1] = { wchar_t* warnoptions[1] = {
L"error::ResourceWarning", L"config_warnoption",
}; };
config.warnoptions.length = Py_ARRAY_LENGTH(warnoptions); config_set_wide_string_list(&config, &config.warnoptions,
config.warnoptions.items = warnoptions; Py_ARRAY_LENGTH(warnoptions), warnoptions);
/* FIXME: test pythonpath_env */ /* FIXME: test pythonpath_env */
/* FIXME: test home */ /* FIXME: test home */
@ -544,22 +592,20 @@ static int test_init_from_config(void)
Force it to 0 through the config. */ Force it to 0 through the config. */
config.legacy_windows_stdio = 0; config.legacy_windows_stdio = 0;
#endif #endif
config.stdio_encoding = L"iso8859-1"; config_set_string(&config, &config.stdio_encoding, L"iso8859-1");
config.stdio_errors = L"replace"; config_set_string(&config, &config.stdio_errors, L"replace");
putenv("PYTHONNOUSERSITE="); putenv("PYTHONNOUSERSITE=");
Py_NoUserSiteDirectory = 0; Py_NoUserSiteDirectory = 0;
config.user_site_directory = 0; config.user_site_directory = 0;
config.check_hash_pycs_mode = L"always"; config_set_string(&config, &config.check_hash_pycs_mode, L"always");
Py_FrozenFlag = 0; Py_FrozenFlag = 0;
config.pathconfig_warnings = 0; config.pathconfig_warnings = 0;
status = Py_InitializeFromConfig(&config); init_from_config_clear(&config);
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}
dump_config(); dump_config();
Py_Finalize(); Py_Finalize();
return 0; return 0;
@ -576,7 +622,9 @@ static int check_init_parse_argv(int parse_argv)
Py_ExitStatusException(status); Py_ExitStatusException(status);
} }
static wchar_t* argv[] = { config.parse_argv = parse_argv;
wchar_t* argv[] = {
L"./argv0", L"./argv0",
L"-E", L"-E",
L"-c", L"-c",
@ -585,15 +633,9 @@ static int check_init_parse_argv(int parse_argv)
L"-v", L"-v",
L"arg3", L"arg3",
}; };
config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
init_from_config_clear(&config);
config.argv.length = Py_ARRAY_LENGTH(argv);
config.argv.items = argv;
config.parse_argv = parse_argv;
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}
dump_config(); dump_config();
Py_Finalize(); Py_Finalize();
return 0; return 0;
@ -664,12 +706,10 @@ static int test_init_python_env(void)
if (PyStatus_Exception(status)) { if (PyStatus_Exception(status)) {
Py_ExitStatusException(status); Py_ExitStatusException(status);
} }
config.program_name = L"./_testembed";
status = Py_InitializeFromConfig(&config); config_set_program_name(&config);
if (PyStatus_Exception(status)) { init_from_config_clear(&config);
Py_ExitStatusException(status);
}
dump_config(); dump_config();
Py_Finalize(); Py_Finalize();
return 0; return 0;
@ -723,14 +763,10 @@ static int test_init_isolated_flag(void)
Py_IsolatedFlag = 0; Py_IsolatedFlag = 0;
config.isolated = 1; config.isolated = 1;
/* Use path starting with "./" avoids a search along the PATH */ config_set_program_name(&config);
config.program_name = L"./_testembed";
set_all_env_vars(); set_all_env_vars();
status = Py_InitializeFromConfig(&config); init_from_config_clear(&config);
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}
dump_config(); dump_config();
Py_Finalize(); Py_Finalize();
return 0; return 0;
@ -753,13 +789,10 @@ static int test_preinit_isolated1(void)
PyConfig config; PyConfig config;
_PyConfig_InitCompatConfig(&config); _PyConfig_InitCompatConfig(&config);
config.program_name = L"./_testembed"; config_set_program_name(&config);
set_all_env_vars(); set_all_env_vars();
status = Py_InitializeFromConfig(&config); init_from_config_clear(&config);
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}
dump_config(); dump_config();
Py_Finalize(); Py_Finalize();
return 0; return 0;
@ -787,14 +820,10 @@ static int test_preinit_isolated2(void)
Py_IsolatedFlag = 0; Py_IsolatedFlag = 0;
config.isolated = 1; config.isolated = 1;
/* Use path starting with "./" avoids a search along the PATH */ config_set_program_name(&config);
config.program_name = L"./_testembed";
set_all_env_vars(); set_all_env_vars();
status = Py_InitializeFromConfig(&config); init_from_config_clear(&config);
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}
dump_config(); dump_config();
Py_Finalize(); Py_Finalize();
return 0; return 0;
@ -819,44 +848,28 @@ static int test_preinit_dont_parse_argv(void)
L"script.py"}; L"script.py"};
status = Py_PreInitializeFromArgs(&preconfig, Py_ARRAY_LENGTH(argv), argv); status = Py_PreInitializeFromArgs(&preconfig, Py_ARRAY_LENGTH(argv), argv);
if (PyStatus_Exception(status)) { if (PyStatus_Exception(status)) {
goto failed; Py_ExitStatusException(status);
} }
PyConfig config; PyConfig config;
status = PyConfig_InitIsolatedConfig(&config); status = PyConfig_InitIsolatedConfig(&config);
if (PyStatus_Exception(status)) { if (PyStatus_Exception(status)) {
goto failed; PyConfig_Clear(&config);
Py_ExitStatusException(status);
} }
config.isolated = 0; config.isolated = 0;
/* Pre-initialize implicitly using argv: make sure that -X dev /* Pre-initialize implicitly using argv: make sure that -X dev
is used to configure the allocation in preinitialization */ is used to configure the allocation in preinitialization */
status = PyConfig_SetArgv(&config, Py_ARRAY_LENGTH(argv), argv); config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
if (PyStatus_Exception(status)) { config_set_program_name(&config);
goto failed; init_from_config_clear(&config);
}
status = PyConfig_SetString(&config, &config.program_name,
L"./_testembed");
if (PyStatus_Exception(status)) {
goto failed;
}
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
goto failed;
}
PyConfig_Clear(&config);
dump_config(); dump_config();
Py_Finalize(); Py_Finalize();
return 0; return 0;
failed:
PyConfig_Clear(&config);
Py_ExitStatusException(status);
} }
@ -867,36 +880,20 @@ static int test_preinit_parse_argv(void)
status = PyConfig_InitPythonConfig(&config); status = PyConfig_InitPythonConfig(&config);
if (PyStatus_Exception(status)) { if (PyStatus_Exception(status)) {
goto failed; PyConfig_Clear(&config);
Py_ExitStatusException(status);
} }
/* Pre-initialize implicitly using argv: make sure that -X dev /* Pre-initialize implicitly using argv: make sure that -X dev
is used to configure the allocation in preinitialization */ is used to configure the allocation in preinitialization */
wchar_t *argv[] = {L"python3", L"-X", L"dev", L"script.py"}; wchar_t *argv[] = {L"python3", L"-X", L"dev", L"script.py"};
status = PyConfig_SetArgv(&config, Py_ARRAY_LENGTH(argv), argv); config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
if (PyStatus_Exception(status)) { config_set_program_name(&config);
goto failed; init_from_config_clear(&config);
}
status = PyConfig_SetString(&config, &config.program_name,
L"./_testembed");
if (PyStatus_Exception(status)) {
goto failed;
}
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
goto failed;
}
PyConfig_Clear(&config);
dump_config(); dump_config();
Py_Finalize(); Py_Finalize();
return 0; return 0;
failed:
PyConfig_Clear(&config);
Py_ExitStatusException(status);
} }
@ -955,13 +952,8 @@ static int check_preinit_isolated_config(int preinit)
PyConfig_Clear(&config); PyConfig_Clear(&config);
Py_ExitStatusException(status); Py_ExitStatusException(status);
} }
config.program_name = L"./_testembed"; config_set_program_name(&config);
init_from_config_clear(&config);
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
PyConfig_Clear(&config);
Py_ExitStatusException(status);
}
rt_preconfig = &_PyRuntime.preconfig; rt_preconfig = &_PyRuntime.preconfig;
assert(rt_preconfig->isolated == 1); assert(rt_preconfig->isolated == 1);
@ -1017,12 +1009,9 @@ static int check_init_python_config(int preinit)
if (PyStatus_Exception(status)) { if (PyStatus_Exception(status)) {
Py_ExitStatusException(status); Py_ExitStatusException(status);
} }
config.program_name = L"./_testembed"; config_set_program_name(&config);
init_from_config_clear(&config);
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}
dump_config(); dump_config();
Py_Finalize(); Py_Finalize();
return 0; return 0;
@ -1061,11 +1050,8 @@ static int test_init_dont_configure_locale(void)
if (PyStatus_Exception(status)) { if (PyStatus_Exception(status)) {
Py_ExitStatusException(status); Py_ExitStatusException(status);
} }
config.program_name = L"./_testembed"; config_set_program_name(&config);
status = Py_InitializeFromConfig(&config); init_from_config_clear(&config);
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}
dump_config(); dump_config();
Py_Finalize(); Py_Finalize();
@ -1084,11 +1070,9 @@ static int test_init_dev_mode(void)
putenv("PYTHONFAULTHANDLER="); putenv("PYTHONFAULTHANDLER=");
putenv("PYTHONMALLOC="); putenv("PYTHONMALLOC=");
config.dev_mode = 1; config.dev_mode = 1;
config.program_name = L"./_testembed"; config_set_program_name(&config);
status = Py_InitializeFromConfig(&config); init_from_config_clear(&config);
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}
dump_config(); dump_config();
Py_Finalize(); Py_Finalize();
return 0; return 0;
@ -1278,16 +1262,9 @@ static int test_init_read_set(void)
} }
/* override executable computed by PyConfig_Read() */ /* override executable computed by PyConfig_Read() */
status = PyConfig_SetString(&config, &config.executable, L"my_executable"); config_set_string(&config, &config.executable, L"my_executable");
if (PyStatus_Exception(status)) { init_from_config_clear(&config);
goto fail;
}
status = Py_InitializeFromConfig(&config);
PyConfig_Clear(&config);
if (PyStatus_Exception(status)) {
goto fail;
}
dump_config(); dump_config();
Py_Finalize(); Py_Finalize();
return 0; return 0;
@ -1297,19 +1274,18 @@ fail:
} }
wchar_t *init_main_argv[] = {
L"python3", L"-c",
(L"import _testinternalcapi, json; "
L"print(json.dumps(_testinternalcapi.get_configs()))"),
L"arg2"};
static void configure_init_main(PyConfig *config) static void configure_init_main(PyConfig *config)
{ {
config->argv.length = Py_ARRAY_LENGTH(init_main_argv); wchar_t* argv[] = {
config->argv.items = init_main_argv; L"python3", L"-c",
(L"import _testinternalcapi, json; "
L"print(json.dumps(_testinternalcapi.get_configs()))"),
L"arg2"};
config->parse_argv = 1; config->parse_argv = 1;
config->program_name = L"./python3";
config_set_argv(config, Py_ARRAY_LENGTH(argv), argv);
config_set_string(config, &config->program_name, L"./python3");
} }
@ -1322,11 +1298,7 @@ static int test_init_run_main(void)
Py_ExitStatusException(status); Py_ExitStatusException(status);
} }
configure_init_main(&config); configure_init_main(&config);
init_from_config_clear(&config);
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}
return Py_RunMain(); return Py_RunMain();
} }
@ -1343,11 +1315,7 @@ static int test_init_main(void)
} }
configure_init_main(&config); configure_init_main(&config);
config._init_main = 0; config._init_main = 0;
init_from_config_clear(&config);
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}
/* sys.stdout don't exist yet: it is created by _Py_InitializeMain() */ /* sys.stdout don't exist yet: it is created by _Py_InitializeMain() */
int res = PyRun_SimpleString( int res = PyRun_SimpleString(
@ -1374,35 +1342,19 @@ static int test_run_main(void)
status = PyConfig_InitPythonConfig(&config); status = PyConfig_InitPythonConfig(&config);
if (PyStatus_Exception(status)) { if (PyStatus_Exception(status)) {
goto failed; PyConfig_Clear(&config);
Py_ExitStatusException(status);
} }
wchar_t *argv[] = {L"python3", L"-c", wchar_t *argv[] = {L"python3", L"-c",
(L"import sys; " (L"import sys; "
L"print(f'Py_RunMain(): sys.argv={sys.argv}')"), L"print(f'Py_RunMain(): sys.argv={sys.argv}')"),
L"arg2"}; L"arg2"};
status = PyConfig_SetArgv(&config, Py_ARRAY_LENGTH(argv), argv); config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
if (PyStatus_Exception(status)) { config_set_string(&config, &config.program_name, L"./python3");
goto failed; init_from_config_clear(&config);
}
status = PyConfig_SetString(&config, &config.program_name,
L"./python3");
if (PyStatus_Exception(status)) {
goto failed;
}
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
goto failed;
}
PyConfig_Clear(&config);
return Py_RunMain(); return Py_RunMain();
failed:
PyConfig_Clear(&config);
Py_ExitStatusException(status);
} }