Skip to content

Commit 69f6cc7

Browse files
authored
gh-64490: Fix refcount error when arguments are packed to tuple in argument clinic (#99233)
1 parent ae185fd commit 69f6cc7

File tree

6 files changed

+121
-4
lines changed

6 files changed

+121
-4
lines changed

Lib/test/clinic.test

+2-2
Original file line numberDiff line numberDiff line change
@@ -3793,7 +3793,7 @@ test_vararg_and_posonly(PyObject *module, PyObject *const *args, Py_ssize_t narg
37933793
a = args[0];
37943794
__clinic_args = PyTuple_New(nargs - 1);
37953795
for (Py_ssize_t i = 0; i < nargs - 1; ++i) {
3796-
PyTuple_SET_ITEM(__clinic_args, i, args[1 + i]);
3796+
PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[1 + i]));
37973797
}
37983798
return_value = test_vararg_and_posonly_impl(module, a, __clinic_args);
37993799

@@ -3804,7 +3804,7 @@ exit:
38043804

38053805
static PyObject *
38063806
test_vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args)
3807-
/*[clinic end generated code: output=548bca3a127c22c1 input=08dc2bf7afbf1613]*/
3807+
/*[clinic end generated code: output=081a953b8cbe7617 input=08dc2bf7afbf1613]*/
38083808

38093809
/*[clinic input]
38103810
test_vararg

Lib/test/test_clinic.py

+14
Original file line numberDiff line numberDiff line change
@@ -1211,6 +1211,20 @@ def test_keyword_only_parameter(self):
12111211
ac_tester.keyword_only_parameter(1)
12121212
self.assertEqual(ac_tester.keyword_only_parameter(a=1), (1,))
12131213

1214+
def test_vararg_and_posonly(self):
1215+
with self.assertRaises(TypeError):
1216+
ac_tester.vararg_and_posonly()
1217+
with self.assertRaises(TypeError):
1218+
ac_tester.vararg_and_posonly(1, b=2)
1219+
self.assertEqual(ac_tester.vararg_and_posonly(1, 2, 3, 4), (1, (2, 3, 4)))
1220+
1221+
def test_gh_99233_refcount(self):
1222+
arg = '*A unique string is not referenced by anywhere else.*'
1223+
arg_refcount_origin = sys.getrefcount(arg)
1224+
ac_tester.gh_99233_refcount(arg)
1225+
arg_refcount_after = sys.getrefcount(arg)
1226+
self.assertEqual(arg_refcount_origin, arg_refcount_after)
1227+
12141228

12151229
if __name__ == "__main__":
12161230
unittest.main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix refcount error when arguments are packed to tuple in Argument Clinic.

Modules/_testclinic.c

+37
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,41 @@ keyword_only_parameter_impl(PyObject *module, PyObject *a)
892892
}
893893

894894

895+
/*[clinic input]
896+
vararg_and_posonly
897+
898+
a: object
899+
*args: object
900+
/
901+
902+
[clinic start generated code]*/
903+
904+
static PyObject *
905+
vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args)
906+
/*[clinic end generated code: output=42792f799465a14d input=defe017b19ba52e8]*/
907+
{
908+
return pack_arguments_newref(2, a, args);
909+
}
910+
911+
912+
/*[clinic input]
913+
gh_99233_refcount
914+
915+
*args: object
916+
/
917+
918+
Proof-of-concept of GH-99233 refcount error bug.
919+
920+
[clinic start generated code]*/
921+
922+
static PyObject *
923+
gh_99233_refcount_impl(PyObject *module, PyObject *args)
924+
/*[clinic end generated code: output=585855abfbca9a7f input=85f5fb47ac91a626]*/
925+
{
926+
Py_RETURN_NONE;
927+
}
928+
929+
895930
static PyMethodDef tester_methods[] = {
896931
TEST_EMPTY_FUNCTION_METHODDEF
897932
OBJECTS_CONVERTER_METHODDEF
@@ -933,6 +968,8 @@ static PyMethodDef tester_methods[] = {
933968
POSONLY_KEYWORDS_OPT_KWONLY_OPT_METHODDEF
934969
POSONLY_OPT_KEYWORDS_OPT_KWONLY_OPT_METHODDEF
935970
KEYWORD_ONLY_PARAMETER_METHODDEF
971+
VARARG_AND_POSONLY_METHODDEF
972+
GH_99233_REFCOUNT_METHODDEF
936973
{NULL, NULL}
937974
};
938975

Modules/clinic/_testclinic.c.h

+66-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tools/clinic/clinic.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,7 @@ def parser_body(prototype, *fields, declarations=''):
956956
parser_code.append(normalize_snippet("""
957957
%s = PyTuple_New(%s);
958958
for (Py_ssize_t i = 0; i < %s; ++i) {{
959-
PyTuple_SET_ITEM(%s, i, args[%d + i]);
959+
PyTuple_SET_ITEM(%s, i, Py_NewRef(args[%d + i]));
960960
}}
961961
""" % (
962962
p.converter.parser_name,

0 commit comments

Comments
 (0)