[Python-checkins] [3.11] gh-64490: Fix refcount error when arguments are packed to tuple in argument clinic (GH-99233) (#100338)
kumaraditya303
webhook-mailer at python.org
Mon Dec 19 04:49:23 EST 2022
https://github.com/python/cpython/commit/c42a4ad58749273841ae6f504a4e661fb7c5ca3b
commit: c42a4ad58749273841ae6f504a4e661fb7c5ca3b
branch: 3.11
author: colorfulappl <colorfulappl at qq.com>
committer: kumaraditya303 <59607654+kumaraditya303 at users.noreply.github.com>
date: 2022-12-19T15:18:49+05:30
summary:
[3.11] gh-64490: Fix refcount error when arguments are packed to tuple in argument clinic (GH-99233) (#100338)
(cherry picked from commit 69f6cc77d0f1664f983a83b6ae707d99a99f5c4f)
files:
A Misc/NEWS.d/next/Library/2022-11-08-11-18-51.gh-issue-64490.VcBgrN.rst
M Lib/test/clinic.test
M Lib/test/test_clinic.py
M Modules/_testclinic.c
M Modules/clinic/_testclinic.c.h
M Tools/clinic/clinic.py
diff --git a/Lib/test/clinic.test b/Lib/test/clinic.test
index 0228d6be0326..8643f3fe78ae 100644
--- a/Lib/test/clinic.test
+++ b/Lib/test/clinic.test
@@ -3339,7 +3339,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);
@@ -3350,7 +3350,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
diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py
index 86c4f94ac028..af86d685866c 100644
--- a/Lib/test/test_clinic.py
+++ b/Lib/test/test_clinic.py
@@ -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()
diff --git a/Misc/NEWS.d/next/Library/2022-11-08-11-18-51.gh-issue-64490.VcBgrN.rst b/Misc/NEWS.d/next/Library/2022-11-08-11-18-51.gh-issue-64490.VcBgrN.rst
new file mode 100644
index 000000000000..f98c181cc9c5
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-11-08-11-18-51.gh-issue-64490.VcBgrN.rst
@@ -0,0 +1 @@
+Fix refcount error when arguments are packed to tuple in Argument Clinic.
diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c
index c9858e964457..a23ece2ae035 100644
--- a/Modules/_testclinic.c
+++ b/Modules/_testclinic.c
@@ -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
@@ -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}
};
diff --git a/Modules/clinic/_testclinic.c.h b/Modules/clinic/_testclinic.c.h
index d363dd3f358e..c108d9d626a1 100644
--- a/Modules/clinic/_testclinic.c.h
+++ b/Modules/clinic/_testclinic.c.h
@@ -1914,4 +1914,69 @@ keyword_only_parameter(PyObject *module, PyObject *const *args, Py_ssize_t nargs
exit:
return return_value;
}
-/*[clinic end generated code: output=83f439d06635a2e9 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=16848e04bd5ddf7d input=a9049054013a1b77]*/
diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py
index 97d8d0a9410b..acd463bdd894 100755
--- a/Tools/clinic/clinic.py
+++ b/Tools/clinic/clinic.py
@@ -897,7 +897,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,
More information about the Python-checkins
mailing list