gh-64490: Fix bugs in argument clinic varargs processing (#32092) · python/cpython@0da7283 · GitHub
Skip to content

Commit 0da7283

Browse files
authored
gh-64490: Fix bugs in argument clinic varargs processing (#32092)
1 parent 351842b commit 0da7283

11 files changed

Lines changed: 612 additions & 11 deletions

File tree

Include/internal/pycore_global_objects_fini_generated.h

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_global_strings.h

Lines changed: 5 additions & 0 deletions

Include/internal/pycore_runtime_init_generated.h

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_unicodeobject_generated.h

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/clinic.test

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3845,7 +3845,6 @@ test_vararg(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
38453845
};
38463846
#undef KWTUPLE
38473847
PyObject *argsbuf[2];
3848-
Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
38493848
PyObject *a;
38503849
PyObject *__clinic_args = NULL;
38513850

@@ -3864,7 +3863,7 @@ exit:
38643863

38653864
static PyObject *
38663865
test_vararg_impl(PyObject *module, PyObject *a, PyObject *args)
3867-
/*[clinic end generated code: output=6661f3ca97d85e8c input=81d33815ad1bae6e]*/
3866+
/*[clinic end generated code: output=880365c61ae205d7 input=81d33815ad1bae6e]*/
38683867

38693868
/*[clinic input]
38703869
test_vararg_with_default
@@ -3918,7 +3917,7 @@ test_vararg_with_default(PyObject *module, PyObject *const *args, Py_ssize_t nar
39183917
};
39193918
#undef KWTUPLE
39203919
PyObject *argsbuf[3];
3921-
Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
3920+
Py_ssize_t noptargs = Py_MIN(nargs, 1) + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
39223921
PyObject *a;
39233922
PyObject *__clinic_args = NULL;
39243923
int b = 0;
@@ -3947,7 +3946,7 @@ exit:
39473946
static PyObject *
39483947
test_vararg_with_default_impl(PyObject *module, PyObject *a, PyObject *args,
39493948
int b)
3950-
/*[clinic end generated code: output=5fe3cfccb1bef781 input=6e110b54acd9b22d]*/
3949+
/*[clinic end generated code: output=291e9a5a09831128 input=6e110b54acd9b22d]*/
39513950

39523951
/*[clinic input]
39533952
test_vararg_with_only_defaults

Lib/test/test_clinic.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,15 @@ def test_parameters_not_permitted_after_slash_for_now(self):
730730
x: int
731731
""")
732732

733+
def test_parameters_no_more_than_one_vararg(self):
734+
s = self.parse_function_should_fail("""
735+
module foo
736+
foo.bar
737+
*vararg1: object
738+
*vararg2: object
739+
""")
740+
self.assertEqual(s, "Error on line 0:\nToo many var args\n")
741+
733742
def test_function_not_at_column_0(self):
734743
function = self.parse_function("""
735744
module foo
@@ -1222,13 +1231,47 @@ def test_keyword_only_parameter(self):
12221231
ac_tester.keyword_only_parameter(1)
12231232
self.assertEqual(ac_tester.keyword_only_parameter(a=1), (1,))
12241233

1234+
def test_posonly_vararg(self):
1235+
with self.assertRaises(TypeError):
1236+
ac_tester.posonly_vararg()
1237+
self.assertEqual(ac_tester.posonly_vararg(1, 2), (1, 2, ()))
1238+
self.assertEqual(ac_tester.posonly_vararg(1, b=2), (1, 2, ()))
1239+
self.assertEqual(ac_tester.posonly_vararg(1, 2, 3, 4), (1, 2, (3, 4)))
1240+
12251241
def test_vararg_and_posonly(self):
12261242
with self.assertRaises(TypeError):
12271243
ac_tester.vararg_and_posonly()
12281244
with self.assertRaises(TypeError):
12291245
ac_tester.vararg_and_posonly(1, b=2)
12301246
self.assertEqual(ac_tester.vararg_and_posonly(1, 2, 3, 4), (1, (2, 3, 4)))
12311247

1248+
def test_vararg(self):
1249+
with self.assertRaises(TypeError):
1250+
ac_tester.vararg()
1251+
with self.assertRaises(TypeError):
1252+
ac_tester.vararg(1, b=2)
1253+
self.assertEqual(ac_tester.vararg(1, 2, 3, 4), (1, (2, 3, 4)))
1254+
1255+
def test_vararg_with_default(self):
1256+
with self.assertRaises(TypeError):
1257+
ac_tester.vararg_with_default()
1258+
self.assertEqual(ac_tester.vararg_with_default(1, b=False), (1, (), False))
1259+
self.assertEqual(ac_tester.vararg_with_default(1, 2, 3, 4), (1, (2, 3, 4), False))
1260+
self.assertEqual(ac_tester.vararg_with_default(1, 2, 3, 4, b=True), (1, (2, 3, 4), True))
1261+
1262+
def test_vararg_with_only_defaults(self):
1263+
self.assertEqual(ac_tester.vararg_with_only_defaults(), ((), None))
1264+
self.assertEqual(ac_tester.vararg_with_only_defaults(b=2), ((), 2))
1265+
self.assertEqual(ac_tester.vararg_with_only_defaults(1, b=2), ((1, ), 2))
1266+
self.assertEqual(ac_tester.vararg_with_only_defaults(1, 2, 3, 4), ((1, 2, 3, 4), None))
1267+
self.assertEqual(ac_tester.vararg_with_only_defaults(1, 2, 3, 4, b=5), ((1, 2, 3, 4), 5))
1268+
1269+
def test_gh_32092_oob(self):
1270+
ac_tester.gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6)
1271+
1272+
def test_gh_32092_kw_pass(self):
1273+
ac_tester.gh_32092_kw_pass(1, 2, 3)
1274+
12321275
def test_gh_99233_refcount(self):
12331276
arg = '*A unique string is not referenced by anywhere else.*'
12341277
arg_refcount_origin = sys.getrefcount(arg)
@@ -1241,5 +1284,6 @@ def test_gh_99240_double_free(self):
12411284
with self.assertRaisesRegex(TypeError, expected_error):
12421285
ac_tester.gh_99240_double_free('a', '\0b')
12431286

1287+
12441288
if __name__ == "__main__":
12451289
unittest.main()
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Argument Clinic varargs bugfixes
2+
3+
* Fix out-of-bounds error in :c:func:`!_PyArg_UnpackKeywordsWithVararg`.
4+
* Fix incorrect check which allowed more than one varargs in clinic.py.
5+
* Fix miscalculation of ``noptargs`` in generated code.
6+
* Do not generate ``noptargs`` when there is a vararg argument and no optional argument.
7+

Modules/_testclinic.c

Lines changed: 119 additions & 0 deletions

0 commit comments

Comments
 (0)