bpo-45445: Revert "bpo-45445: Fail if an invalid X-option is provided in the command line (GH-28823)" (#94745)

This commit is contained in:
Pablo Galindo Salgado 2022-07-31 16:33:56 +01:00 committed by GitHub
parent 50b2261bda
commit aa37ffda29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 27 additions and 83 deletions

View File

@ -1780,13 +1780,13 @@ always available.
.. code-block:: shell-session .. code-block:: shell-session
$ ./python -Xpycache_prefix=some_path -Xdev $ ./python -Xa=b -Xc
Python 3.2a3+ (py3k, Oct 16 2010, 20:14:50) Python 3.2a3+ (py3k, Oct 16 2010, 20:14:50)
[GCC 4.4.3] on linux2 [GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information. Type "help", "copyright", "credits" or "license" for more information.
>>> import sys >>> import sys
>>> sys._xoptions >>> sys._xoptions
{'pycache_prefix': 'some_path', 'dev': True} {'a': 'b', 'c': True}
.. impl-detail:: .. impl-detail::

View File

@ -20,7 +20,7 @@ class AuditTest(unittest.TestCase):
@support.requires_subprocess() @support.requires_subprocess()
def do_test(self, *args): def do_test(self, *args):
with subprocess.Popen( with subprocess.Popen(
[sys.executable, "-Xutf8", AUDIT_TESTS_PY, *args], [sys.executable, "-X utf8", AUDIT_TESTS_PY, *args],
encoding="utf-8", encoding="utf-8",
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stderr=subprocess.PIPE,
@ -35,7 +35,7 @@ class AuditTest(unittest.TestCase):
def run_python(self, *args): def run_python(self, *args):
events = [] events = []
with subprocess.Popen( with subprocess.Popen(
[sys.executable, "-Xutf8", AUDIT_TESTS_PY, *args], [sys.executable, "-X utf8", AUDIT_TESTS_PY, *args],
encoding="utf-8", encoding="utf-8",
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stderr=subprocess.PIPE,

View File

@ -105,17 +105,8 @@ class CmdLineTest(unittest.TestCase):
opts = get_xoptions() opts = get_xoptions()
self.assertEqual(opts, {}) self.assertEqual(opts, {})
opts = get_xoptions('-Xno_debug_ranges', '-Xdev=1234') opts = get_xoptions('-Xa', '-Xb=c,d=e')
self.assertEqual(opts, {'no_debug_ranges': True, 'dev': '1234'}) self.assertEqual(opts, {'a': True, 'b': 'c,d=e'})
@unittest.skipIf(interpreter_requires_environment(),
'Cannot run -E tests when PYTHON env vars are required.')
def test_unknown_xoptions(self):
rc, out, err = assert_python_failure('-X', 'blech')
self.assertIn(b'Unknown value for option -X', err)
msg = b'Fatal Python error: Unknown value for option -X (see --help-xoptions)'
self.assertEqual(err.splitlines().count(msg), 1)
self.assertEqual(b'', out)
def test_showrefcount(self): def test_showrefcount(self):
def run_python(*args): def run_python(*args):

View File

@ -283,7 +283,7 @@ class EmbeddingTests(EmbeddingTestsMixin, unittest.TestCase):
"test_pre_initialization_sys_options", env=env) "test_pre_initialization_sys_options", env=env)
expected_output = ( expected_output = (
"sys.warnoptions: ['once', 'module', 'default']\n" "sys.warnoptions: ['once', 'module', 'default']\n"
"sys._xoptions: {'dev': '2', 'utf8': '1'}\n" "sys._xoptions: {'not_an_option': '1', 'also_not_an_option': '2'}\n"
"warnings.filters[:3]: ['default', 'module', 'once']\n" "warnings.filters[:3]: ['default', 'module', 'once']\n"
) )
self.assertIn(expected_output, out) self.assertIn(expected_output, out)
@ -841,14 +841,15 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'argv': ['-c', 'arg2'], 'argv': ['-c', 'arg2'],
'orig_argv': ['python3', 'orig_argv': ['python3',
'-W', 'cmdline_warnoption', '-W', 'cmdline_warnoption',
'-X', 'dev', '-X', 'cmdline_xoption',
'-c', 'pass', '-c', 'pass',
'arg2'], 'arg2'],
'parse_argv': 2, 'parse_argv': 2,
'xoptions': [ 'xoptions': [
'dev=3', 'config_xoption1=3',
'utf8', 'config_xoption2=',
'dev', 'config_xoption3',
'cmdline_xoption',
], ],
'warnoptions': [ 'warnoptions': [
'cmdline_warnoption', 'cmdline_warnoption',
@ -1076,8 +1077,9 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
config = { config = {
'faulthandler': 1, 'faulthandler': 1,
'xoptions': [ 'xoptions': [
'dev', 'config_xoption',
'utf8', 'cmdline_xoption',
'sysadd_xoption',
'faulthandler', 'faulthandler',
], ],
'warnoptions': [ 'warnoptions': [
@ -1087,12 +1089,9 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
], ],
'orig_argv': ['python3', 'orig_argv': ['python3',
'-W', 'ignore:::cmdline_warnoption', '-W', 'ignore:::cmdline_warnoption',
'-X', 'utf8'], '-X', 'cmdline_xoption'],
} }
preconfig = {'utf8_mode': 1} self.check_all_configs("test_init_sys_add", config, api=API_PYTHON)
self.check_all_configs("test_init_sys_add", config,
expected_preconfig=preconfig,
api=API_PYTHON)
def test_init_run_main(self): def test_init_run_main(self):
code = ('import _testinternalcapi, json; ' code = ('import _testinternalcapi, json; '

View File

@ -279,7 +279,7 @@ static int test_pre_initialization_sys_options(void)
* relying on the caller to keep the passed in strings alive. * relying on the caller to keep the passed in strings alive.
*/ */
const wchar_t *static_warnoption = L"once"; const wchar_t *static_warnoption = L"once";
const wchar_t *static_xoption = L"utf8=1"; const wchar_t *static_xoption = L"also_not_an_option=2";
size_t warnoption_len = wcslen(static_warnoption); size_t warnoption_len = wcslen(static_warnoption);
size_t xoption_len = wcslen(static_xoption); size_t xoption_len = wcslen(static_xoption);
wchar_t *dynamic_once_warnoption = \ wchar_t *dynamic_once_warnoption = \
@ -298,7 +298,7 @@ static int test_pre_initialization_sys_options(void)
PySys_AddWarnOption(L"module"); PySys_AddWarnOption(L"module");
PySys_AddWarnOption(L"default"); PySys_AddWarnOption(L"default");
_Py_EMBED_PREINIT_CHECK("Checking PySys_AddXOption\n"); _Py_EMBED_PREINIT_CHECK("Checking PySys_AddXOption\n");
PySys_AddXOption(L"dev=2"); PySys_AddXOption(L"not_an_option=1");
PySys_AddXOption(dynamic_xoption); PySys_AddXOption(dynamic_xoption);
/* Delete the dynamic options early */ /* Delete the dynamic options early */
@ -591,7 +591,7 @@ static int test_init_from_config(void)
L"-W", L"-W",
L"cmdline_warnoption", L"cmdline_warnoption",
L"-X", L"-X",
L"dev", L"cmdline_xoption",
L"-c", L"-c",
L"pass", L"pass",
L"arg2", L"arg2",
@ -599,9 +599,10 @@ static int test_init_from_config(void)
config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv); config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
config.parse_argv = 1; config.parse_argv = 1;
wchar_t* xoptions[2] = { wchar_t* xoptions[3] = {
L"dev=3", L"config_xoption1=3",
L"utf8", L"config_xoption2=",
L"config_xoption3",
}; };
config_set_wide_string_list(&config, &config.xoptions, config_set_wide_string_list(&config, &config.xoptions,
Py_ARRAY_LENGTH(xoptions), xoptions); Py_ARRAY_LENGTH(xoptions), xoptions);
@ -1425,6 +1426,7 @@ fail:
static int test_init_sys_add(void) static int test_init_sys_add(void)
{ {
PySys_AddXOption(L"sysadd_xoption");
PySys_AddXOption(L"faulthandler"); PySys_AddXOption(L"faulthandler");
PySys_AddWarnOption(L"ignore:::sysadd_warnoption"); PySys_AddWarnOption(L"ignore:::sysadd_warnoption");
@ -1436,14 +1438,14 @@ static int test_init_sys_add(void)
L"-W", L"-W",
L"ignore:::cmdline_warnoption", L"ignore:::cmdline_warnoption",
L"-X", L"-X",
L"utf8", L"cmdline_xoption",
}; };
config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv); config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
config.parse_argv = 1; config.parse_argv = 1;
PyStatus status; PyStatus status;
status = PyWideStringList_Append(&config.xoptions, status = PyWideStringList_Append(&config.xoptions,
L"dev"); L"config_xoption");
if (PyStatus_Exception(status)) { if (PyStatus_Exception(status)) {
goto fail; goto fail;
} }

View File

@ -2061,49 +2061,6 @@ _PyConfig_InitImportConfig(PyConfig *config)
return config_init_import(config, 1); return config_init_import(config, 1);
} }
// List of known xoptions to validate against the provided ones. Note that all
// options are listed, even if they are only available if a specific macro is
// set, like -X showrefcount which requires a debug build. In this case unknown
// options are silently ignored.
const wchar_t* known_xoptions[] = {
L"faulthandler",
L"showrefcount",
L"tracemalloc",
L"importtime",
L"dev",
L"utf8",
L"pycache_prefix",
L"warn_default_encoding",
L"no_debug_ranges",
L"frozen_modules",
NULL,
};
static const wchar_t*
_Py_check_xoptions(const PyWideStringList *xoptions, const wchar_t **names)
{
for (Py_ssize_t i=0; i < xoptions->length; i++) {
const wchar_t *option = xoptions->items[i];
size_t len;
wchar_t *sep = wcschr(option, L'=');
if (sep != NULL) {
len = (sep - option);
}
else {
len = wcslen(option);
}
int found = 0;
for (const wchar_t** name = names; *name != NULL; name++) {
if (wcsncmp(option, *name, len) == 0 && (*name)[len] == L'\0') {
found = 1;
}
}
if (found == 0) {
return option;
}
}
return NULL;
}
static PyStatus static PyStatus
config_read(PyConfig *config, int compute_path_config) config_read(PyConfig *config, int compute_path_config)
@ -2119,11 +2076,6 @@ config_read(PyConfig *config, int compute_path_config)
} }
/* -X options */ /* -X options */
const wchar_t* option = _Py_check_xoptions(&config->xoptions, known_xoptions);
if (option != NULL) {
return PyStatus_Error("Unknown value for option -X (see --help-xoptions)");
}
if (config_get_xoption(config, L"showrefcount")) { if (config_get_xoption(config, L"showrefcount")) {
config->show_ref_count = 1; config->show_ref_count = 1;
} }