mirror of
https://github.com/python/cpython.git
synced 2025-10-01 04:42:10 +00:00
gh-64490: Fix refcount error when arguments are packed to tuple in argument clinic (#99233)
This commit is contained in:
parent
ae185fdcca
commit
69f6cc77d0
6 changed files with 121 additions and 4 deletions
|
@ -3793,7 +3793,7 @@ test_vararg_and_posonly(PyObject *module, PyObject *const *args, Py_ssize_t narg
|
||||||
a = args[0];
|
a = args[0];
|
||||||
__clinic_args = PyTuple_New(nargs - 1);
|
__clinic_args = PyTuple_New(nargs - 1);
|
||||||
for (Py_ssize_t i = 0; i < nargs - 1; ++i) {
|
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);
|
return_value = test_vararg_and_posonly_impl(module, a, __clinic_args);
|
||||||
|
|
||||||
|
@ -3804,7 +3804,7 @@ exit:
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
test_vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args)
|
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]
|
/*[clinic input]
|
||||||
test_vararg
|
test_vararg
|
||||||
|
|
|
@ -1211,6 +1211,20 @@ class ClinicFunctionalTest(unittest.TestCase):
|
||||||
ac_tester.keyword_only_parameter(1)
|
ac_tester.keyword_only_parameter(1)
|
||||||
self.assertEqual(ac_tester.keyword_only_parameter(a=1), (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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix refcount error when arguments are packed to tuple in Argument Clinic.
|
|
@ -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[] = {
|
static PyMethodDef tester_methods[] = {
|
||||||
TEST_EMPTY_FUNCTION_METHODDEF
|
TEST_EMPTY_FUNCTION_METHODDEF
|
||||||
OBJECTS_CONVERTER_METHODDEF
|
OBJECTS_CONVERTER_METHODDEF
|
||||||
|
@ -933,6 +968,8 @@ static PyMethodDef tester_methods[] = {
|
||||||
POSONLY_KEYWORDS_OPT_KWONLY_OPT_METHODDEF
|
POSONLY_KEYWORDS_OPT_KWONLY_OPT_METHODDEF
|
||||||
POSONLY_OPT_KEYWORDS_OPT_KWONLY_OPT_METHODDEF
|
POSONLY_OPT_KEYWORDS_OPT_KWONLY_OPT_METHODDEF
|
||||||
KEYWORD_ONLY_PARAMETER_METHODDEF
|
KEYWORD_ONLY_PARAMETER_METHODDEF
|
||||||
|
VARARG_AND_POSONLY_METHODDEF
|
||||||
|
GH_99233_REFCOUNT_METHODDEF
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
67
Modules/clinic/_testclinic.c.h
generated
67
Modules/clinic/_testclinic.c.h
generated
|
@ -2288,4 +2288,69 @@ keyword_only_parameter(PyObject *module, PyObject *const *args, Py_ssize_t nargs
|
||||||
exit:
|
exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
/*[clinic end generated code: output=a9212f8e6ba18bba input=a9049054013a1b77]*/
|
|
||||||
|
PyDoc_STRVAR(vararg_and_posonly__doc__,
|
||||||
|
"vararg_and_posonly($module, a, /, *args)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define VARARG_AND_POSONLY_METHODDEF \
|
||||||
|
{"vararg_and_posonly", _PyCFunction_CAST(vararg_and_posonly), METH_FASTCALL, vararg_and_posonly__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
vararg_and_posonly(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
PyObject *a;
|
||||||
|
PyObject *__clinic_args = NULL;
|
||||||
|
|
||||||
|
if (!_PyArg_CheckPositional("vararg_and_posonly", nargs, 1, PY_SSIZE_T_MAX)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
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, Py_NewRef(args[1 + i]));
|
||||||
|
}
|
||||||
|
return_value = vararg_and_posonly_impl(module, a, __clinic_args);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
Py_XDECREF(__clinic_args);
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(gh_99233_refcount__doc__,
|
||||||
|
"gh_99233_refcount($module, /, *args)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Proof-of-concept of GH-99233 refcount error bug.");
|
||||||
|
|
||||||
|
#define GH_99233_REFCOUNT_METHODDEF \
|
||||||
|
{"gh_99233_refcount", _PyCFunction_CAST(gh_99233_refcount), METH_FASTCALL, gh_99233_refcount__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
gh_99233_refcount_impl(PyObject *module, PyObject *args);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
gh_99233_refcount(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
PyObject *__clinic_args = NULL;
|
||||||
|
|
||||||
|
if (!_PyArg_CheckPositional("gh_99233_refcount", nargs, 0, PY_SSIZE_T_MAX)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
__clinic_args = PyTuple_New(nargs - 0);
|
||||||
|
for (Py_ssize_t i = 0; i < nargs - 0; ++i) {
|
||||||
|
PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i]));
|
||||||
|
}
|
||||||
|
return_value = gh_99233_refcount_impl(module, __clinic_args);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
Py_XDECREF(__clinic_args);
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
/*[clinic end generated code: output=a5c9f181f3a32d85 input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -956,7 +956,7 @@ class CLanguage(Language):
|
||||||
parser_code.append(normalize_snippet("""
|
parser_code.append(normalize_snippet("""
|
||||||
%s = PyTuple_New(%s);
|
%s = PyTuple_New(%s);
|
||||||
for (Py_ssize_t i = 0; i < %s; ++i) {{
|
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,
|
p.converter.parser_name,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue