Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5f161fd

Browse files
bpo-30184: Add tests for invalid use of PyArg_ParseTupleAndKeywords. (#1316)
1 parent feec3dc commit 5f161fd

2 files changed

Lines changed: 43 additions & 20 deletions

File tree

Lib/test/test_capi.py

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -490,9 +490,8 @@ def test_skipitem(self):
490490
# test the format unit when not skipped
491491
format = c + "i"
492492
try:
493-
# (note: the format string must be bytes!)
494493
_testcapi.parse_tuple_and_keywords(tuple_1, dict_b,
495-
format.encode("ascii"), keywords)
494+
format, keywords)
496495
when_not_skipped = False
497496
except SystemError as e:
498497
s = "argument 1 (impossible<bad format char>)"
@@ -504,7 +503,7 @@ def test_skipitem(self):
504503
optional_format = "|" + format
505504
try:
506505
_testcapi.parse_tuple_and_keywords(empty_tuple, dict_b,
507-
optional_format.encode("ascii"), keywords)
506+
optional_format, keywords)
508507
when_skipped = False
509508
except SystemError as e:
510509
s = "impossible<bad format char>: '{}'".format(format)
@@ -517,40 +516,64 @@ def test_skipitem(self):
517516
self.assertIs(when_skipped, when_not_skipped, message)
518517

519518
def test_parse_tuple_and_keywords(self):
520-
# parse_tuple_and_keywords error handling tests
519+
# Test handling errors in the parse_tuple_and_keywords helper itself
521520
self.assertRaises(TypeError, _testcapi.parse_tuple_and_keywords,
522521
(), {}, 42, [])
523522
self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
524-
(), {}, b'', 42)
523+
(), {}, '', 42)
525524
self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
526-
(), {}, b'', [''] * 42)
525+
(), {}, '', [''] * 42)
527526
self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
528-
(), {}, b'', [42])
527+
(), {}, '', [42])
528+
529+
def test_bad_use(self):
530+
# Test handling invalid format and keywords in
531+
# PyArg_ParseTupleAndKeywords()
532+
self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
533+
(1,), {}, '||O', ['a'])
534+
self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
535+
(1, 2), {}, '|O|O', ['a', 'b'])
536+
self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
537+
(), {'a': 1}, '$$O', ['a'])
538+
self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
539+
(), {'a': 1, 'b': 2}, '$O$O', ['a', 'b'])
540+
self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
541+
(), {'a': 1}, '$|O', ['a'])
542+
self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
543+
(), {'a': 1, 'b': 2}, '$O|O', ['a', 'b'])
544+
self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
545+
(1,), {}, '|O', ['a', 'b'])
546+
self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
547+
(1,), {}, '|OO', ['a'])
548+
self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
549+
(), {}, '|$O', [''])
550+
self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
551+
(), {}, '|OO', ['a', ''])
529552

530553
def test_positional_only(self):
531554
parse = _testcapi.parse_tuple_and_keywords
532555

533-
parse((1, 2, 3), {}, b'OOO', ['', '', 'a'])
534-
parse((1, 2), {'a': 3}, b'OOO', ['', '', 'a'])
556+
parse((1, 2, 3), {}, 'OOO', ['', '', 'a'])
557+
parse((1, 2), {'a': 3}, 'OOO', ['', '', 'a'])
535558
with self.assertRaisesRegex(TypeError,
536559
r'function takes at least 2 positional arguments \(1 given\)'):
537-
parse((1,), {'a': 3}, b'OOO', ['', '', 'a'])
538-
parse((1,), {}, b'O|OO', ['', '', 'a'])
560+
parse((1,), {'a': 3}, 'OOO', ['', '', 'a'])
561+
parse((1,), {}, 'O|OO', ['', '', 'a'])
539562
with self.assertRaisesRegex(TypeError,
540563
r'function takes at least 1 positional arguments \(0 given\)'):
541-
parse((), {}, b'O|OO', ['', '', 'a'])
542-
parse((1, 2), {'a': 3}, b'OO$O', ['', '', 'a'])
564+
parse((), {}, 'O|OO', ['', '', 'a'])
565+
parse((1, 2), {'a': 3}, 'OO$O', ['', '', 'a'])
543566
with self.assertRaisesRegex(TypeError,
544567
r'function takes exactly 2 positional arguments \(1 given\)'):
545-
parse((1,), {'a': 3}, b'OO$O', ['', '', 'a'])
546-
parse((1,), {}, b'O|O$O', ['', '', 'a'])
568+
parse((1,), {'a': 3}, 'OO$O', ['', '', 'a'])
569+
parse((1,), {}, 'O|O$O', ['', '', 'a'])
547570
with self.assertRaisesRegex(TypeError,
548571
r'function takes at least 1 positional arguments \(0 given\)'):
549-
parse((), {}, b'O|O$O', ['', '', 'a'])
572+
parse((), {}, 'O|O$O', ['', '', 'a'])
550573
with self.assertRaisesRegex(SystemError, r'Empty parameter name after \$'):
551-
parse((1,), {}, b'O|$OO', ['', '', 'a'])
574+
parse((1,), {}, 'O|$OO', ['', '', 'a'])
552575
with self.assertRaisesRegex(SystemError, 'Empty keyword'):
553-
parse((1,), {}, b'O|OO', ['', 'a', ''])
576+
parse((1,), {}, 'O|OO', ['', 'a', ''])
554577

555578

556579
@unittest.skipUnless(threading, 'Threading required for this test.')

Modules/_testcapimodule.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,7 +1560,7 @@ parse_tuple_and_keywords(PyObject *self, PyObject *args)
15601560
{
15611561
PyObject *sub_args;
15621562
PyObject *sub_kwargs;
1563-
char *sub_format;
1563+
const char *sub_format;
15641564
PyObject *sub_keywords;
15651565

15661566
Py_ssize_t i, size;
@@ -1573,7 +1573,7 @@ parse_tuple_and_keywords(PyObject *self, PyObject *args)
15731573

15741574
double buffers[8][4]; /* double ensures alignment where necessary */
15751575

1576-
if (!PyArg_ParseTuple(args, "OOyO:parse_tuple_and_keywords",
1576+
if (!PyArg_ParseTuple(args, "OOsO:parse_tuple_and_keywords",
15771577
&sub_args, &sub_kwargs,
15781578
&sub_format, &sub_keywords))
15791579
return NULL;

0 commit comments

Comments
 (0)