8000 bpo-45445: Fail if an invalid X-option is provided in the command line by pablogsal · Pull Request #28823 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-45445: Fail if an invalid X-option is provided in the command line #28823

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
Oct 13, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
fixup! Fail if an invalid X-option is provided in the command line
  • Loading branch information
pablogsal committed Oct 12, 2021
commit 33bf9dc3a9a357aa602c65e6c9ca52d354fe6090
3 changes: 0 additions & 3 deletions Include/internal/pycore_initconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,6 @@ PyAPI_FUNC(int) _Py_str_to_int(
PyAPI_FUNC(const wchar_t*) _Py_get_xoption(
const PyWideStringList *xoptions,
const wchar_t *name);
PyAPI_FUNC(const wchar_t*) _Py_check_xoptions(
const PyWideStringList *xoptions,
const wchar_t **name);
PyAPI_FUNC(const char*) _Py_GetEnv(
int use_environment,
const char *name);
Expand Down
4 changes: 2 additions & 2 deletions Lib/test/test_audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
class AuditTest(unittest.TestCase):
def do_test(self, *args):
with subprocess.Popen(
[sys.executable, "-X utf8", AUDIT_TESTS_PY, *args],
[sys.executable, "-Xutf8", AUDIT_TESTS_PY, *args],
Copy link
Member Author
@pablogsal pablogsal Oct 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bonus! This was a bug because the Xoption was provided as utf8 (with space) and not utf8 so it was silently ignored :(

@vstinner @zooba

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, or you can write "-X", "utf8". I suppose that both work.

encoding="utf-8",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
Expand All @@ -32,7 +32,7 @@ def do_test(self, *args):
def run_python(self, *args):
events = []
with subprocess.Popen(
[sys.executable, "-X utf8", AUDIT_TESTS_PY, *args],
[sys.executable, "-Xutf8", AUDIT_TESTS_PY, *args],
encoding="utf-8",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
Expand Down
23 changes: 12 additions & 11 deletions Lib/test/test_embed.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ def test_pre_initialization_sys_options(self):
"test_pre_initialization_sys_options", env=env)
expected_output = (
"sys.warnoptions: ['once', 'module', 'default']\n"
"sys._xoptions: {'not_an_option': '1', 'also_not_an_option': '2'}\n"
"sys._xoptions: {'dev': '2', 'utf8': '1'}\n"
"warnings.filters[:3]: ['default', 'module', 'once']\n"
)
self.assertIn(expected_output, out)
Expand Down Expand Up @@ -822,15 +822,14 @@ def test_init_from_config(self):
'argv': ['-c', 'arg2'],
'orig_argv': ['python3',
'-W', 'cmdline_warnoption',
'-X', 'cmdline_xoption',
'-X', 'dev',
'-c', 'pass',
'arg2'],
'parse_argv': 2,
'xoptions': [
'config_xoption1=3',
'config_xoption2=',
'config_xoption3',
'cmdline_xoption',
'dev=3',
'utf8',
'dev',
],
'warnoptions': [
'cmdline_warnoption',
Expand Down Expand Up @@ -1048,9 +1047,8 @@ def test_init_sys_add(self):
config = {
'faulthandler': 1,
'xoptions': [
'config_xoption',
'cmdline_xoption',
'sysadd_xoption',
'dev',
'utf8',
'faulthandler',
],
'warnoptions': [
Expand All @@ -1060,9 +1058,12 @@ def test_init_sys_add(self):
],
'orig_argv': ['python3',
'-W', 'ignore:::cmdline_warnoption',
'-X', 'cmdline_xoption'],
'-X', 'utf8'],
}
self.check_all_configs("test_init_sys_add", config, api=API_PYTHON)
preconfig = {'utf8_mode': 1}
self.check_all_configs("test_init_sys_add", config,
expected_preconfig=preconfig,
api=API_PYTHON)

def test_init_run_main(self):
code = ('import _testinternalcapi, json; '
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Python now fails to initialize if an invalid :option:`-X` option in the
command line. Patch by Pablo Galindo.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if... what? :-)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, thanks for the fix :-)

18 changes: 8 additions & 10 deletions Programs/_testembed.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ static int test_pre_initialization_sys_options(void)
* relying on the caller to keep the passed in strings alive.
*/
const wchar_t *static_warnoption = L"once";
const wchar_t *static_xoption = L"also_not_an_option=2";
const wchar_t *static_xoption = L"utf8=1";
size_t warnoption_len = wcslen(static_warnoption);
size_t xoption_len = wcslen(static_xoption);
wchar_t *dynamic_once_warnoption = \
Expand All @@ -230,7 +230,7 @@ static int test_pre_initialization_sys_options(void)
PySys_AddWarnOption(L"module");
PySys_AddWarnOption(L"default");
_Py_EMBED_PREINIT_CHECK("Checking PySys_AddXOption\n");
PySys_AddXOption(L"not_an_option=1");
PySys_AddXOption(L"dev=2");
PySys_AddXOption(dynamic_xoption);

/* Delete the dynamic options early */
Expand Down Expand Up @@ -548,18 +548,17 @@ static int test_init_from_config(void)
L"-W",
L"cmdline_warnoption",
L"-X",
L"cmdline_xoption",
L"dev",
L"-c",
L"pass",
L"arg2",
};
config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
config.parse_argv = 1;

wchar_t* xoptions[3] = {
L"config_xoption1=3",
L"config_xoption2=",
L"config_xoption3",
wchar_t* xoptions[2] = {
L"dev=3",
L"utf8",
};
config_set_wide_string_list(&config, &config.xoptions,
Py_ARRAY_LENGTH(xoptions), xoptions);
Expand Down Expand Up @@ -1375,7 +1374,6 @@ static int test_init_read_set(void)

static int test_init_sys_add(void)
{
PySys_AddXOption(L"sysadd_xoption");
PySys_AddXOption(L"faulthandler");
PySys_AddWarnOption(L"ignore:::sysadd_warnoption");

Expand All @@ -1387,14 +1385,14 @@ static int test_init_sys_add(void)
L"-W",
L"ignore:::cmdline_warnoption",
L"-X",
L"cmdline_xoption",
L"utf8",
};
config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
config.parse_argv = 1;

PyStatus status;
status = PyWideStringList_Append(&config.xoptions,
L"config_xoption");
L"dev");
if (PyStatus_Exception(status)) {
goto fail;
}
Expand Down
26 changes: 26 additions & 0 deletions Python/initconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -2135,6 +2135,32 @@ const wchar_t* known_xoptions[] = {
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
config_read(PyConfig *config, int compute_path_config)
{
Expand Down
25 changes: 0 additions & 25 deletions Python/preconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,31 +593,6 @@ _Py_get_xoption(const PyWideStringList *xoptions, const wchar_t *name)
return NULL;
}

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
preconfig_init_utf8_mode(PyPreConfig *config, const _PyPreCmdline *cmdline)
Expand Down
0