]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-64490: Fix refcount error when arguments are packed to tuple in argument clinic...
authorcolorfulappl <colorfulappl@qq.com>
Thu, 24 Nov 2022 12:24:18 +0000 (20:24 +0800)
committerGitHub <noreply@github.com>
Thu, 24 Nov 2022 12:24:18 +0000 (17:54 +0530)
Lib/test/clinic.test
Lib/test/test_clinic.py
Misc/NEWS.d/next/Library/2022-11-08-11-18-51.gh-issue-64490.VcBgrN.rst [new file with mode: 0644]
Modules/_testclinic.c
Modules/clinic/_testclinic.c.h
Tools/clinic/clinic.py

index 47e3e02490c8163480faf9603ba4bf12cee6a1f8..7b804e8576aedcea6ea673a179c644d2ec552a9d 100644 (file)
@@ -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);
 
@@ -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
index 7c1bd1c10d2ab651713894ab8ccfd60dea7d7a5b..a590fa50aab04f2c690001bd8f27fb4b3c3b6461 100644 (file)
@@ -1211,6 +1211,20 @@ class ClinicFunctionalTest(unittest.TestCase):
             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 (file)
index 0000000..f98c181
--- /dev/null
@@ -0,0 +1 @@
+Fix refcount error when arguments are packed to tuple in Argument Clinic.
index c9858e96445714e7b53790f891c2e4ad7480f59c..a23ece2ae0355bb7d7996165db34a52843d089fe 100644 (file)
@@ -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}
 };
 
index b0ac4c2eef83402ce1fa705ac9fa08c400e7b611..eb425821e9cb3fbe1b90f4d7f5089e4b8a57f8a8 100644 (file)
@@ -2288,4 +2288,69 @@ keyword_only_parameter(PyObject *module, PyObject *const *args, Py_ssize_t nargs
 exit:
     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]*/
index a8687e3470a185ff958c089fdc08a0dbddc536bd..94e17ee9c7dfda553e4d3abf0a14b5b647a1fd1c 100755 (executable)
@@ -956,7 +956,7 @@ class CLanguage(Language):
                         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,