Skip to content

Commit 33bf9dc

Browse files
committed
fixup! Fail if an invalid X-option is provided in the command line
1 parent 4b7ea77 commit 33bf9dc

File tree

7 files changed

+50
-51
lines changed

7 files changed

+50
-51
lines changed

Include/internal/pycore_initconfig.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,6 @@ PyAPI_FUNC(int) _Py_str_to_int(
8282
PyAPI_FUNC(const wchar_t*) _Py_get_xoption(
8383
const PyWideStringList *xoptions,
8484
const wchar_t *name);
85-
PyAPI_FUNC(const wchar_t*) _Py_check_xoptions(
86-
const PyWideStringList *xoptions,
87-
const wchar_t **name);
8885
PyAPI_FUNC(const char*) _Py_GetEnv(
8986
int use_environment,
9087
const char *name);

Lib/test/test_audit.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
class AuditTest(unittest.TestCase):
1919
def do_test(self, *args):
2020
with subprocess.Popen(
21-
[sys.executable, "-X utf8", AUDIT_TESTS_PY, *args],
21+
[sys.executable, "-Xutf8", AUDIT_TESTS_PY, *args],
2222
encoding="utf-8",
2323
stdout=subprocess.PIPE,
2424
stderr=subprocess.PIPE,
@@ -32,7 +32,7 @@ def do_test(self, *args):
3232
def run_python(self, *args):
3333
events = []
3434
with subprocess.Popen(
35-
[sys.executable, "-X utf8", AUDIT_TESTS_PY, *args],
35+
[sys.executable, "-Xutf8", AUDIT_TESTS_PY, *args],
3636
encoding="utf-8",
3737
stdout=subprocess.PIPE,
3838
stderr=subprocess.PIPE,

Lib/test/test_embed.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ def test_pre_initialization_sys_options(self):
274274
"test_pre_initialization_sys_options", env=env)
275275
expected_output = (
276276
"sys.warnoptions: ['once', 'module', 'default']\n"
277-
"sys._xoptions: {'not_an_option': '1', 'also_not_an_option': '2'}\n"
277+
"sys._xoptions: {'dev': '2', 'utf8': '1'}\n"
278278
"warnings.filters[:3]: ['default', 'module', 'once']\n"
279279
)
280280
self.assertIn(expected_output, out)
@@ -822,15 +822,14 @@ def test_init_from_config(self):
822822
'argv': ['-c', 'arg2'],
823823
'orig_argv': ['python3',
824824
'-W', 'cmdline_warnoption',
825-
'-X', 'cmdline_xoption',
825+
'-X', 'dev',
826826
'-c', 'pass',
827827
'arg2'],
828828
'parse_argv': 2,
829829
'xoptions': [
830-
'config_xoption1=3',
831-
'config_xoption2=',
832-
'config_xoption3',
833-
'cmdline_xoption',
830+
'dev=3',
831+
'utf8',
832+
'dev',
834833
],
835834
'warnoptions': [
836835
'cmdline_warnoption',
@@ -1048,9 +1047,8 @@ def test_init_sys_add(self):
10481047
config = {
10491048
'faulthandler': 1,
10501049
'xoptions': [
1051-
'config_xoption',
1052-
'cmdline_xoption',
1053-
'sysadd_xoption',
1050+
'dev',
1051+
'utf8',
10541052
'faulthandler',
10551053
],
10561054
'warnoptions': [
@@ -1060,9 +1058,12 @@ def test_init_sys_add(self):
10601058
],
10611059
'orig_argv': ['python3',
10621060
'-W', 'ignore:::cmdline_warnoption',
1063-
'-X', 'cmdline_xoption'],
1061+
'-X', 'utf8'],
10641062
}
1065-
self.check_all_configs("test_init_sys_add", config, api=API_PYTHON)
1063+
preconfig = {'utf8_mode': 1}
1064+
self.check_all_configs("test_init_sys_add", config,
1065+
expected_preconfig=preconfig,
1066+
api=API_PYTHON)
10661067

10671068
def test_init_run_main(self):
10681069
code = ('import _testinternalcapi, json; '
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Python now fails to initialize if an invalid :option:`-X` option in the
2+
command line. Patch by Pablo Galindo.

Programs/_testembed.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ static int test_pre_initialization_sys_options(void)
211211
* relying on the caller to keep the passed in strings alive.
212212
*/
213213
const wchar_t *static_warnoption = L"once";
214-
const wchar_t *static_xoption = L"also_not_an_option=2";
214+
const wchar_t *static_xoption = L"utf8=1";
215215
size_t warnoption_len = wcslen(static_warnoption);
216216
size_t xoption_len = wcslen(static_xoption);
217217
wchar_t *dynamic_once_warnoption = \
@@ -230,7 +230,7 @@ static int test_pre_initialization_sys_options(void)
230230
PySys_AddWarnOption(L"module");
231231
PySys_AddWarnOption(L"default");
232232
_Py_EMBED_PREINIT_CHECK("Checking PySys_AddXOption\n");
233-
PySys_AddXOption(L"not_an_option=1");
233+
PySys_AddXOption(L"dev=2");
234234
PySys_AddXOption(dynamic_xoption);
235235

236236
/* Delete the dynamic options early */
@@ -548,18 +548,17 @@ static int test_init_from_config(void)
548548
L"-W",
549549
L"cmdline_warnoption",
550550
L"-X",
551-
L"cmdline_xoption",
551+
L"dev",
552552
L"-c",
553553
L"pass",
554554
L"arg2",
555555
};
556556
config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
557557
config.parse_argv = 1;
558558

559-
wchar_t* xoptions[3] = {
560-
L"config_xoption1=3",
561-
L"config_xoption2=",
562-
L"config_xoption3",
559+
wchar_t* xoptions[2] = {
560+
L"dev=3",
561+
L"utf8",
563562
};
564563
config_set_wide_string_list(&config, &config.xoptions,
565564
Py_ARRAY_LENGTH(xoptions), xoptions);
@@ -1375,7 +1374,6 @@ static int test_init_read_set(void)
13751374

13761375
static int test_init_sys_add(void)
13771376
{
1378-
PySys_AddXOption(L"sysadd_xoption");
13791377
PySys_AddXOption(L"faulthandler");
13801378
PySys_AddWarnOption(L"ignore:::sysadd_warnoption");
13811379

@@ -1387,14 +1385,14 @@ static int test_init_sys_add(void)
13871385
L"-W",
13881386
L"ignore:::cmdline_warnoption",
13891387
L"-X",
1390-
L"cmdline_xoption",
1388+
L"utf8",
13911389
};
13921390
config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
13931391
config.parse_argv = 1;
13941392

13951393
PyStatus status;
13961394
status = PyWideStringList_Append(&config.xoptions,
1397-
L"config_xoption");
1395+
L"dev");
13981396
if (PyStatus_Exception(status)) {
13991397
goto fail;
14001398
}

Python/initconfig.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2135,6 +2135,32 @@ const wchar_t* known_xoptions[] = {
21352135
NULL,
21362136
};
21372137

2138+
static const wchar_t*
2139+
_Py_check_xoptions(const PyWideStringList *xoptions, const wchar_t **names)
2140+
{
2141+
for (Py_ssize_t i=0; i < xoptions->length; i++) {
2142+
const wchar_t *option = xoptions->items[i];
2143+
size_t len;
2144+
wchar_t *sep = wcschr(option, L'=');
2145+
if (sep != NULL) {
2146+
len = (sep - option);
2147+
}
2148+
else {
2149+
len = wcslen(option);
2150+
}
2151+
int found = 0;
2152+
for (const wchar_t** name = names; *name != NULL; name++) {
2153+
if (wcsncmp(option, *name, len) == 0 && (*name)[len] == L'\0') {
2154+
found = 1;
2155+
}
2156+
}
2157+
if (found == 0) {
2158+
return option;
2159+
}
2160+
}
2161+
return NULL;
2162+
}
2163+
21382164
static PyStatus
21392165
config_read(PyConfig *config, int compute_path_config)
21402166
{

Python/preconfig.c

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -593,31 +593,6 @@ _Py_get_xoption(const PyWideStringList *xoptions, const wchar_t *name)
593593
return NULL;
594594
}
595595

596-
const wchar_t*
597-
_Py_check_xoptions(const PyWideStringList *xoptions, const wchar_t **names)
598-
{
599-
for (Py_ssize_t i=0; i < xoptions->length; i++) {
600-
const wchar_t *option = xoptions->items[i];
601-
size_t len;
602-
wchar_t *sep = wcschr(option, L'=');
603-
if (sep != NULL) {
604-
len = (sep - option);
605-
}
606-
else {
607-
len = wcslen(option);
608-
}
609-
int found = 0;
610-
for (const wchar_t** name = names; *name != NULL; name++) {
611-
if (wcsncmp(option, *name, len) == 0 && (*name)[len] == L'\0') {
612-
found = 1;
613-
}
614-
}
615-
if (found == 0) {
616-
return option;
617-
}
618-
}
619-
return NULL;
620-
}
621596

622597
static PyStatus
623598
preconfig_init_utf8_mode(PyPreConfig *config, const _PyPreCmdline *cmdline)

0 commit comments

Comments
 (0)