Skip to content

Commit c42a4ad

Browse files
authored
[3.11] gh-64490: Fix refcount error when arguments are packed to tuple in argument clinic (GH-99233) (#100338)
(cherry picked from commit 69f6cc7)
1 parent 0918667 commit c42a4ad

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
@@ -3339,7 +3339,7 @@ test_vararg_and_posonly(PyObject *module, PyObject *const *args, Py_ssize_t narg
33393339
a = args[0];
33403340
__clinic_args = PyTuple_New(nargs - 1);
33413341
for (Py_ssize_t i = 0; i < nargs - 1; ++i) {
3342-
PyTuple_SET_ITEM(__clinic_args, i, args[1 + i]);
3342+
PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[1 + i]));
33433343
}
33443344
return_value = test_vararg_and_posonly_impl(module, a, __clinic_args);
33453345

@@ -3350,7 +3350,7 @@ exit:
33503350

33513351
static PyObject *
33523352
test_vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args)
3353-
/*[clinic end generated code: output=548bca3a127c22c1 input=08dc2bf7afbf1613]*/
3353+
/*[clinic end generated code: output=081a953b8cbe7617 input=08dc2bf7afbf1613]*/
33543354

33553355
/*[clinic input]
33563356
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
@@ -897,7 +897,7 @@ def parser_body(prototype, *fields, declarations=''):
897897
parser_code.append(normalize_snippet("""
898898
%s = PyTuple_New(%s);
899899
for (Py_ssize_t i = 0; i < %s; ++i) {{
900-
PyTuple_SET_ITEM(%s, i, args[%d + i]);
900+
PyTuple_SET_ITEM(%s, i, Py_NewRef(args[%d + i]));
901901
}}
902902
""" % (
903903
p.converter.parser_name,

0 commit comments

Comments
 (0)