Skip to content

Commit

Permalink
pythongh-64490: Fix refcount error when arguments are packed to tuple…
Browse files Browse the repository at this point in the history
… in argument clinic (python#99233)
  • Loading branch information
colorfulappl committed Nov 24, 2022
1 parent ae185fd commit 69f6cc7
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 4 deletions.
4 changes: 2 additions & 2 deletions Lib/test/clinic.test
Expand Up @@ -3793,7 +3793,7 @@ test_vararg_and_posonly(PyObject *module, PyObject *const *args, Py_ssize_t narg
a = args[0];
__clinic_args = PyTuple_New(nargs - 1);
for (Py_ssize_t i = 0; i < nargs - 1; ++i) {
PyTuple_SET_ITEM(__clinic_args, i, args[1 + i]);
PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[1 + i]));
}
return_value = test_vararg_and_posonly_impl(module, a, __clinic_args);

Expand All @@ -3804,7 +3804,7 @@ exit:

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

/*[clinic input]
test_vararg
Expand Down
14 changes: 14 additions & 0 deletions Lib/test/test_clinic.py
Expand Up @@ -1211,6 +1211,20 @@ def test_keyword_only_parameter(self):
ac_tester.keyword_only_parameter(1)
self.assertEqual(ac_tester.keyword_only_parameter(a=1), (1,))

def test_vararg_and_posonly(self):
with self.assertRaises(TypeError):
ac_tester.vararg_and_posonly()
with self.assertRaises(TypeError):
ac_tester.vararg_and_posonly(1, b=2)
self.assertEqual(ac_tester.vararg_and_posonly(1, 2, 3, 4), (1, (2, 3, 4)))

def test_gh_99233_refcount(self):
arg = '*A unique string is not referenced by anywhere else.*'
arg_refcount_origin = sys.getrefcount(arg)
ac_tester.gh_99233_refcount(arg)
arg_refcount_after = sys.getrefcount(arg)
self.assertEqual(arg_refcount_origin, arg_refcount_after)


if __name__ == "__main__":
unittest.main()
@@ -0,0 +1 @@
Fix refcount error when arguments are packed to tuple in Argument Clinic.
37 changes: 37 additions & 0 deletions Modules/_testclinic.c
Expand Up @@ -892,6 +892,41 @@ keyword_only_parameter_impl(PyObject *module, PyObject *a)
}


/*[clinic input]
vararg_and_posonly
a: object
*args: object
/
[clinic start generated code]*/

static PyObject *
vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args)
/*[clinic end generated code: output=42792f799465a14d input=defe017b19ba52e8]*/
{
return pack_arguments_newref(2, a, args);
}


/*[clinic input]
gh_99233_refcount
*args: object
/
Proof-of-concept of GH-99233 refcount error bug.
[clinic start generated code]*/

static PyObject *
gh_99233_refcount_impl(PyObject *module, PyObject *args)
/*[clinic end generated code: output=585855abfbca9a7f input=85f5fb47ac91a626]*/
{
Py_RETURN_NONE;
}


static PyMethodDef tester_methods[] = {
TEST_EMPTY_FUNCTION_METHODDEF
OBJECTS_CONVERTER_METHODDEF
Expand Down Expand Up @@ -933,6 +968,8 @@ static PyMethodDef tester_methods[] = {
POSONLY_KEYWORDS_OPT_KWONLY_OPT_METHODDEF
POSONLY_OPT_KEYWORDS_OPT_KWONLY_OPT_METHODDEF
KEYWORD_ONLY_PARAMETER_METHODDEF
VARARG_AND_POSONLY_METHODDEF
GH_99233_REFCOUNT_METHODDEF
{NULL, NULL}
};

Expand Down
67 changes: 66 additions & 1 deletion Modules/clinic/_testclinic.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Tools/clinic/clinic.py
Expand Up @@ -956,7 +956,7 @@ def parser_body(prototype, *fields, declarations=''):
parser_code.append(normalize_snippet("""
%s = PyTuple_New(%s);
for (Py_ssize_t i = 0; i < %s; ++i) {{
PyTuple_SET_ITEM(%s, i, args[%d + i]);
PyTuple_SET_ITEM(%s, i, Py_NewRef(args[%d + i]));
}}
""" % (
p.converter.parser_name,
Expand Down

0 comments on commit 69f6cc7

Please sign in to comment.