From f00bb03be775538203f3ee643a17fdb50fe8565f Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Mon, 22 Aug 2022 19:26:25 +0800 Subject: [PATCH 01/29] Support functional test for Argument Clinic --- .../test_clinic_functionality/__init__.py | 1 + .../test_clinic_functionality/__main__.py | 3 + .../clinic/test_clinic_functionality.c.h | 165 ++++++++++++++++++ Lib/test/test_clinic_functionality/setup.py | 12 ++ .../test_clinic_functionality.c | 97 ++++++++++ .../test_clinic_functionality.py | 128 ++++++++++++++ 6 files changed, 406 insertions(+) create mode 100644 Lib/test/test_clinic_functionality/__init__.py create mode 100644 Lib/test/test_clinic_functionality/__main__.py create mode 100644 Lib/test/test_clinic_functionality/clinic/test_clinic_functionality.c.h create mode 100644 Lib/test/test_clinic_functionality/setup.py create mode 100644 Lib/test/test_clinic_functionality/test_clinic_functionality.c create mode 100644 Lib/test/test_clinic_functionality/test_clinic_functionality.py diff --git a/Lib/test/test_clinic_functionality/__init__.py b/Lib/test/test_clinic_functionality/__init__.py new file mode 100644 index 00000000000000..3ad4812cda5e16 --- /dev/null +++ b/Lib/test/test_clinic_functionality/__init__.py @@ -0,0 +1 @@ +from .test_clinic_functionality import * diff --git a/Lib/test/test_clinic_functionality/__main__.py b/Lib/test/test_clinic_functionality/__main__.py new file mode 100644 index 00000000000000..e3847f31fd6c91 --- /dev/null +++ b/Lib/test/test_clinic_functionality/__main__.py @@ -0,0 +1,3 @@ +import unittest + +unittest.main('test.test_clinic_functionality') diff --git a/Lib/test/test_clinic_functionality/clinic/test_clinic_functionality.c.h b/Lib/test/test_clinic_functionality/clinic/test_clinic_functionality.c.h new file mode 100644 index 00000000000000..46a6aa9903ac48 --- /dev/null +++ b/Lib/test/test_clinic_functionality/clinic/test_clinic_functionality.c.h @@ -0,0 +1,165 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() +#endif + + +PyDoc_STRVAR(gh_32092_oob__doc__, +"gh_32092_oob($module, /, pos1, pos2, *varargs, kw1=None, kw2=None)\n" +"--\n" +"\n" +"Proof-of-concept of GH-32092 OOB bug.\n" +"\n" +"Array index out-of-bound bug in function\n" +"`_PyArg_UnpackKeywordsWithVararg` .\n" +"\n" +"Calling this function by gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6)\n" +"to trigger this bug (crash).\n" +"Expected return: (1, 2, (3, 4), 5, 6)"); + +#define GH_32092_OOB_METHODDEF \ + {"gh_32092_oob", _PyCFunction_CAST(gh_32092_oob), METH_FASTCALL|METH_KEYWORDS, gh_32092_oob__doc__}, + +static PyObject * +gh_32092_oob_impl(PyObject *module, PyObject *pos1, PyObject *pos2, + PyObject *varargs, PyObject *kw1, PyObject *kw2); + +static PyObject * +gh_32092_oob(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(pos1), &_Py_ID(pos2), &_Py_ID(kw1), &_Py_ID(kw2), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"pos1", "pos2", "kw1", "kw2", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "gh_32092_oob", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + PyObject *pos1; + PyObject *pos2; + PyObject *varargs = NULL; + PyObject *kw1 = Py_None; + PyObject *kw2 = Py_None; + + args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, 2, argsbuf); + if (!args) { + goto exit; + } + pos1 = args[0]; + pos2 = args[1]; + varargs = args[2]; + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[3]) { + kw1 = args[3]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + kw2 = args[4]; +skip_optional_kwonly: + return_value = gh_32092_oob_impl(module, pos1, pos2, varargs, kw1, kw2); + +exit: + Py_XDECREF(varargs); + return return_value; +} + +PyDoc_STRVAR(gh_32092_kw_pass__doc__, +"gh_32092_kw_pass($module, /, pos, *args, kw=None)\n" +"--\n" +"\n" +"Proof-of-concept of GH-32092 keyword args passing bug.\n" +"\n" +"The calculation of `noptargs` in AC-generated function\n" +"`builtin_kw_pass_poc` is incorrect.\n" +"\n" +"Calling this function by gh_32092_kw_pass(1, 2, 3)\n" +"to trigger this bug (crash).\n" +"Expected return: (1, (2, 3))"); + +#define GH_32092_KW_PASS_METHODDEF \ + {"gh_32092_kw_pass", _PyCFunction_CAST(gh_32092_kw_pass), METH_FASTCALL|METH_KEYWORDS, gh_32092_kw_pass__doc__}, + +static PyObject * +gh_32092_kw_pass_impl(PyObject *module, PyObject *pos, PyObject *args, + PyObject *kw); + +static PyObject * +gh_32092_kw_pass(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(pos), &_Py_ID(kw), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"pos", "kw", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "gh_32092_kw_pass", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *pos; + PyObject *__clinic_args = NULL; + PyObject *kw = Py_None; + + args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf); + if (!args) { + goto exit; + } + pos = args[0]; + __clinic_args = args[1]; + if (!noptargs) { + goto skip_optional_kwonly; + } + kw = args[2]; +skip_optional_kwonly: + return_value = gh_32092_kw_pass_impl(module, pos, __clinic_args, kw); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} +/*[clinic end generated code: output=cebc2a5a0048c387 input=a9049054013a1b77]*/ diff --git a/Lib/test/test_clinic_functionality/setup.py b/Lib/test/test_clinic_functionality/setup.py new file mode 100644 index 00000000000000..d5891a465cfefc --- /dev/null +++ b/Lib/test/test_clinic_functionality/setup.py @@ -0,0 +1,12 @@ +from setuptools import setup, Extension +from test import support + + +def main(): + SOURCE = support.findfile('test_clinic_functionality.c', subdir='test_clinic_functionality') + module = Extension('test_clinic_functionality', sources=[SOURCE]) + setup(name='test_clinic_functionality', version='0.0', ext_modules=[module]) + + +if __name__ == '__main__': + main() diff --git a/Lib/test/test_clinic_functionality/test_clinic_functionality.c b/Lib/test/test_clinic_functionality/test_clinic_functionality.c new file mode 100644 index 00000000000000..0ba688e3d58199 --- /dev/null +++ b/Lib/test/test_clinic_functionality/test_clinic_functionality.c @@ -0,0 +1,97 @@ +#define PY_SSIZE_T_CLEAN +#include +#include "clinic/test_clinic_functionality.c.h" + + +/*[clinic input] +module clinic_functional_tester +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2ee8b0b242501b11]*/ + +/*[clinic input] +gh_32092_oob + + pos1: object + pos2: object + *varargs: object + kw1: object = None + kw2: object = None + +Proof-of-concept of GH-32092 OOB bug. + +Array index out-of-bound bug in function +`_PyArg_UnpackKeywordsWithVararg` . + +Calling this function by gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6) +to trigger this bug (crash). +Expected return: (1, 2, (3, 4), 5, 6) + +[clinic start generated code]*/ + +static PyObject * +gh_32092_oob_impl(PyObject *module, PyObject *pos1, PyObject *pos2, + PyObject *varargs, PyObject *kw1, PyObject *kw2) +/*[clinic end generated code: output=ee259c130054653f input=91d8e227acf93b02]*/ +{ + PyObject *tuple = PyTuple_New(5);; + PyTuple_SET_ITEM(tuple, 0, Py_NewRef(pos1)); + PyTuple_SET_ITEM(tuple, 1, Py_NewRef(pos2)); + PyTuple_SET_ITEM(tuple, 2, Py_NewRef(varargs)); + PyTuple_SET_ITEM(tuple, 3, Py_NewRef(kw1)); + PyTuple_SET_ITEM(tuple, 4, Py_NewRef(kw2)); + return tuple; +} + +/*[clinic input] +gh_32092_kw_pass + + pos: object + *args: object + kw: object = None + +Proof-of-concept of GH-32092 keyword args passing bug. + +The calculation of `noptargs` in AC-generated function +`builtin_kw_pass_poc` is incorrect. + +Calling this function by gh_32092_kw_pass(1, 2, 3) +to trigger this bug (crash). +Expected return: (1, (2, 3)) + +[clinic start generated code]*/ + +static PyObject * +gh_32092_kw_pass_impl(PyObject *module, PyObject *pos, PyObject *args, + PyObject *kw) +/*[clinic end generated code: output=4a2bbe4f7c8604e9 input=c51b7572ac09f193]*/ +{ + PyObject *tuple = PyTuple_New(3);; + PyTuple_SET_ITEM(tuple, 0, Py_NewRef(pos)); + PyTuple_SET_ITEM(tuple, 1, Py_NewRef(args)); + PyTuple_SET_ITEM(tuple, 2, Py_NewRef(kw)); + return tuple; +} + +static PyMethodDef tester_methods[] = { + GH_32092_OOB_METHODDEF + GH_32092_KW_PASS_METHODDEF + {NULL, NULL} +}; + +static struct PyModuleDef clinic_functional_tester_module = { + PyModuleDef_HEAD_INIT, + "clinic_functional_tester", + NULL, + 0, + tester_methods, + NULL, + NULL, + NULL, + NULL +}; + +PyMODINIT_FUNC +PyInit_test_clinic_functionality(void) +{ + return PyModule_Create(&clinic_functional_tester_module); +} diff --git a/Lib/test/test_clinic_functionality/test_clinic_functionality.py b/Lib/test/test_clinic_functionality/test_clinic_functionality.py new file mode 100644 index 00000000000000..53cad36bfb3b29 --- /dev/null +++ b/Lib/test/test_clinic_functionality/test_clinic_functionality.py @@ -0,0 +1,128 @@ +import os.path +import sys +import unittest +import subprocess +import textwrap +from test import support +from test.support import os_helper + + +MS_WINDOWS = (sys.platform == 'win32') +SETUP = support.findfile('setup.py', subdir='test_clinic_functionality') +MOD_NAME = 'test_clinic_functionality' + + +def _run_cmd(operation, cmd, verbose=False): + if verbose: + print(f'{operation}:', ' '.join(cmd)) + subprocess.run(cmd, check=True) + else: + proc = subprocess.run(cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True) + if proc.returncode: + print(proc.stdout, end='') + self.fail(f'{operation} failed with exit code {proc.returncode}') + + +class EnvInitializer: + """Build the module before test and clear the files after test.""" + python = '' + verbose = support.verbose + + def run_cmd(self, operation, cmd): + _run_cmd(operation, cmd, self.verbose) + + def _setup_env(self): + venv_dir = 'env' + + # Create virtual environment to get setuptools + cmd = [sys.executable, '-X', 'dev', '-m', 'venv', venv_dir] + self.run_cmd('Setup venv', cmd) + + # Get the Python executable of the venv + python_exe = 'python' + if sys.executable.endswith('.exe'): + python_exe += '.exe' + if MS_WINDOWS: + self.python = os.path.join(venv_dir, 'Scripts', python_exe) + else: + self.python = os.path.join(venv_dir, 'bin', python_exe) + + # Build module + cmd = [self.python, '-X', 'dev', SETUP, 'build_ext', '--verbose'] + self.run_cmd('Build', cmd) + + # Install module + cmd = [self.python, '-X', 'dev', SETUP, 'install'] + self.run_cmd('Install', cmd) + + def setup_env(self): + # Build in a temporary directory + with os_helper.temp_cwd(): + self._setup_env() + yield + + def __init__(self): + if self.verbose: + print() + print('Setup test environment') + self.env = self.setup_env() + next(self.env) + + def __del__(self): + if self.verbose: + print('Clear test environment') + try: + next(self.env) + except StopIteration: + pass + except Exception as e: + raise e + + +env = None + + +def setUpModule(): + global env + env = EnvInitializer() + + +def tearDownModule(): + global env + del env + + +@support.requires_subprocess() +@support.requires_venv_with_pip() +class TestClinicFunctional(unittest.TestCase): + verbose = support.verbose + + def run_cmd(self, operation, cmd): + _run_cmd(operation, cmd, self.verbose) + + def exec_script(self, script): + script = textwrap.dedent(script) + global env + python = env.python + cmd = [python, '-c', script] + self.run_cmd('Test', cmd) + + def assert_func_result(self, func_str, expected_result): + script = f'''\ + import {MOD_NAME} as mod + assert(mod.{func_str} == {expected_result}) + ''' + self.exec_script(script) + + def test_gh_32092_oob(self): + self.assert_func_result('gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6)', '(1, 2, (3, 4), 5, 6))') + + def test_gh_32092_kw_pass(self): + self.assert_func_result('gh_32092_kw_pass(1, 2, 3)', '(1, (2, 3))') + + +if __name__ == "__main__": + unittest.main() From a59e3042f5ac9a7f296e00d07af58374b947ec97 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Mon, 22 Aug 2022 15:49:15 +0000 Subject: [PATCH 02/29] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Tests/2022-08-22-15-49-14.gh-issue-96002.4UE9UE.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Tests/2022-08-22-15-49-14.gh-issue-96002.4UE9UE.rst diff --git a/Misc/NEWS.d/next/Tests/2022-08-22-15-49-14.gh-issue-96002.4UE9UE.rst b/Misc/NEWS.d/next/Tests/2022-08-22-15-49-14.gh-issue-96002.4UE9UE.rst new file mode 100644 index 00000000000000..d0597e956e2b5d --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2022-08-22-15-49-14.gh-issue-96002.4UE9UE.rst @@ -0,0 +1 @@ +Add functional test (``test_clinic_functionality``) for Argument Clinic. From 2bd331e97a61ee36baa3f21d41ee11aff9da5bfb Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Tue, 23 Aug 2022 13:07:41 +0800 Subject: [PATCH 03/29] Revert "Support functional test for Argument Clinic" This reverts commit f00bb03be775538203f3ee643a17fdb50fe8565f. --- .../test_clinic_functionality/__init__.py | 1 - .../test_clinic_functionality/__main__.py | 3 - .../clinic/test_clinic_functionality.c.h | 165 ------------------ Lib/test/test_clinic_functionality/setup.py | 12 -- .../test_clinic_functionality.c | 97 ---------- .../test_clinic_functionality.py | 128 -------------- 6 files changed, 406 deletions(-) delete mode 100644 Lib/test/test_clinic_functionality/__init__.py delete mode 100644 Lib/test/test_clinic_functionality/__main__.py delete mode 100644 Lib/test/test_clinic_functionality/clinic/test_clinic_functionality.c.h delete mode 100644 Lib/test/test_clinic_functionality/setup.py delete mode 100644 Lib/test/test_clinic_functionality/test_clinic_functionality.c delete mode 100644 Lib/test/test_clinic_functionality/test_clinic_functionality.py diff --git a/Lib/test/test_clinic_functionality/__init__.py b/Lib/test/test_clinic_functionality/__init__.py deleted file mode 100644 index 3ad4812cda5e16..00000000000000 --- a/Lib/test/test_clinic_functionality/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .test_clinic_functionality import * diff --git a/Lib/test/test_clinic_functionality/__main__.py b/Lib/test/test_clinic_functionality/__main__.py deleted file mode 100644 index e3847f31fd6c91..00000000000000 --- a/Lib/test/test_clinic_functionality/__main__.py +++ /dev/null @@ -1,3 +0,0 @@ -import unittest - -unittest.main('test.test_clinic_functionality') diff --git a/Lib/test/test_clinic_functionality/clinic/test_clinic_functionality.c.h b/Lib/test/test_clinic_functionality/clinic/test_clinic_functionality.c.h deleted file mode 100644 index 46a6aa9903ac48..00000000000000 --- a/Lib/test/test_clinic_functionality/clinic/test_clinic_functionality.c.h +++ /dev/null @@ -1,165 +0,0 @@ -/*[clinic input] -preserve -[clinic start generated code]*/ - -#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) -# include "pycore_gc.h" // PyGC_Head -# include "pycore_runtime.h" // _Py_ID() -#endif - - -PyDoc_STRVAR(gh_32092_oob__doc__, -"gh_32092_oob($module, /, pos1, pos2, *varargs, kw1=None, kw2=None)\n" -"--\n" -"\n" -"Proof-of-concept of GH-32092 OOB bug.\n" -"\n" -"Array index out-of-bound bug in function\n" -"`_PyArg_UnpackKeywordsWithVararg` .\n" -"\n" -"Calling this function by gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6)\n" -"to trigger this bug (crash).\n" -"Expected return: (1, 2, (3, 4), 5, 6)"); - -#define GH_32092_OOB_METHODDEF \ - {"gh_32092_oob", _PyCFunction_CAST(gh_32092_oob), METH_FASTCALL|METH_KEYWORDS, gh_32092_oob__doc__}, - -static PyObject * -gh_32092_oob_impl(PyObject *module, PyObject *pos1, PyObject *pos2, - PyObject *varargs, PyObject *kw1, PyObject *kw2); - -static PyObject * -gh_32092_oob(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(pos1), &_Py_ID(pos2), &_Py_ID(kw1), &_Py_ID(kw2), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"pos1", "pos2", "kw1", "kw2", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "gh_32092_oob", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[5]; - Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - PyObject *pos1; - PyObject *pos2; - PyObject *varargs = NULL; - PyObject *kw1 = Py_None; - PyObject *kw2 = Py_None; - - args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, 2, argsbuf); - if (!args) { - goto exit; - } - pos1 = args[0]; - pos2 = args[1]; - varargs = args[2]; - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[3]) { - kw1 = args[3]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - kw2 = args[4]; -skip_optional_kwonly: - return_value = gh_32092_oob_impl(module, pos1, pos2, varargs, kw1, kw2); - -exit: - Py_XDECREF(varargs); - return return_value; -} - -PyDoc_STRVAR(gh_32092_kw_pass__doc__, -"gh_32092_kw_pass($module, /, pos, *args, kw=None)\n" -"--\n" -"\n" -"Proof-of-concept of GH-32092 keyword args passing bug.\n" -"\n" -"The calculation of `noptargs` in AC-generated function\n" -"`builtin_kw_pass_poc` is incorrect.\n" -"\n" -"Calling this function by gh_32092_kw_pass(1, 2, 3)\n" -"to trigger this bug (crash).\n" -"Expected return: (1, (2, 3))"); - -#define GH_32092_KW_PASS_METHODDEF \ - {"gh_32092_kw_pass", _PyCFunction_CAST(gh_32092_kw_pass), METH_FASTCALL|METH_KEYWORDS, gh_32092_kw_pass__doc__}, - -static PyObject * -gh_32092_kw_pass_impl(PyObject *module, PyObject *pos, PyObject *args, - PyObject *kw); - -static PyObject * -gh_32092_kw_pass(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(pos), &_Py_ID(kw), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"pos", "kw", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "gh_32092_kw_pass", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - PyObject *pos; - PyObject *__clinic_args = NULL; - PyObject *kw = Py_None; - - args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf); - if (!args) { - goto exit; - } - pos = args[0]; - __clinic_args = args[1]; - if (!noptargs) { - goto skip_optional_kwonly; - } - kw = args[2]; -skip_optional_kwonly: - return_value = gh_32092_kw_pass_impl(module, pos, __clinic_args, kw); - -exit: - Py_XDECREF(__clinic_args); - return return_value; -} -/*[clinic end generated code: output=cebc2a5a0048c387 input=a9049054013a1b77]*/ diff --git a/Lib/test/test_clinic_functionality/setup.py b/Lib/test/test_clinic_functionality/setup.py deleted file mode 100644 index d5891a465cfefc..00000000000000 --- a/Lib/test/test_clinic_functionality/setup.py +++ /dev/null @@ -1,12 +0,0 @@ -from setuptools import setup, Extension -from test import support - - -def main(): - SOURCE = support.findfile('test_clinic_functionality.c', subdir='test_clinic_functionality') - module = Extension('test_clinic_functionality', sources=[SOURCE]) - setup(name='test_clinic_functionality', version='0.0', ext_modules=[module]) - - -if __name__ == '__main__': - main() diff --git a/Lib/test/test_clinic_functionality/test_clinic_functionality.c b/Lib/test/test_clinic_functionality/test_clinic_functionality.c deleted file mode 100644 index 0ba688e3d58199..00000000000000 --- a/Lib/test/test_clinic_functionality/test_clinic_functionality.c +++ /dev/null @@ -1,97 +0,0 @@ -#define PY_SSIZE_T_CLEAN -#include -#include "clinic/test_clinic_functionality.c.h" - - -/*[clinic input] -module clinic_functional_tester -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2ee8b0b242501b11]*/ - -/*[clinic input] -gh_32092_oob - - pos1: object - pos2: object - *varargs: object - kw1: object = None - kw2: object = None - -Proof-of-concept of GH-32092 OOB bug. - -Array index out-of-bound bug in function -`_PyArg_UnpackKeywordsWithVararg` . - -Calling this function by gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6) -to trigger this bug (crash). -Expected return: (1, 2, (3, 4), 5, 6) - -[clinic start generated code]*/ - -static PyObject * -gh_32092_oob_impl(PyObject *module, PyObject *pos1, PyObject *pos2, - PyObject *varargs, PyObject *kw1, PyObject *kw2) -/*[clinic end generated code: output=ee259c130054653f input=91d8e227acf93b02]*/ -{ - PyObject *tuple = PyTuple_New(5);; - PyTuple_SET_ITEM(tuple, 0, Py_NewRef(pos1)); - PyTuple_SET_ITEM(tuple, 1, Py_NewRef(pos2)); - PyTuple_SET_ITEM(tuple, 2, Py_NewRef(varargs)); - PyTuple_SET_ITEM(tuple, 3, Py_NewRef(kw1)); - PyTuple_SET_ITEM(tuple, 4, Py_NewRef(kw2)); - return tuple; -} - -/*[clinic input] -gh_32092_kw_pass - - pos: object - *args: object - kw: object = None - -Proof-of-concept of GH-32092 keyword args passing bug. - -The calculation of `noptargs` in AC-generated function -`builtin_kw_pass_poc` is incorrect. - -Calling this function by gh_32092_kw_pass(1, 2, 3) -to trigger this bug (crash). -Expected return: (1, (2, 3)) - -[clinic start generated code]*/ - -static PyObject * -gh_32092_kw_pass_impl(PyObject *module, PyObject *pos, PyObject *args, - PyObject *kw) -/*[clinic end generated code: output=4a2bbe4f7c8604e9 input=c51b7572ac09f193]*/ -{ - PyObject *tuple = PyTuple_New(3);; - PyTuple_SET_ITEM(tuple, 0, Py_NewRef(pos)); - PyTuple_SET_ITEM(tuple, 1, Py_NewRef(args)); - PyTuple_SET_ITEM(tuple, 2, Py_NewRef(kw)); - return tuple; -} - -static PyMethodDef tester_methods[] = { - GH_32092_OOB_METHODDEF - GH_32092_KW_PASS_METHODDEF - {NULL, NULL} -}; - -static struct PyModuleDef clinic_functional_tester_module = { - PyModuleDef_HEAD_INIT, - "clinic_functional_tester", - NULL, - 0, - tester_methods, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit_test_clinic_functionality(void) -{ - return PyModule_Create(&clinic_functional_tester_module); -} diff --git a/Lib/test/test_clinic_functionality/test_clinic_functionality.py b/Lib/test/test_clinic_functionality/test_clinic_functionality.py deleted file mode 100644 index 53cad36bfb3b29..00000000000000 --- a/Lib/test/test_clinic_functionality/test_clinic_functionality.py +++ /dev/null @@ -1,128 +0,0 @@ -import os.path -import sys -import unittest -import subprocess -import textwrap -from test import support -from test.support import os_helper - - -MS_WINDOWS = (sys.platform == 'win32') -SETUP = support.findfile('setup.py', subdir='test_clinic_functionality') -MOD_NAME = 'test_clinic_functionality' - - -def _run_cmd(operation, cmd, verbose=False): - if verbose: - print(f'{operation}:', ' '.join(cmd)) - subprocess.run(cmd, check=True) - else: - proc = subprocess.run(cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True) - if proc.returncode: - print(proc.stdout, end='') - self.fail(f'{operation} failed with exit code {proc.returncode}') - - -class EnvInitializer: - """Build the module before test and clear the files after test.""" - python = '' - verbose = support.verbose - - def run_cmd(self, operation, cmd): - _run_cmd(operation, cmd, self.verbose) - - def _setup_env(self): - venv_dir = 'env' - - # Create virtual environment to get setuptools - cmd = [sys.executable, '-X', 'dev', '-m', 'venv', venv_dir] - self.run_cmd('Setup venv', cmd) - - # Get the Python executable of the venv - python_exe = 'python' - if sys.executable.endswith('.exe'): - python_exe += '.exe' - if MS_WINDOWS: - self.python = os.path.join(venv_dir, 'Scripts', python_exe) - else: - self.python = os.path.join(venv_dir, 'bin', python_exe) - - # Build module - cmd = [self.python, '-X', 'dev', SETUP, 'build_ext', '--verbose'] - self.run_cmd('Build', cmd) - - # Install module - cmd = [self.python, '-X', 'dev', SETUP, 'install'] - self.run_cmd('Install', cmd) - - def setup_env(self): - # Build in a temporary directory - with os_helper.temp_cwd(): - self._setup_env() - yield - - def __init__(self): - if self.verbose: - print() - print('Setup test environment') - self.env = self.setup_env() - next(self.env) - - def __del__(self): - if self.verbose: - print('Clear test environment') - try: - next(self.env) - except StopIteration: - pass - except Exception as e: - raise e - - -env = None - - -def setUpModule(): - global env - env = EnvInitializer() - - -def tearDownModule(): - global env - del env - - -@support.requires_subprocess() -@support.requires_venv_with_pip() -class TestClinicFunctional(unittest.TestCase): - verbose = support.verbose - - def run_cmd(self, operation, cmd): - _run_cmd(operation, cmd, self.verbose) - - def exec_script(self, script): - script = textwrap.dedent(script) - global env - python = env.python - cmd = [python, '-c', script] - self.run_cmd('Test', cmd) - - def assert_func_result(self, func_str, expected_result): - script = f'''\ - import {MOD_NAME} as mod - assert(mod.{func_str} == {expected_result}) - ''' - self.exec_script(script) - - def test_gh_32092_oob(self): - self.assert_func_result('gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6)', '(1, 2, (3, 4), 5, 6))') - - def test_gh_32092_kw_pass(self): - self.assert_func_result('gh_32092_kw_pass(1, 2, 3)', '(1, (2, 3))') - - -if __name__ == "__main__": - unittest.main() From fac5b7772dee54cd062fc0e8bb659ae39e311c0e Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Tue, 23 Aug 2022 15:36:42 +0800 Subject: [PATCH 04/29] Add functional test for Argument Clinic --- Include/internal/pycore_global_strings.h | 5 + .../internal/pycore_runtime_init_generated.h | 35 ++++ Lib/test/test_clinic_functionality.py | 16 ++ Modules/Setup.stdlib.in | 1 + Modules/_testclinicfunctionality.c | 105 +++++++++++ Modules/clinic/_testclinicfunctionality.c.h | 165 ++++++++++++++++++ Python/stdlib_module_names.h | 1 + configure | 40 +++++ configure.ac | 1 + 9 files changed, 369 insertions(+) create mode 100644 Lib/test/test_clinic_functionality.py create mode 100644 Modules/_testclinicfunctionality.c create mode 100644 Modules/clinic/_testclinicfunctionality.c.h diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index aada220395023d..2a3261120744b5 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -425,6 +425,9 @@ struct _Py_global_strings { STRUCT_FOR_ID(keyfile) STRUCT_FOR_ID(keys) STRUCT_FOR_ID(kind) + STRUCT_FOR_ID(kw) + STRUCT_FOR_ID(kw1) + STRUCT_FOR_ID(kw2) STRUCT_FOR_ID(lambda) STRUCT_FOR_ID(last) STRUCT_FOR_ID(last_node) @@ -516,6 +519,8 @@ struct _Py_global_strings { STRUCT_FOR_ID(pid) STRUCT_FOR_ID(policy) STRUCT_FOR_ID(pos) + STRUCT_FOR_ID(pos1) + STRUCT_FOR_ID(pos2) STRUCT_FOR_ID(print_file_and_line) STRUCT_FOR_ID(priority) STRUCT_FOR_ID(progress) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 09890cd812015b..ebf0395f121463 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -934,6 +934,9 @@ extern "C" { INIT_ID(keyfile), \ INIT_ID(keys), \ INIT_ID(kind), \ + INIT_ID(kw), \ + INIT_ID(kw1), \ + INIT_ID(kw2), \ INIT_ID(lambda), \ INIT_ID(last), \ INIT_ID(last_node), \ @@ -1025,6 +1028,8 @@ extern "C" { INIT_ID(pid), \ INIT_ID(policy), \ INIT_ID(pos), \ + INIT_ID(pos1), \ + INIT_ID(pos2), \ INIT_ID(print_file_and_line), \ INIT_ID(priority), \ INIT_ID(progress), \ @@ -2170,6 +2175,12 @@ _PyUnicode_InitStaticStrings(void) { PyUnicode_InternInPlace(&string); string = &_Py_ID(kind); PyUnicode_InternInPlace(&string); + string = &_Py_ID(kw); + PyUnicode_InternInPlace(&string); + string = &_Py_ID(kw1); + PyUnicode_InternInPlace(&string); + string = &_Py_ID(kw2); + PyUnicode_InternInPlace(&string); string = &_Py_ID(lambda); PyUnicode_InternInPlace(&string); string = &_Py_ID(last); @@ -2352,6 +2363,10 @@ _PyUnicode_InitStaticStrings(void) { PyUnicode_InternInPlace(&string); string = &_Py_ID(pos); PyUnicode_InternInPlace(&string); + string = &_Py_ID(pos1); + PyUnicode_InternInPlace(&string); + string = &_Py_ID(pos2); + PyUnicode_InternInPlace(&string); string = &_Py_ID(print_file_and_line); PyUnicode_InternInPlace(&string); string = &_Py_ID(priority); @@ -6263,6 +6278,18 @@ _PyStaticObjects_CheckRefcnt(void) { _PyObject_Dump((PyObject *)&_Py_ID(kind)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); }; + if (Py_REFCNT((PyObject *)&_Py_ID(kw)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(kw)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(kw1)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(kw1)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(kw2)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(kw2)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; if (Py_REFCNT((PyObject *)&_Py_ID(lambda)) < _PyObject_IMMORTAL_REFCNT) { _PyObject_Dump((PyObject *)&_Py_ID(lambda)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); @@ -6627,6 +6654,14 @@ _PyStaticObjects_CheckRefcnt(void) { _PyObject_Dump((PyObject *)&_Py_ID(pos)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); }; + if (Py_REFCNT((PyObject *)&_Py_ID(pos1)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(pos1)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; + if (Py_REFCNT((PyObject *)&_Py_ID(pos2)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(pos2)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; if (Py_REFCNT((PyObject *)&_Py_ID(print_file_and_line)) < _PyObject_IMMORTAL_REFCNT) { _PyObject_Dump((PyObject *)&_Py_ID(print_file_and_line)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); diff --git a/Lib/test/test_clinic_functionality.py b/Lib/test/test_clinic_functionality.py new file mode 100644 index 00000000000000..0356a4437989b1 --- /dev/null +++ b/Lib/test/test_clinic_functionality.py @@ -0,0 +1,16 @@ +import unittest +from test.support import import_helper + +ac_tester = import_helper.import_module('_testclinicfunctionality') + + +class TestClinicFunctionality(unittest.TestCase): + def test_gh_32092_oob(self): + res = ac_tester.gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6) + expect = (1, 2, (3, 4), 5, 6) + self.assertEqual(res, expect) + + def test_gh_32092_kw_pass(self): + res = ac_tester.gh_32092_kw_pass(1, 2, 3) + expect = (1, (2, 3), None) + self.assertEqual(res, expect) diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index ac8959ebea5bf2..1032522fb9c47d 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -170,6 +170,7 @@ @MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c @MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c @MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/unicode.c +@MODULE__TESTCLINICFUNCTIONALITY_TRUE@_testclinicfunctionality _testclinicfunctionality.c # Some testing modules MUST be built as shared libraries. *shared* diff --git a/Modules/_testclinicfunctionality.c b/Modules/_testclinicfunctionality.c new file mode 100644 index 00000000000000..a23ba318a6cea4 --- /dev/null +++ b/Modules/_testclinicfunctionality.c @@ -0,0 +1,105 @@ +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + +/* Always enable assertions */ +#undef NDEBUG + +#define PY_SSIZE_T_CLEAN + +#include "Python.h" + +#include "clinic/_testclinicfunctionality.c.h" + +/*[clinic input] +module _testclinicfunctionality +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=19bd80db1aefb188]*/ + +/*[clinic input] +gh_32092_oob + + pos1: object + pos2: object + *varargs: object + kw1: object = None + kw2: object = None + +Proof-of-concept of GH-32092 OOB bug. + +Array index out-of-bound bug in function +`_PyArg_UnpackKeywordsWithVararg` . + +Calling this function by gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6) +to trigger this bug (crash). +Expected return: (1, 2, (3, 4), 5, 6) + +[clinic start generated code]*/ + +static PyObject * +gh_32092_oob_impl(PyObject *module, PyObject *pos1, PyObject *pos2, + PyObject *varargs, PyObject *kw1, PyObject *kw2) +/*[clinic end generated code: output=ee259c130054653f input=91d8e227acf93b02]*/ +{ + PyObject *tuple = PyTuple_New(5); + PyTuple_SET_ITEM(tuple, 0, Py_NewRef(pos1)); + PyTuple_SET_ITEM(tuple, 1, Py_NewRef(pos2)); + PyTuple_SET_ITEM(tuple, 2, Py_NewRef(varargs)); + PyTuple_SET_ITEM(tuple, 3, Py_NewRef(kw1)); + PyTuple_SET_ITEM(tuple, 4, Py_NewRef(kw2)); + return tuple; +} + +/*[clinic input] +gh_32092_kw_pass + + pos: object + *args: object + kw: object = None + +Proof-of-concept of GH-32092 keyword args passing bug. + +The calculation of `noptargs` in AC-generated function +`builtin_kw_pass_poc` is incorrect. + +Calling this function by gh_32092_kw_pass(1, 2, 3) +to trigger this bug (crash). +Expected return: (1, (2, 3), None) + +[clinic start generated code]*/ + +static PyObject * +gh_32092_kw_pass_impl(PyObject *module, PyObject *pos, PyObject *args, + PyObject *kw) +/*[clinic end generated code: output=4a2bbe4f7c8604e9 input=5fc48f72f49193b6]*/ +{ + PyObject *tuple = PyTuple_New(3); + PyTuple_SET_ITEM(tuple, 0, Py_NewRef(pos)); + PyTuple_SET_ITEM(tuple, 1, Py_NewRef(args)); + PyTuple_SET_ITEM(tuple, 2, Py_NewRef(kw)); + return tuple; +} + +static PyMethodDef tester_methods[] = { + GH_32092_OOB_METHODDEF + GH_32092_KW_PASS_METHODDEF + {NULL, NULL} +}; + +static struct PyModuleDef _testclinicfunctionality_module = { + PyModuleDef_HEAD_INIT, + "_testclinicfunctionality", + NULL, + 0, + tester_methods, + NULL, + NULL, + NULL, + NULL +}; + +PyMODINIT_FUNC +PyInit__testclinicfunctionality(void) +{ + return PyModule_Create(&_testclinicfunctionality_module); +} diff --git a/Modules/clinic/_testclinicfunctionality.c.h b/Modules/clinic/_testclinicfunctionality.c.h new file mode 100644 index 00000000000000..60c04a3ee96147 --- /dev/null +++ b/Modules/clinic/_testclinicfunctionality.c.h @@ -0,0 +1,165 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() +#endif + + +PyDoc_STRVAR(gh_32092_oob__doc__, +"gh_32092_oob($module, /, pos1, pos2, *varargs, kw1=None, kw2=None)\n" +"--\n" +"\n" +"Proof-of-concept of GH-32092 OOB bug.\n" +"\n" +"Array index out-of-bound bug in function\n" +"`_PyArg_UnpackKeywordsWithVararg` .\n" +"\n" +"Calling this function by gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6)\n" +"to trigger this bug (crash).\n" +"Expected return: (1, 2, (3, 4), 5, 6)"); + +#define GH_32092_OOB_METHODDEF \ + {"gh_32092_oob", _PyCFunction_CAST(gh_32092_oob), METH_FASTCALL|METH_KEYWORDS, gh_32092_oob__doc__}, + +static PyObject * +gh_32092_oob_impl(PyObject *module, PyObject *pos1, PyObject *pos2, + PyObject *varargs, PyObject *kw1, PyObject *kw2); + +static PyObject * +gh_32092_oob(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(pos1), &_Py_ID(pos2), &_Py_ID(kw1), &_Py_ID(kw2), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"pos1", "pos2", "kw1", "kw2", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "gh_32092_oob", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + PyObject *pos1; + PyObject *pos2; + PyObject *varargs = NULL; + PyObject *kw1 = Py_None; + PyObject *kw2 = Py_None; + + args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, 2, argsbuf); + if (!args) { + goto exit; + } + pos1 = args[0]; + pos2 = args[1]; + varargs = args[2]; + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[3]) { + kw1 = args[3]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + kw2 = args[4]; +skip_optional_kwonly: + return_value = gh_32092_oob_impl(module, pos1, pos2, varargs, kw1, kw2); + +exit: + Py_XDECREF(varargs); + return return_value; +} + +PyDoc_STRVAR(gh_32092_kw_pass__doc__, +"gh_32092_kw_pass($module, /, pos, *args, kw=None)\n" +"--\n" +"\n" +"Proof-of-concept of GH-32092 keyword args passing bug.\n" +"\n" +"The calculation of `noptargs` in AC-generated function\n" +"`builtin_kw_pass_poc` is incorrect.\n" +"\n" +"Calling this function by gh_32092_kw_pass(1, 2, 3)\n" +"to trigger this bug (crash).\n" +"Expected return: (1, (2, 3), None)"); + +#define GH_32092_KW_PASS_METHODDEF \ + {"gh_32092_kw_pass", _PyCFunction_CAST(gh_32092_kw_pass), METH_FASTCALL|METH_KEYWORDS, gh_32092_kw_pass__doc__}, + +static PyObject * +gh_32092_kw_pass_impl(PyObject *module, PyObject *pos, PyObject *args, + PyObject *kw); + +static PyObject * +gh_32092_kw_pass(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(pos), &_Py_ID(kw), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"pos", "kw", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "gh_32092_kw_pass", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *pos; + PyObject *__clinic_args = NULL; + PyObject *kw = Py_None; + + args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf); + if (!args) { + goto exit; + } + pos = args[0]; + __clinic_args = args[1]; + if (!noptargs) { + goto skip_optional_kwonly; + } + kw = args[2]; +skip_optional_kwonly: + return_value = gh_32092_kw_pass_impl(module, pos, __clinic_args, kw); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} +/*[clinic end generated code: output=15c1dca3a5c1ae38 input=a9049054013a1b77]*/ diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h index b28156608d1b80..c3423ed20a388c 100644 --- a/Python/stdlib_module_names.h +++ b/Python/stdlib_module_names.h @@ -77,6 +77,7 @@ static const char* _Py_stdlib_module_names[] = { "_strptime", "_struct", "_symtable", +"_testclinicfunctionality", "_thread", "_threading_local", "_tkinter", diff --git a/configure b/configure index 1801f806ae137f..21f005a51c02e5 100755 --- a/configure +++ b/configure @@ -642,6 +642,8 @@ MODULE__TESTBUFFER_FALSE MODULE__TESTBUFFER_TRUE MODULE__TESTINTERNALCAPI_FALSE MODULE__TESTINTERNALCAPI_TRUE +MODULE__TESTCLINICFUNCTIONALITY_FALSE +MODULE__TESTCLINICFUNCTIONALITY_TRUE MODULE__TESTCAPI_FALSE MODULE__TESTCAPI_TRUE MODULE__HASHLIB_FALSE @@ -27625,6 +27627,40 @@ fi $as_echo "$py_cv_module__testcapi" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _testclinicfunctionality" >&5 +$as_echo_n "checking for stdlib extension module _testclinicfunctionality... " >&6; } + if test "$py_cv_module__testclinicfunctionality" != "n/a"; then : + + if test "$TEST_MODULES" = yes; then : + if true; then : + py_cv_module__testclinicfunctionality=yes +else + py_cv_module__testclinicfunctionality=missing +fi +else + py_cv_module__testclinicfunctionality=disabled +fi + +fi + as_fn_append MODULE_BLOCK "MODULE__TESTCLINICFUNCTIONALITY_STATE=$py_cv_module__testclinicfunctionality$as_nl" + if test "x$py_cv_module__testclinicfunctionality" = xyes; then : + + + + +fi + if test "$py_cv_module__testclinicfunctionality" = yes; then + MODULE__TESTCLINICFUNCTIONALITY_TRUE= + MODULE__TESTCLINICFUNCTIONALITY_FALSE='#' +else + MODULE__TESTCLINICFUNCTIONALITY_TRUE='#' + MODULE__TESTCLINICFUNCTIONALITY_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__testclinicfunctionality" >&5 +$as_echo "$py_cv_module__testclinicfunctionality" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _testinternalcapi" >&5 $as_echo_n "checking for stdlib extension module _testinternalcapi... " >&6; } if test "$py_cv_module__testinternalcapi" != "n/a"; then : @@ -28344,6 +28380,10 @@ if test -z "${MODULE__TESTCAPI_TRUE}" && test -z "${MODULE__TESTCAPI_FALSE}"; th as_fn_error $? "conditional \"MODULE__TESTCAPI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__TESTCLINICFUNCTIONALITY_TRUE}" && test -z "${MODULE__TESTCLINICFUNCTIONALITY_FALSE}"; then + as_fn_error $? "conditional \"MODULE__TESTCLINICFUNCTIONALITY\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__TESTINTERNALCAPI_TRUE}" && test -z "${MODULE__TESTINTERNALCAPI_FALSE}"; then as_fn_error $? "conditional \"MODULE__TESTINTERNALCAPI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index bb9fec07242f8e..2daf78d4cd07d0 100644 --- a/configure.ac +++ b/configure.ac @@ -7301,6 +7301,7 @@ PY_STDLIB_MOD([_hashlib], [], [test "$ac_cv_working_openssl_hashlib" = yes], dnl test modules PY_STDLIB_MOD([_testcapi], [test "$TEST_MODULES" = yes]) +PY_STDLIB_MOD([_testclinicfunctionality], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testinternalcapi], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testbuffer], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testimportmultiple], [test "$TEST_MODULES" = yes], [test "$ac_cv_func_dlopen" = yes]) From 962434c9ca94eff00d54979caf6ba1cf07d5b5ae Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Tue, 23 Aug 2022 20:17:20 +0800 Subject: [PATCH 05/29] Add testcases written in C --- Lib/test/test_clinic_functionality.py | 5 +++++ Modules/_testclinicfunctionality.c | 13 +++++++++++++ Modules/clinic/_testclinicfunctionality.c.h | 19 ++++++++++++++++++- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_clinic_functionality.py b/Lib/test/test_clinic_functionality.py index 0356a4437989b1..6bedd675875c26 100644 --- a/Lib/test/test_clinic_functionality.py +++ b/Lib/test/test_clinic_functionality.py @@ -14,3 +14,8 @@ def test_gh_32092_kw_pass(self): res = ac_tester.gh_32092_kw_pass(1, 2, 3) expect = (1, (2, 3), None) self.assertEqual(res, expect) + + +class TestClinicFunctionalityC(unittest.TestCase): + locals().update((name, getattr(ac_tester, name)) + for name in dir(ac_tester) if name.startswith('test_')) diff --git a/Modules/_testclinicfunctionality.c b/Modules/_testclinicfunctionality.c index a23ba318a6cea4..58bfac6eb3f52f 100644 --- a/Modules/_testclinicfunctionality.c +++ b/Modules/_testclinicfunctionality.c @@ -16,6 +16,18 @@ module _testclinicfunctionality [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=19bd80db1aefb188]*/ +/*[clinic input] +test_empty_function + +[clinic start generated code]*/ + +static PyObject * +test_empty_function_impl(PyObject *module) +/*[clinic end generated code: output=0f8aeb3ddced55cb input=0dd7048651ad4ae4]*/ +{ + Py_RETURN_NONE; +}; + /*[clinic input] gh_32092_oob @@ -81,6 +93,7 @@ gh_32092_kw_pass_impl(PyObject *module, PyObject *pos, PyObject *args, } static PyMethodDef tester_methods[] = { + TEST_EMPTY_FUNCTION_METHODDEF GH_32092_OOB_METHODDEF GH_32092_KW_PASS_METHODDEF {NULL, NULL} diff --git a/Modules/clinic/_testclinicfunctionality.c.h b/Modules/clinic/_testclinicfunctionality.c.h index 60c04a3ee96147..781546036cda7e 100644 --- a/Modules/clinic/_testclinicfunctionality.c.h +++ b/Modules/clinic/_testclinicfunctionality.c.h @@ -8,6 +8,23 @@ preserve #endif +PyDoc_STRVAR(test_empty_function__doc__, +"test_empty_function($module, /)\n" +"--\n" +"\n"); + +#define TEST_EMPTY_FUNCTION_METHODDEF \ + {"test_empty_function", (PyCFunction)test_empty_function, METH_NOARGS, test_empty_function__doc__}, + +static PyObject * +test_empty_function_impl(PyObject *module); + +static PyObject * +test_empty_function(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return test_empty_function_impl(module); +} + PyDoc_STRVAR(gh_32092_oob__doc__, "gh_32092_oob($module, /, pos1, pos2, *varargs, kw1=None, kw2=None)\n" "--\n" @@ -162,4 +179,4 @@ gh_32092_kw_pass(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb Py_XDECREF(__clinic_args); return return_value; } -/*[clinic end generated code: output=15c1dca3a5c1ae38 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=da33e7aa2f9377db input=a9049054013a1b77]*/ From b93b2aedfbb64501c653ce78bdfe9d0ffecacda8 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Tue, 25 Oct 2022 22:56:07 +0800 Subject: [PATCH 06/29] Rename _testclinicfunctionality.c to _testclinic.c --- Lib/test/test_clinic_functionality.py | 2 +- Modules/Setup.stdlib.in | 2 +- ...estclinicfunctionality.c => _testclinic.c} | 14 +++---- ...linicfunctionality.c.h => _testclinic.c.h} | 0 Python/stdlib_module_names.h | 2 +- configure | 38 +++++++++---------- configure.ac | 2 +- 7 files changed, 30 insertions(+), 30 deletions(-) rename Modules/{_testclinicfunctionality.c => _testclinic.c} (87%) rename Modules/clinic/{_testclinicfunctionality.c.h => _testclinic.c.h} (100%) diff --git a/Lib/test/test_clinic_functionality.py b/Lib/test/test_clinic_functionality.py index 6bedd675875c26..7b1328b7920c09 100644 --- a/Lib/test/test_clinic_functionality.py +++ b/Lib/test/test_clinic_functionality.py @@ -1,7 +1,7 @@ import unittest from test.support import import_helper -ac_tester = import_helper.import_module('_testclinicfunctionality') +ac_tester = import_helper.import_module('_testclinic') class TestClinicFunctionality(unittest.TestCase): diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 1032522fb9c47d..345a7ac3097dad 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -170,7 +170,7 @@ @MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c @MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c @MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/unicode.c -@MODULE__TESTCLINICFUNCTIONALITY_TRUE@_testclinicfunctionality _testclinicfunctionality.c +@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c # Some testing modules MUST be built as shared libraries. *shared* diff --git a/Modules/_testclinicfunctionality.c b/Modules/_testclinic.c similarity index 87% rename from Modules/_testclinicfunctionality.c rename to Modules/_testclinic.c index 58bfac6eb3f52f..481fd8a9de9744 100644 --- a/Modules/_testclinicfunctionality.c +++ b/Modules/_testclinic.c @@ -9,12 +9,12 @@ #include "Python.h" -#include "clinic/_testclinicfunctionality.c.h" +#include "clinic/_testclinic.c.h" /*[clinic input] -module _testclinicfunctionality +module _testclinic [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=19bd80db1aefb188]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d4981b80d6efdb12]*/ /*[clinic input] test_empty_function @@ -99,9 +99,9 @@ static PyMethodDef tester_methods[] = { {NULL, NULL} }; -static struct PyModuleDef _testclinicfunctionality_module = { +static struct PyModuleDef _testclinic_module = { PyModuleDef_HEAD_INIT, - "_testclinicfunctionality", + "_testclinic", NULL, 0, tester_methods, @@ -112,7 +112,7 @@ static struct PyModuleDef _testclinicfunctionality_module = { }; PyMODINIT_FUNC -PyInit__testclinicfunctionality(void) +PyInit__testclinic(void) { - return PyModule_Create(&_testclinicfunctionality_module); + return PyModule_Create(&_testclinic_module); } diff --git a/Modules/clinic/_testclinicfunctionality.c.h b/Modules/clinic/_testclinic.c.h similarity index 100% rename from Modules/clinic/_testclinicfunctionality.c.h rename to Modules/clinic/_testclinic.c.h diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h index c3423ed20a388c..67a4d01262e082 100644 --- a/Python/stdlib_module_names.h +++ b/Python/stdlib_module_names.h @@ -77,7 +77,7 @@ static const char* _Py_stdlib_module_names[] = { "_strptime", "_struct", "_symtable", -"_testclinicfunctionality", +"_testclinic", "_thread", "_threading_local", "_tkinter", diff --git a/configure b/configure index 21f005a51c02e5..494b022f251dd8 100755 --- a/configure +++ b/configure @@ -642,8 +642,8 @@ MODULE__TESTBUFFER_FALSE MODULE__TESTBUFFER_TRUE MODULE__TESTINTERNALCAPI_FALSE MODULE__TESTINTERNALCAPI_TRUE -MODULE__TESTCLINICFUNCTIONALITY_FALSE -MODULE__TESTCLINICFUNCTIONALITY_TRUE +MODULE__TESTCLINIC_FALSE +MODULE__TESTCLINIC_TRUE MODULE__TESTCAPI_FALSE MODULE__TESTCAPI_TRUE MODULE__HASHLIB_FALSE @@ -27627,38 +27627,38 @@ fi $as_echo "$py_cv_module__testcapi" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _testclinicfunctionality" >&5 -$as_echo_n "checking for stdlib extension module _testclinicfunctionality... " >&6; } - if test "$py_cv_module__testclinicfunctionality" != "n/a"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _testclinic" >&5 +$as_echo_n "checking for stdlib extension module _testclinic... " >&6; } + if test "$py_cv_module__testclinic" != "n/a"; then : if test "$TEST_MODULES" = yes; then : if true; then : - py_cv_module__testclinicfunctionality=yes + py_cv_module__testclinic=yes else - py_cv_module__testclinicfunctionality=missing + py_cv_module__testclinic=missing fi else - py_cv_module__testclinicfunctionality=disabled + py_cv_module__testclinic=disabled fi fi - as_fn_append MODULE_BLOCK "MODULE__TESTCLINICFUNCTIONALITY_STATE=$py_cv_module__testclinicfunctionality$as_nl" - if test "x$py_cv_module__testclinicfunctionality" = xyes; then : + as_fn_append MODULE_BLOCK "MODULE__TESTCLINIC_STATE=$py_cv_module__testclinic$as_nl" + if test "x$py_cv_module__testclinic" = xyes; then : fi - if test "$py_cv_module__testclinicfunctionality" = yes; then - MODULE__TESTCLINICFUNCTIONALITY_TRUE= - MODULE__TESTCLINICFUNCTIONALITY_FALSE='#' + if test "$py_cv_module__testclinic" = yes; then + MODULE__TESTCLINIC_TRUE= + MODULE__TESTCLINIC_FALSE='#' else - MODULE__TESTCLINICFUNCTIONALITY_TRUE='#' - MODULE__TESTCLINICFUNCTIONALITY_FALSE= + MODULE__TESTCLINIC_TRUE='#' + MODULE__TESTCLINIC_FALSE= fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__testclinicfunctionality" >&5 -$as_echo "$py_cv_module__testclinicfunctionality" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__testclinic" >&5 +$as_echo "$py_cv_module__testclinic" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _testinternalcapi" >&5 @@ -28380,8 +28380,8 @@ if test -z "${MODULE__TESTCAPI_TRUE}" && test -z "${MODULE__TESTCAPI_FALSE}"; th as_fn_error $? "conditional \"MODULE__TESTCAPI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE__TESTCLINICFUNCTIONALITY_TRUE}" && test -z "${MODULE__TESTCLINICFUNCTIONALITY_FALSE}"; then - as_fn_error $? "conditional \"MODULE__TESTCLINICFUNCTIONALITY\" was never defined. +if test -z "${MODULE__TESTCLINIC_TRUE}" && test -z "${MODULE__TESTCLINIC_FALSE}"; then + as_fn_error $? "conditional \"MODULE__TESTCLINIC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${MODULE__TESTINTERNALCAPI_TRUE}" && test -z "${MODULE__TESTINTERNALCAPI_FALSE}"; then diff --git a/configure.ac b/configure.ac index 2daf78d4cd07d0..1d14fb310da5fa 100644 --- a/configure.ac +++ b/configure.ac @@ -7301,7 +7301,7 @@ PY_STDLIB_MOD([_hashlib], [], [test "$ac_cv_working_openssl_hashlib" = yes], dnl test modules PY_STDLIB_MOD([_testcapi], [test "$TEST_MODULES" = yes]) -PY_STDLIB_MOD([_testclinicfunctionality], [test "$TEST_MODULES" = yes]) +PY_STDLIB_MOD([_testclinic], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testinternalcapi], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testbuffer], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testimportmultiple], [test "$TEST_MODULES" = yes], [test "$ac_cv_func_dlopen" = yes]) From 35c5f137c0176fe9328af944e894245a24a6a49f Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Tue, 25 Oct 2022 23:02:48 +0800 Subject: [PATCH 07/29] Add _testclinic to stdlib IGNORE list --- Python/stdlib_module_names.h | 1 - Tools/scripts/generate_stdlib_module_names.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h index 67a4d01262e082..b28156608d1b80 100644 --- a/Python/stdlib_module_names.h +++ b/Python/stdlib_module_names.h @@ -77,7 +77,6 @@ static const char* _Py_stdlib_module_names[] = { "_strptime", "_struct", "_symtable", -"_testclinic", "_thread", "_threading_local", "_tkinter", diff --git a/Tools/scripts/generate_stdlib_module_names.py b/Tools/scripts/generate_stdlib_module_names.py index 92100bd06509a5..80fbf1e2ba6ea2 100644 --- a/Tools/scripts/generate_stdlib_module_names.py +++ b/Tools/scripts/generate_stdlib_module_names.py @@ -27,6 +27,7 @@ '_ctypes_test', '_testbuffer', '_testcapi', + '_testclinic', '_testconsole', '_testimportmultiple', '_testinternalcapi', From 86703dea483ef5d1d916ac39f82b44ea8ef8e5f9 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Tue, 25 Oct 2022 23:03:10 +0800 Subject: [PATCH 08/29] Merge TestClinicFunctionalityC class into TestClinicFunctionality --- Lib/test/test_clinic_functionality.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_clinic_functionality.py b/Lib/test/test_clinic_functionality.py index 7b1328b7920c09..21926f2c7a6c92 100644 --- a/Lib/test/test_clinic_functionality.py +++ b/Lib/test/test_clinic_functionality.py @@ -5,6 +5,9 @@ class TestClinicFunctionality(unittest.TestCase): + locals().update((name, getattr(ac_tester, name)) + for name in dir(ac_tester) if name.startswith('test_')) + def test_gh_32092_oob(self): res = ac_tester.gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6) expect = (1, 2, (3, 4), 5, 6) @@ -14,8 +17,3 @@ def test_gh_32092_kw_pass(self): res = ac_tester.gh_32092_kw_pass(1, 2, 3) expect = (1, (2, 3), None) self.assertEqual(res, expect) - - -class TestClinicFunctionalityC(unittest.TestCase): - locals().update((name, getattr(ac_tester, name)) - for name in dir(ac_tester) if name.startswith('test_')) From e66d60b68259b11ccd9c8decfb7b990680ecf6e4 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Tue, 25 Oct 2022 23:14:52 +0800 Subject: [PATCH 09/29] Format code in _testclinic.c --- Modules/_testclinic.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index 481fd8a9de9744..6c7da3157caa94 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -93,22 +93,17 @@ gh_32092_kw_pass_impl(PyObject *module, PyObject *pos, PyObject *args, } static PyMethodDef tester_methods[] = { - TEST_EMPTY_FUNCTION_METHODDEF - GH_32092_OOB_METHODDEF - GH_32092_KW_PASS_METHODDEF - {NULL, NULL} + TEST_EMPTY_FUNCTION_METHODDEF + GH_32092_OOB_METHODDEF + GH_32092_KW_PASS_METHODDEF + {NULL, NULL} }; static struct PyModuleDef _testclinic_module = { - PyModuleDef_HEAD_INIT, - "_testclinic", - NULL, - 0, - tester_methods, - NULL, - NULL, - NULL, - NULL + PyModuleDef_HEAD_INIT, + .m_name = "_testclinic", + .m_size = 0, + .m_methods = tester_methods, }; PyMODINIT_FUNC From f1fb3778dd40e9ea7fc35547f53bf1744740ced0 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Wed, 26 Oct 2022 10:54:37 +0800 Subject: [PATCH 10/29] Merge test_clinic_functionality.py into test_clinic.py --- Lib/test/test_clinic.py | 20 +++++++++++++++++++- Lib/test/test_clinic_functionality.py | 19 ------------------- 2 files changed, 19 insertions(+), 20 deletions(-) delete mode 100644 Lib/test/test_clinic_functionality.py diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 4aa9691a4829d1..344068e18a7121 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -3,7 +3,7 @@ # Licensed to the PSF under a contributor agreement. from test import support, test_tools -from test.support import os_helper +from test.support import import_helper, os_helper from unittest import TestCase import collections import inspect @@ -820,5 +820,23 @@ def test_external(self): self.assertEqual(new_mtime_ns, old_mtime_ns) +ac_tester = import_helper.import_module('_testclinic') + + +class TestClinicFunctionality(unittest.TestCase): + locals().update((name, getattr(ac_tester, name)) + for name in dir(ac_tester) if name.startswith('test_')) + + def test_gh_32092_oob(self): + res = ac_tester.gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6) + expect = (1, 2, (3, 4), 5, 6) + self.assertEqual(res, expect) + + def test_gh_32092_kw_pass(self): + res = ac_tester.gh_32092_kw_pass(1, 2, 3) + expect = (1, (2, 3), None) + self.assertEqual(res, expect) + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_clinic_functionality.py b/Lib/test/test_clinic_functionality.py deleted file mode 100644 index 21926f2c7a6c92..00000000000000 --- a/Lib/test/test_clinic_functionality.py +++ /dev/null @@ -1,19 +0,0 @@ -import unittest -from test.support import import_helper - -ac_tester = import_helper.import_module('_testclinic') - - -class TestClinicFunctionality(unittest.TestCase): - locals().update((name, getattr(ac_tester, name)) - for name in dir(ac_tester) if name.startswith('test_')) - - def test_gh_32092_oob(self): - res = ac_tester.gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6) - expect = (1, 2, (3, 4), 5, 6) - self.assertEqual(res, expect) - - def test_gh_32092_kw_pass(self): - res = ac_tester.gh_32092_kw_pass(1, 2, 3) - expect = (1, (2, 3), None) - self.assertEqual(res, expect) From 449c8feccfa5d7cf9cc32edec58972436845e5b6 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Wed, 26 Oct 2022 10:56:24 +0800 Subject: [PATCH 11/29] Simplify testcases --- Modules/_testclinic.c | 20 ++++---------------- Modules/clinic/_testclinic.c.h | 8 +++----- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index 6c7da3157caa94..af07b80a7e88da 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -44,22 +44,15 @@ Array index out-of-bound bug in function Calling this function by gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6) to trigger this bug (crash). -Expected return: (1, 2, (3, 4), 5, 6) [clinic start generated code]*/ static PyObject * gh_32092_oob_impl(PyObject *module, PyObject *pos1, PyObject *pos2, PyObject *varargs, PyObject *kw1, PyObject *kw2) -/*[clinic end generated code: output=ee259c130054653f input=91d8e227acf93b02]*/ +/*[clinic end generated code: output=ee259c130054653f input=568c6276e3fdef62]*/ { - PyObject *tuple = PyTuple_New(5); - PyTuple_SET_ITEM(tuple, 0, Py_NewRef(pos1)); - PyTuple_SET_ITEM(tuple, 1, Py_NewRef(pos2)); - PyTuple_SET_ITEM(tuple, 2, Py_NewRef(varargs)); - PyTuple_SET_ITEM(tuple, 3, Py_NewRef(kw1)); - PyTuple_SET_ITEM(tuple, 4, Py_NewRef(kw2)); - return tuple; + Py_RETURN_NONE; } /*[clinic input] @@ -76,20 +69,15 @@ The calculation of `noptargs` in AC-generated function Calling this function by gh_32092_kw_pass(1, 2, 3) to trigger this bug (crash). -Expected return: (1, (2, 3), None) [clinic start generated code]*/ static PyObject * gh_32092_kw_pass_impl(PyObject *module, PyObject *pos, PyObject *args, PyObject *kw) -/*[clinic end generated code: output=4a2bbe4f7c8604e9 input=5fc48f72f49193b6]*/ +/*[clinic end generated code: output=4a2bbe4f7c8604e9 input=5bfe6191e1e7a2fb]*/ { - PyObject *tuple = PyTuple_New(3); - PyTuple_SET_ITEM(tuple, 0, Py_NewRef(pos)); - PyTuple_SET_ITEM(tuple, 1, Py_NewRef(args)); - PyTuple_SET_ITEM(tuple, 2, Py_NewRef(kw)); - return tuple; + Py_RETURN_NONE; } static PyMethodDef tester_methods[] = { diff --git a/Modules/clinic/_testclinic.c.h b/Modules/clinic/_testclinic.c.h index 781546036cda7e..599fcb46b8d769 100644 --- a/Modules/clinic/_testclinic.c.h +++ b/Modules/clinic/_testclinic.c.h @@ -35,8 +35,7 @@ PyDoc_STRVAR(gh_32092_oob__doc__, "`_PyArg_UnpackKeywordsWithVararg` .\n" "\n" "Calling this function by gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6)\n" -"to trigger this bug (crash).\n" -"Expected return: (1, 2, (3, 4), 5, 6)"); +"to trigger this bug (crash)."); #define GH_32092_OOB_METHODDEF \ {"gh_32092_oob", _PyCFunction_CAST(gh_32092_oob), METH_FASTCALL|METH_KEYWORDS, gh_32092_oob__doc__}, @@ -117,8 +116,7 @@ PyDoc_STRVAR(gh_32092_kw_pass__doc__, "`builtin_kw_pass_poc` is incorrect.\n" "\n" "Calling this function by gh_32092_kw_pass(1, 2, 3)\n" -"to trigger this bug (crash).\n" -"Expected return: (1, (2, 3), None)"); +"to trigger this bug (crash)."); #define GH_32092_KW_PASS_METHODDEF \ {"gh_32092_kw_pass", _PyCFunction_CAST(gh_32092_kw_pass), METH_FASTCALL|METH_KEYWORDS, gh_32092_kw_pass__doc__}, @@ -179,4 +177,4 @@ gh_32092_kw_pass(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb Py_XDECREF(__clinic_args); return return_value; } -/*[clinic end generated code: output=da33e7aa2f9377db input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f1f47303a227104b input=a9049054013a1b77]*/ From 81fe77b826d6e4855d281b3620f6326606712ce1 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Fri, 28 Oct 2022 13:28:17 +0800 Subject: [PATCH 12/29] Add more testcases --- Include/internal/pycore_global_strings.h | 3 + .../internal/pycore_runtime_init_generated.h | 21 + Lib/test/test_clinic.py | 423 +++ Modules/_testclinic.c | 973 ++++++- Modules/clinic/_testclinic.c.h | 2531 ++++++++++++++++- 5 files changed, 3949 insertions(+), 2 deletions(-) diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 339f074cfd55d2..651d99b44f4ea0 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -260,6 +260,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(byteorder) STRUCT_FOR_ID(bytes) STRUCT_FOR_ID(bytes_per_sep) + STRUCT_FOR_ID(c) STRUCT_FOR_ID(c_call) STRUCT_FOR_ID(c_exception) STRUCT_FOR_ID(c_return) @@ -306,6 +307,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(coro) STRUCT_FOR_ID(count) STRUCT_FOR_ID(cwd) + STRUCT_FOR_ID(d) STRUCT_FOR_ID(data) STRUCT_FOR_ID(database) STRUCT_FOR_ID(decode) @@ -332,6 +334,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(dst) STRUCT_FOR_ID(dst_dir_fd) STRUCT_FOR_ID(duration) + STRUCT_FOR_ID(e) STRUCT_FOR_ID(effective_ids) STRUCT_FOR_ID(element_factory) STRUCT_FOR_ID(encode) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 27deeb1ee453a2..ed6fe616746937 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -769,6 +769,7 @@ extern "C" { INIT_ID(byteorder), \ INIT_ID(bytes), \ INIT_ID(bytes_per_sep), \ + INIT_ID(c), \ INIT_ID(c_call), \ INIT_ID(c_exception), \ INIT_ID(c_return), \ @@ -815,6 +816,7 @@ extern "C" { INIT_ID(coro), \ INIT_ID(count), \ INIT_ID(cwd), \ + INIT_ID(d), \ INIT_ID(data), \ INIT_ID(database), \ INIT_ID(decode), \ @@ -841,6 +843,7 @@ extern "C" { INIT_ID(dst), \ INIT_ID(dst_dir_fd), \ INIT_ID(duration), \ + INIT_ID(e), \ INIT_ID(effective_ids), \ INIT_ID(element_factory), \ INIT_ID(encode), \ @@ -1856,6 +1859,8 @@ _PyUnicode_InitStaticStrings(void) { PyUnicode_InternInPlace(&string); string = &_Py_ID(bytes_per_sep); PyUnicode_InternInPlace(&string); + string = &_Py_ID(c); + PyUnicode_InternInPlace(&string); string = &_Py_ID(c_call); PyUnicode_InternInPlace(&string); string = &_Py_ID(c_exception); @@ -1948,6 +1953,8 @@ _PyUnicode_InitStaticStrings(void) { PyUnicode_InternInPlace(&string); string = &_Py_ID(cwd); PyUnicode_InternInPlace(&string); + string = &_Py_ID(d); + PyUnicode_InternInPlace(&string); string = &_Py_ID(data); PyUnicode_InternInPlace(&string); string = &_Py_ID(database); @@ -2000,6 +2007,8 @@ _PyUnicode_InitStaticStrings(void) { PyUnicode_InternInPlace(&string); string = &_Py_ID(duration); PyUnicode_InternInPlace(&string); + string = &_Py_ID(e); + PyUnicode_InternInPlace(&string); string = &_Py_ID(effective_ids); PyUnicode_InternInPlace(&string); string = &_Py_ID(element_factory); @@ -5651,6 +5660,10 @@ _PyStaticObjects_CheckRefcnt(void) { _PyObject_Dump((PyObject *)&_Py_ID(bytes_per_sep)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); }; + if (Py_REFCNT((PyObject *)&_Py_ID(c)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(c)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; if (Py_REFCNT((PyObject *)&_Py_ID(c_call)) < _PyObject_IMMORTAL_REFCNT) { _PyObject_Dump((PyObject *)&_Py_ID(c_call)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); @@ -5835,6 +5848,10 @@ _PyStaticObjects_CheckRefcnt(void) { _PyObject_Dump((PyObject *)&_Py_ID(cwd)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); }; + if (Py_REFCNT((PyObject *)&_Py_ID(d)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(d)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; if (Py_REFCNT((PyObject *)&_Py_ID(data)) < _PyObject_IMMORTAL_REFCNT) { _PyObject_Dump((PyObject *)&_Py_ID(data)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); @@ -5939,6 +5956,10 @@ _PyStaticObjects_CheckRefcnt(void) { _PyObject_Dump((PyObject *)&_Py_ID(duration)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); }; + if (Py_REFCNT((PyObject *)&_Py_ID(e)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(e)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; if (Py_REFCNT((PyObject *)&_Py_ID(effective_ids)) < _PyObject_IMMORTAL_REFCNT) { _PyObject_Dump((PyObject *)&_Py_ID(effective_ids)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 7d717e033b8a18..f34d02f13b22d1 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -827,6 +827,429 @@ class TestClinicFunctionality(unittest.TestCase): locals().update((name, getattr(ac_tester, name)) for name in dir(ac_tester) if name.startswith('test_')) + def test_objects_converter(self): + with self.assertRaises(TypeError): + ac_tester.objects_converter() + self.assertEqual(ac_tester.objects_converter(1, 2), (1, 2)) + self.assertEqual(ac_tester.objects_converter([], 'whatever class'), ([], 'whatever class')) + self.assertEqual(ac_tester.objects_converter(1), (1, None)) + + def test_bytes_object_converter(self): + with self.assertRaises(TypeError): + ac_tester.bytes_object_converter(1) + self.assertEqual(ac_tester.bytes_object_converter(b'BytesObject'), (b'BytesObject', )) + + def test_byte_array_object_converter(self): + with self.assertRaises(TypeError): + ac_tester.byte_array_object_converter(1) + byte_arr = bytearray(b'ByteArrayObject') + self.assertEqual(ac_tester.byte_array_object_converter(byte_arr), (byte_arr, )) + + def test_unicode_converter(self): + with self.assertRaises(TypeError): + ac_tester.unicode_converter(1) + self.assertEqual(ac_tester.unicode_converter('unicode'), ('unicode', )) + + def test_bool_converter(self): + with self.assertRaises(TypeError): + ac_tester.bool_converter(False, False, 'not a int') + self.assertEqual(ac_tester.bool_converter(), (True, True, True)) + self.assertEqual(ac_tester.bool_converter('', [], 5), (False, False, True)) + self.assertEqual(ac_tester.bool_converter(('not empty', ), {1: 2}, 0), (True, True, False)) + + def test_char_converter(self): + with self.assertRaises(TypeError): + ac_tester.char_converter(1) + with self.assertRaises(TypeError): + ac_tester.char_converter(b'ab') + chars = [b'A', b'\a', b'\b', b'\t', b'\n', b'\v', b'\f', b'\r', b'"', b"'", b'?', b'\\', b'\000', b'\377'] + expected = tuple([ord(c) for c in chars]) + self.assertEqual(ac_tester.char_converter(), expected) + chars = [b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'0', b'a', b'b', b'c', b'd'] + expected = tuple([ord(c) for c in chars]) + self.assertEqual(ac_tester.char_converter(*chars), expected) + + def test_unsigned_char_converter(self): + from _testcapi import UCHAR_MAX + with self.assertRaises(OverflowError): + ac_tester.unsigned_char_converter(-1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_char_converter(UCHAR_MAX + 1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_char_converter(0, UCHAR_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.unsigned_char_converter([]) + self.assertEqual(ac_tester.unsigned_char_converter(), (12, 34, 56)) + self.assertEqual(ac_tester.unsigned_char_converter(0, 0, UCHAR_MAX + 1), (0, 0, 0)) + self.assertEqual(ac_tester.unsigned_char_converter(0, 0, (UCHAR_MAX + 1) * 3 + 123), (0, 0, 123)) + + def test_short_converter(self): + from _testcapi import SHRT_MIN, SHRT_MAX + with self.assertRaises(OverflowError): + ac_tester.short_converter(SHRT_MIN - 1) + with self.assertRaises(OverflowError): + ac_tester.short_converter(SHRT_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.short_converter([]) + self.assertEqual(ac_tester.short_converter(-1234), (-1234, )) + self.assertEqual(ac_tester.short_converter(4321), (4321, )) + + def test_unsigned_short_converter(self): + from _testcapi import USHRT_MAX + with self.assertRaises(ValueError): + ac_tester.unsigned_short_converter(-1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_short_converter(USHRT_MAX + 1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_short_converter(0, USHRT_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.unsigned_short_converter([]) + self.assertEqual(ac_tester.unsigned_short_converter(), (12, 34, 56)) + self.assertEqual(ac_tester.unsigned_short_converter(0, 0, USHRT_MAX + 1), (0, 0, 0)) + self.assertEqual(ac_tester.unsigned_short_converter(0, 0, (USHRT_MAX + 1) * 3 + 123), (0, 0, 123)) + + def test_int_converter(self): + from _testcapi import INT_MIN, INT_MAX + with self.assertRaises(OverflowError): + ac_tester.int_converter(INT_MIN - 1) + with self.assertRaises(OverflowError): + ac_tester.int_converter(INT_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.int_converter(1, 2, 3) + with self.assertRaises(TypeError): + ac_tester.int_converter([]) + self.assertEqual(ac_tester.int_converter(), (12, 34, 45)) + self.assertEqual(ac_tester.int_converter(1, 2, '3'), (1, 2, ord('3'))) + + def test_unsigned_int_converter(self): + from _testcapi import UINT_MAX + with self.assertRaises(ValueError): + ac_tester.unsigned_int_converter(-1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_int_converter(UINT_MAX + 1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_int_converter(0, UINT_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.unsigned_int_converter([]) + self.assertEqual(ac_tester.unsigned_int_converter(), (12, 34, 56)) + self.assertEqual(ac_tester.unsigned_int_converter(0, 0, UINT_MAX + 1), (0, 0, 0)) + self.assertEqual(ac_tester.unsigned_int_converter(0, 0, (UINT_MAX + 1) * 3 + 123), (0, 0, 123)) + + def test_long_converter(self): + from _testcapi import LONG_MIN, LONG_MAX + with self.assertRaises(OverflowError): + ac_tester.long_converter(LONG_MIN - 1) + with self.assertRaises(OverflowError): + ac_tester.long_converter(LONG_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.long_converter([]) + self.assertEqual(ac_tester.long_converter(), (12, )) + self.assertEqual(ac_tester.long_converter(-1234), (-1234, )) + + def test_unsigned_long_converter(self): + from _testcapi import ULONG_MAX + with self.assertRaises(ValueError): + ac_tester.unsigned_long_converter(-1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_long_converter(ULONG_MAX + 1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_long_converter(0, ULONG_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.unsigned_long_converter([]) + self.assertEqual(ac_tester.unsigned_long_converter(), (12, 34, 56)) + self.assertEqual(ac_tester.unsigned_long_converter(0, 0, ULONG_MAX + 1), (0, 0, 0)) + self.assertEqual(ac_tester.unsigned_long_converter(0, 0, (ULONG_MAX + 1) * 3 + 123), (0, 0, 123)) + + def test_long_long_converter(self): + from _testcapi import LLONG_MIN, LLONG_MAX + with self.assertRaises(OverflowError): + ac_tester.long_long_converter(LLONG_MIN - 1) + with self.assertRaises(OverflowError): + ac_tester.long_long_converter(LLONG_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.long_long_converter([]) + self.assertEqual(ac_tester.long_long_converter(), (12, )) + self.assertEqual(ac_tester.long_long_converter(-1234), (-1234, )) + + def test_unsigned_long_long_converter(self): + from _testcapi import ULLONG_MAX + with self.assertRaises(ValueError): + ac_tester.unsigned_long_long_converter(-1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_long_long_converter(ULLONG_MAX + 1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_long_long_converter(0, ULLONG_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.unsigned_long_long_converter([]) + self.assertEqual(ac_tester.unsigned_long_long_converter(), (12, 34, 56)) + self.assertEqual(ac_tester.unsigned_long_long_converter(0, 0, ULLONG_MAX + 1), (0, 0, 0)) + self.assertEqual(ac_tester.unsigned_long_long_converter(0, 0, (ULLONG_MAX + 1) * 3 + 123), (0, 0, 123)) + + def test_py_ssize_t_converter(self): + from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX + with self.assertRaises(OverflowError): + ac_tester.py_ssize_t_converter(PY_SSIZE_T_MIN - 1) + with self.assertRaises(OverflowError): + ac_tester.py_ssize_t_converter(PY_SSIZE_T_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.py_ssize_t_converter([]) + self.assertEqual(ac_tester.py_ssize_t_converter(), (12, 34, 56)) + self.assertEqual(ac_tester.py_ssize_t_converter(1, 2, None), (1, 2, 56)) + + def test_slice_index_converter(self): + from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX + with self.assertRaises(TypeError): + ac_tester.slice_index_converter([]) + self.assertEqual(ac_tester.slice_index_converter(), (12, 34, 56)) + self.assertEqual(ac_tester.slice_index_converter(1, 2, None), (1, 2, 56)) + self.assertEqual(ac_tester.slice_index_converter(PY_SSIZE_T_MAX, PY_SSIZE_T_MAX + 1, PY_SSIZE_T_MAX + 1234), + (PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX)) + self.assertEqual(ac_tester.slice_index_converter(PY_SSIZE_T_MIN, PY_SSIZE_T_MIN - 1, PY_SSIZE_T_MIN - 1234), + (PY_SSIZE_T_MIN, PY_SSIZE_T_MIN, PY_SSIZE_T_MIN)) + + def test_size_t_converter(self): + with self.assertRaises(ValueError): + ac_tester.size_t_converter(-1) + with self.assertRaises(TypeError): + ac_tester.size_t_converter([]) + self.assertEqual(ac_tester.size_t_converter(), (12, )) + + def test_float_converter(self): + with self.assertRaises(TypeError): + ac_tester.float_converter([]) + self.assertEqual(ac_tester.float_converter(), (12.5, )) + self.assertEqual(ac_tester.float_converter(-0.5), (-0.5, )) + + def test_double_converter(self): + with self.assertRaises(TypeError): + ac_tester.double_converter([]) + self.assertEqual(ac_tester.double_converter(), (12.5, )) + self.assertEqual(ac_tester.double_converter(-0.5), (-0.5, )) + + def test_py_complex_converter(self): + with self.assertRaises(TypeError): + ac_tester.py_complex_converter([]) + self.assertEqual(ac_tester.py_complex_converter(complex(1, 2)), (complex(1, 2), )) + self.assertEqual(ac_tester.py_complex_converter(complex('-1-2j')), (complex('-1-2j'), )) + self.assertEqual(ac_tester.py_complex_converter(-0.5), (-0.5, )) + self.assertEqual(ac_tester.py_complex_converter(10), (10, )) + + def test_str_converter(self): + with self.assertRaises(TypeError): + ac_tester.str_converter(1) + with self.assertRaises(TypeError): + ac_tester.str_converter('a', 'b', 'c') + with self.assertRaises(ValueError): + ac_tester.str_converter('a', b'b\0b', 'c') + self.assertEqual(ac_tester.str_converter('a', b'b', 'c'), ('a', 'b', 'c')) + self.assertEqual(ac_tester.str_converter('a', b'b', b'c'), ('a', 'b', 'c')) + self.assertEqual(ac_tester.str_converter('a', b'b', 'c\0c'), ('a', 'b', 'c\0c')) + + def test_str_converter_encoding(self): + with self.assertRaises(TypeError): + ac_tester.str_converter_encoding(1) + self.assertEqual(ac_tester.str_converter_encoding('a', 'b', 'c'), ('a', 'b', 'c')) + with self.assertRaises(ValueError): + ac_tester.str_converter_encoding('a', b'b\0b', 'c') + self.assertEqual(ac_tester.str_converter_encoding('a', b'b', bytearray([ord('c')])), ('a', 'b', 'c')) + self.assertEqual(ac_tester.str_converter_encoding('a', b'b', bytearray([ord('c'), 0, ord('c')])), + ('a', 'b', 'c\x00c')) + self.assertEqual(ac_tester.str_converter_encoding('a', b'b', b'c\x00c'), ('a', 'b', 'c\x00c')) + + def test_py_buffer_converter(self): + with self.assertRaises(TypeError): + ac_tester.py_buffer_converter('a', 'b') + self.assertEqual(ac_tester.py_buffer_converter('abc', bytearray([1, 2, 3])), (b'abc', b'\x01\x02\x03')) + + def test_keywords(self): + self.assertEqual(ac_tester.keywords(1, 2), (1, 2)) + self.assertEqual(ac_tester.keywords(1, b=2), (1, 2)) + self.assertEqual(ac_tester.keywords(a=1, b=2), (1, 2)) + + def test_keywords_kwonly(self): + with self.assertRaises(TypeError): + ac_tester.keywords_kwonly(1, 2) + self.assertEqual(ac_tester.keywords_kwonly(1, b=2), (1, 2)) + self.assertEqual(ac_tester.keywords_kwonly(a=1, b=2), (1, 2)) + + def test_keywords_opt(self): + self.assertEqual(ac_tester.keywords_opt(1), (1, None, None)) + self.assertEqual(ac_tester.keywords_opt(1, 2), (1, 2, None)) + self.assertEqual(ac_tester.keywords_opt(1, 2, 3), (1, 2, 3)) + self.assertEqual(ac_tester.keywords_opt(1, b=2), (1, 2, None)) + self.assertEqual(ac_tester.keywords_opt(1, 2, c=3), (1, 2, 3)) + self.assertEqual(ac_tester.keywords_opt(a=1, c=3), (1, None, 3)) + self.assertEqual(ac_tester.keywords_opt(a=1, b=2, c=3), (1, 2, 3)) + + def test_keywords_opt_kwonly(self): + self.assertEqual(ac_tester.keywords_opt_kwonly(1), (1, None, None, None)) + self.assertEqual(ac_tester.keywords_opt_kwonly(1, 2), (1, 2, None, None)) + with self.assertRaises(TypeError): + ac_tester.keywords_opt_kwonly(1, 2, 3) + self.assertEqual(ac_tester.keywords_opt_kwonly(1, b=2), (1, 2, None, None)) + self.assertEqual(ac_tester.keywords_opt_kwonly(1, 2, c=3), (1, 2, 3, None)) + self.assertEqual(ac_tester.keywords_opt_kwonly(a=1, c=3), (1, None, 3, None)) + self.assertEqual(ac_tester.keywords_opt_kwonly(a=1, b=2, c=3, d=4), (1, 2, 3, 4)) + + def test_keywords_kwonly_opt(self): + self.assertEqual(ac_tester.keywords_kwonly_opt(1), (1, None, None)) + with self.assertRaises(TypeError): + ac_tester.keywords_kwonly_opt(1, 2) + self.assertEqual(ac_tester.keywords_kwonly_opt(1, b=2), (1, 2, None)) + self.assertEqual(ac_tester.keywords_kwonly_opt(a=1, c=3), (1, None, 3)) + self.assertEqual(ac_tester.keywords_kwonly_opt(a=1, b=2, c=3), (1, 2, 3)) + + def test_posonly_keywords(self): + with self.assertRaises(TypeError): + ac_tester.posonly_keywords(1) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords(a=1, b=2) + self.assertEqual(ac_tester.posonly_keywords(1, 2), (1, 2)) + self.assertEqual(ac_tester.posonly_keywords(1, b=2), (1, 2)) + + def test_posonly_kwonly(self): + with self.assertRaises(TypeError): + ac_tester.posonly_kwonly(1) + with self.assertRaises(TypeError): + ac_tester.posonly_kwonly(1, 2) + with self.assertRaises(TypeError): + ac_tester.posonly_kwonly(a=1, b=2) + self.assertEqual(ac_tester.posonly_kwonly(1, b=2), (1, 2)) + + def test_posonly_keywords_kwonly(self): + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_kwonly(1) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_kwonly(1, 2, 3) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_kwonly(a=1, b=2, c=3) + self.assertEqual(ac_tester.posonly_keywords_kwonly(1, 2, c=3), (1, 2, 3)) + self.assertEqual(ac_tester.posonly_keywords_kwonly(1, b=2, c=3), (1, 2, 3)) + + def test_posonly_keywords_opt(self): + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_opt(1) + self.assertEqual(ac_tester.posonly_keywords_opt(1, 2), (1, 2, None, None)) + self.assertEqual(ac_tester.posonly_keywords_opt(1, 2, 3), (1, 2, 3, None)) + self.assertEqual(ac_tester.posonly_keywords_opt(1, 2, 3, 4), (1, 2, 3, 4)) + self.assertEqual(ac_tester.posonly_keywords_opt(1, b=2), (1, 2, None, None)) + self.assertEqual(ac_tester.posonly_keywords_opt(1, 2, c=3), (1, 2, 3, None)) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_opt(a=1, b=2, c=3, d=4) + self.assertEqual(ac_tester.posonly_keywords_opt(1, b=2, c=3, d=4), (1, 2, 3, 4)) + + def test_posonly_opt_keywords_opt(self): + self.assertEqual(ac_tester.posonly_opt_keywords_opt(1), (1, None, None, None)) + self.assertEqual(ac_tester.posonly_opt_keywords_opt(1, 2), (1, 2, None, None)) + self.assertEqual(ac_tester.posonly_opt_keywords_opt(1, 2, 3), (1, 2, 3, None)) + self.assertEqual(ac_tester.posonly_opt_keywords_opt(1, 2, 3, 4), (1, 2, 3, 4)) + with self.assertRaises(TypeError): + ac_tester.posonly_opt_keywords_opt(1, b=2) + self.assertEqual(ac_tester.posonly_opt_keywords_opt(1, 2, c=3), (1, 2, 3, None)) + self.assertEqual(ac_tester.posonly_opt_keywords_opt(1, 2, c=3, d=4), (1, 2, 3, 4)) + with self.assertRaises(TypeError): + ac_tester.posonly_opt_keywords_opt(a=1, b=2, c=3, d=4) + + def test_posonly_kwonly_opt(self): + with self.assertRaises(TypeError): + ac_tester.posonly_kwonly_opt(1) + with self.assertRaises(TypeError): + ac_tester.posonly_kwonly_opt(1, 2) + self.assertEqual(ac_tester.posonly_kwonly_opt(1, b=2), (1, 2, None, None)) + self.assertEqual(ac_tester.posonly_kwonly_opt(1, b=2, c=3), (1, 2, 3, None)) + self.assertEqual(ac_tester.posonly_kwonly_opt(1, b=2, c=3, d=4), (1, 2, 3, 4)) + with self.assertRaises(TypeError): + ac_tester.posonly_kwonly_opt(a=1, b=2, c=3, d=4) + + def test_posonly_opt_kwonly_opt(self): + self.assertEqual(ac_tester.posonly_opt_kwonly_opt(1), (1, None, None, None)) + self.assertEqual(ac_tester.posonly_opt_kwonly_opt(1, 2), (1, 2, None, None)) + with self.assertRaises(TypeError): + ac_tester.posonly_opt_kwonly_opt(1, 2, 3) + with self.assertRaises(TypeError): + ac_tester.posonly_opt_kwonly_opt(1, b=2) + self.assertEqual(ac_tester.posonly_opt_kwonly_opt(1, 2, c=3), (1, 2, 3, None)) + self.assertEqual(ac_tester.posonly_opt_kwonly_opt(1, 2, c=3, d=4), (1, 2, 3, 4)) + + def test_posonly_keywords_kwonly_opt(self): + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_kwonly_opt(1) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_kwonly_opt(1, 2) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_kwonly_opt(1, b=2) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_kwonly_opt(1, 2, 3) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_kwonly_opt(a=1, b=2, c=3) + self.assertEqual(ac_tester.posonly_keywords_kwonly_opt(1, 2, c=3), (1, 2, 3, None, None)) + self.assertEqual(ac_tester.posonly_keywords_kwonly_opt(1, b=2, c=3), (1, 2, 3, None, None)) + self.assertEqual(ac_tester.posonly_keywords_kwonly_opt(1, 2, c=3, d=4), (1, 2, 3, 4, None)) + self.assertEqual(ac_tester.posonly_keywords_kwonly_opt(1, 2, c=3, d=4, e=5), (1, 2, 3, 4, 5)) + + def test_posonly_keywords_opt_kwonly_opt(self): + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_opt_kwonly_opt(1) + self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2), (1, 2, None, None, None)) + self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, b=2), (1, 2, None, None, None)) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, 3, 4) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_opt_kwonly_opt(a=1, b=2) + self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, c=3), (1, 2, 3, None, None)) + self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, b=2, c=3), (1, 2, 3, None, None)) + self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, 3, d=4), (1, 2, 3, 4, None)) + self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, c=3, d=4), (1, 2, 3, 4, None)) + self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, 3, d=4, e=5), (1, 2, 3, 4, 5)) + self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, c=3, d=4, e=5), (1, 2, 3, 4, 5)) + + def test_posonly_opt_keywords_opt_kwonly_opt(self): + self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1), (1, None, None, None)) + self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2), (1, 2, None, None)) + with self.assertRaises(TypeError): + ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, b=2) + self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, 3), (1, 2, 3, None)) + self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, c=3), (1, 2, 3, None)) + self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, 3, d=4), (1, 2, 3, 4)) + self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, c=3, d=4), (1, 2, 3, 4)) + with self.assertRaises(TypeError): + ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, 3, 4) + + def test_keyword_only_parameter(self): + with self.assertRaises(TypeError): + ac_tester.keyword_only_parameter() + with self.assertRaises(TypeError): + 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_vararg(self): + with self.assertRaises(TypeError): + ac_tester.vararg() + with self.assertRaises(TypeError): + ac_tester.vararg(1, b=2) + self.assertEqual(ac_tester.vararg(1, 2, 3, 4), (1, (2, 3, 4))) + + def test_vararg_with_default(self): + with self.assertRaises(TypeError): + ac_tester.vararg_with_default() + self.assertEqual(ac_tester.vararg_with_default(1, b=False), (1, (), False)) + self.assertEqual(ac_tester.vararg_with_default(1, 2, 3, 4), (1, (2, 3, 4), False)) + self.assertEqual(ac_tester.vararg_with_default(1, 2, 3, 4, b=True), (1, (2, 3, 4), True)) + + def test_vararg_with_only_defaults(self): + self.assertEqual(ac_tester.vararg_with_only_defaults(), ((), None)) + self.assertEqual(ac_tester.vararg_with_only_defaults(b=2), ((), 2)) + self.assertEqual(ac_tester.vararg_with_only_defaults(1, b=2), ((1, ), 2)) + self.assertEqual(ac_tester.vararg_with_only_defaults(1, 2, 3, 4), ((1, 2, 3, 4), None)) + self.assertEqual(ac_tester.vararg_with_only_defaults(1, 2, 3, 4, b=5), ((1, 2, 3, 4), 5)) + def test_gh_32092_oob(self): res = ac_tester.gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6) expect = (1, 2, (3, 4), 5, 6) diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index af07b80a7e88da..9e744080b335e7 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -11,11 +11,36 @@ #include "clinic/_testclinic.c.h" +PyObject * +pack_arguments(int arg_num, ...) { + va_list vargs; + va_start(vargs, arg_num); + PyObject *tuple = PyTuple_New(arg_num); + for (int i = 0; i < arg_num; i++) { + PyObject *arg = va_arg(vargs, PyObject *); + if (arg) { + if (_PyObject_IsFreed(arg)) { + PyErr_Format(PyExc_AssertionError, + "argument %d at %p is freed or corrupted!", + i, arg); + return NULL; + } + } else { + arg = Py_None; + } + PyTuple_SET_ITEM(tuple, i, Py_NewRef(arg)); + } + va_end(vargs); + return tuple; +} + + /*[clinic input] module _testclinic [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=d4981b80d6efdb12]*/ + /*[clinic input] test_empty_function @@ -26,7 +51,907 @@ test_empty_function_impl(PyObject *module) /*[clinic end generated code: output=0f8aeb3ddced55cb input=0dd7048651ad4ae4]*/ { Py_RETURN_NONE; -}; +} + + +/*[clinic input] +objects_converter + + a: object + b: object = NULL + / + +[clinic start generated code]*/ + +static PyObject * +objects_converter_impl(PyObject *module, PyObject *a, PyObject *b) +/*[clinic end generated code: output=3f9c9415ec86c695 input=1533b1bd94187de4]*/ +{ + return pack_arguments(2, a, b); +} + + +/*[clinic input] +bytes_object_converter + + a: PyBytesObject + / + +[clinic start generated code]*/ + +static PyObject * +bytes_object_converter_impl(PyObject *module, PyBytesObject *a) +/*[clinic end generated code: output=7732da869d74b784 input=94211751e7996236]*/ +{ + if (!PyBytes_Check(a)) { + PyErr_SetString(PyExc_AssertionError, "argument a is not a PyBytesObject"); + } + return pack_arguments(1, a); +} + + +/*[clinic input] +byte_array_object_converter + + a: PyByteArrayObject + / + +[clinic start generated code]*/ + +static PyObject * +byte_array_object_converter_impl(PyObject *module, PyByteArrayObject *a) +/*[clinic end generated code: output=51f15c76f302b1f7 input=b04d253db51c6f56]*/ +{ + if (!PyByteArray_Check(a)) { + PyErr_SetString(PyExc_AssertionError, "argument a is not a PyByteArrayObject"); + } + return pack_arguments(1, a); +} + + +/*[clinic input] +unicode_converter + + a: unicode + / + +[clinic start generated code]*/ + +static PyObject * +unicode_converter_impl(PyObject *module, PyObject *a) +/*[clinic end generated code: output=1b4a4adbb6ac6e34 input=de7b5adbf07435ba]*/ +{ + if (!PyUnicode_Check(a)) { + PyErr_SetString(PyExc_AssertionError, "argument a is not a unicode object"); + } + return pack_arguments(1, a); +} + + +/*[clinic input] +bool_converter + + a: bool = True + b: bool(accept={object}) = True + c: bool(accept={int}) = True + / + +[clinic start generated code]*/ + +static PyObject * +bool_converter_impl(PyObject *module, int a, int b, int c) +/*[clinic end generated code: output=17005b0c29afd590 input=7f6537705b2f32f4]*/ +{ + if (!(a == 0 || a == 1)) { + PyErr_SetString(PyExc_AssertionError, "argument a is not a bool value"); + } + if (!(a == 0 || a == 1)) { + PyErr_SetString(PyExc_AssertionError, "argument b is not a bool value"); + } + if (!(a == 0 || a == 1)) { + PyErr_SetString(PyExc_AssertionError, "argument c is not a bool value"); + } + PyObject *obj_a = a ? Py_True : Py_False; + PyObject *obj_b = b ? Py_True : Py_False; + PyObject *obj_c = c ? Py_True : Py_False; + return pack_arguments(3, obj_a, obj_b, obj_c); +} + + +/*[clinic input] +char_converter + + a: char = b'A' + b: char = b'\a' + c: char = b'\b' + d: char = b'\t' + e: char = b'\n' + f: char = b'\v' + g: char = b'\f' + h: char = b'\r' + i: char = b'"' + j: char = b"'" + k: char = b'?' + l: char = b'\\' + m: char = b'\000' + n: char = b'\377' + / + +[clinic start generated code]*/ + +static PyObject * +char_converter_impl(PyObject *module, char a, char b, char c, char d, char e, + char f, char g, char h, char i, char j, char k, char l, + char m, char n) +/*[clinic end generated code: output=f929dbd2e55a9871 input=b601bc5bc7fe85e3]*/ +{ + return pack_arguments(14, + PyLong_FromUnsignedLong((unsigned char) a), + PyLong_FromUnsignedLong((unsigned char) b), + PyLong_FromUnsignedLong((unsigned char) c), + PyLong_FromUnsignedLong((unsigned char) d), + PyLong_FromUnsignedLong((unsigned char) e), + PyLong_FromUnsignedLong((unsigned char) f), + PyLong_FromUnsignedLong((unsigned char) g), + PyLong_FromUnsignedLong((unsigned char) h), + PyLong_FromUnsignedLong((unsigned char) i), + PyLong_FromUnsignedLong((unsigned char) j), + PyLong_FromUnsignedLong((unsigned char) k), + PyLong_FromUnsignedLong((unsigned char) l), + PyLong_FromUnsignedLong((unsigned char) m), + PyLong_FromUnsignedLong((unsigned char) n)); +} + + +/*[clinic input] +unsigned_char_converter + + a: unsigned_char = 12 + b: unsigned_char(bitwise=False) = 34 + c: unsigned_char(bitwise=True) = 56 + / + +[clinic start generated code]*/ + +static PyObject * +unsigned_char_converter_impl(PyObject *module, unsigned char a, + unsigned char b, unsigned char c) +/*[clinic end generated code: output=490af3b39ce0b199 input=e859502fbe0b3185]*/ +{ + return pack_arguments(3, + PyLong_FromUnsignedLong(a), + PyLong_FromUnsignedLong(b), + PyLong_FromUnsignedLong(c)); +} + + +/*[clinic input] +short_converter + + a: short = 12 + / + +[clinic start generated code]*/ + +static PyObject * +short_converter_impl(PyObject *module, short a) +/*[clinic end generated code: output=1ebb7ddb64248988 input=b4e2309a66f650ae]*/ +{ + return pack_arguments(1, PyLong_FromLong(a)); +} + + +/*[clinic input] +unsigned_short_converter + + a: unsigned_short = 12 + b: unsigned_short(bitwise=False) = 34 + c: unsigned_short(bitwise=True) = 56 + / + +[clinic start generated code]*/ + +static PyObject * +unsigned_short_converter_impl(PyObject *module, unsigned short a, + unsigned short b, unsigned short c) +/*[clinic end generated code: output=5f92cc72fc8707a7 input=9d15cd11e741d0c6]*/ +{ + return pack_arguments(3, + PyLong_FromUnsignedLong(a), + PyLong_FromUnsignedLong(b), + PyLong_FromUnsignedLong(c)); +} + + +/*[clinic input] +int_converter + + a: int = 12 + b: int(accept={int}) = 34 + c: int(accept={str}) = 45 + / + +[clinic start generated code]*/ + +static PyObject * +int_converter_impl(PyObject *module, int a, int b, int c) +/*[clinic end generated code: output=8e56b59be7d0c306 input=a1dbc6344853db7a]*/ +{ + return pack_arguments(3, + PyLong_FromLong(a), + PyLong_FromLong(b), + PyLong_FromLong(c)); +} + + +/*[clinic input] +unsigned_int_converter + + a: unsigned_int = 12 + b: unsigned_int(bitwise=False) = 34 + c: unsigned_int(bitwise=True) = 56 + / + +[clinic start generated code]*/ + +static PyObject * +unsigned_int_converter_impl(PyObject *module, unsigned int a, unsigned int b, + unsigned int c) +/*[clinic end generated code: output=399a57a05c494cc7 input=8427ed9a3f96272d]*/ +{ + return pack_arguments(3, + PyLong_FromUnsignedLong(a), + PyLong_FromUnsignedLong(b), + PyLong_FromUnsignedLong(c)); +} + + +/*[clinic input] +long_converter + + a: long = 12 + / + +[clinic start generated code]*/ + +static PyObject * +long_converter_impl(PyObject *module, long a) +/*[clinic end generated code: output=9663d936a652707a input=84ad0ef28f24bd85]*/ +{ + return pack_arguments(1, PyLong_FromLong(a)); +} + + +/*[clinic input] +unsigned_long_converter + + a: unsigned_long = 12 + b: unsigned_long(bitwise=False) = 34 + c: unsigned_long(bitwise=True) = 56 + / + +[clinic start generated code]*/ + +static PyObject * +unsigned_long_converter_impl(PyObject *module, unsigned long a, + unsigned long b, unsigned long c) +/*[clinic end generated code: output=120b82ea9ebd93a8 input=440dd6f1817f5d91]*/ +{ + return pack_arguments(3, + PyLong_FromUnsignedLong(a), + PyLong_FromUnsignedLong(b), + PyLong_FromUnsignedLong(c)); +} + + +/*[clinic input] +long_long_converter + + a: long_long = 12 + / + +[clinic start generated code]*/ + +static PyObject * +long_long_converter_impl(PyObject *module, long long a) +/*[clinic end generated code: output=5fb5f2220770c3e1 input=730fcb3eecf4d993]*/ +{ + return pack_arguments(1, PyLong_FromLongLong(a)); +} + + +/*[clinic input] +unsigned_long_long_converter + + a: unsigned_long_long = 12 + b: unsigned_long_long(bitwise=False) = 34 + c: unsigned_long_long(bitwise=True) = 56 + / + +[clinic start generated code]*/ + +static PyObject * +unsigned_long_long_converter_impl(PyObject *module, unsigned long long a, + unsigned long long b, unsigned long long c) +/*[clinic end generated code: output=65b7273e63501762 input=300737b0bdb230e9]*/ +{ + return pack_arguments(3, + PyLong_FromUnsignedLongLong(a), + PyLong_FromUnsignedLongLong(b), + PyLong_FromUnsignedLongLong(c)); +} + + +/*[clinic input] +py_ssize_t_converter + + a: Py_ssize_t = 12 + b: Py_ssize_t(accept={int}) = 34 + c: Py_ssize_t(accept={int, NoneType}) = 56 + / + +[clinic start generated code]*/ + +static PyObject * +py_ssize_t_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b, + Py_ssize_t c) +/*[clinic end generated code: output=ce252143e0ed0372 input=76d0f342e9317a1f]*/ +{ + return pack_arguments(3, + PyLong_FromSsize_t(a), + PyLong_FromSsize_t(b), + PyLong_FromSsize_t(c)); +} + + +/*[clinic input] +slice_index_converter + + a: slice_index = 12 + b: slice_index(accept={int}) = 34 + c: slice_index(accept={int, NoneType}) = 56 + / + +[clinic start generated code]*/ + +static PyObject * +slice_index_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b, + Py_ssize_t c) +/*[clinic end generated code: output=923c6cac77666a6b input=64f99f3f83265e47]*/ +{ + return pack_arguments(3, + PyLong_FromSsize_t(a), + PyLong_FromSsize_t(b), + PyLong_FromSsize_t(c)); +} + + +/*[clinic input] +size_t_converter + + a: size_t = 12 + / + +[clinic start generated code]*/ + +static PyObject * +size_t_converter_impl(PyObject *module, size_t a) +/*[clinic end generated code: output=412b5b7334ab444d input=83ae7d9171fbf208]*/ +{ + return pack_arguments(1, PyLong_FromSize_t(a)); +} + + +/*[clinic input] +float_converter + + a: float = 12.5 + / + +[clinic start generated code]*/ + +static PyObject * +float_converter_impl(PyObject *module, float a) +/*[clinic end generated code: output=1c98f64f2cf1d55c input=a625b59ad68047d8]*/ +{ + return pack_arguments(1, PyFloat_FromDouble((double) a)); +} + + +/*[clinic input] +double_converter + + a: double = 12.5 + / + +[clinic start generated code]*/ + +static PyObject * +double_converter_impl(PyObject *module, double a) +/*[clinic end generated code: output=a4e8532d284d035d input=098df188f24e7c62]*/ +{ + return pack_arguments(1, PyFloat_FromDouble(a)); +} + + +/*[clinic input] +py_complex_converter + + a: Py_complex + / + +[clinic start generated code]*/ + +static PyObject * +py_complex_converter_impl(PyObject *module, Py_complex a) +/*[clinic end generated code: output=9e6ca2eb53b14846 input=e9148a8ca1dbf195]*/ +{ + return pack_arguments(1, PyComplex_FromCComplex(a)); +} + + +/*[clinic input] +str_converter + + a: str = "a" + b: str(accept={robuffer}) = "b" + c: str(accept={robuffer, str}, zeroes=True) = "c" + / + +[clinic start generated code]*/ + +static PyObject * +str_converter_impl(PyObject *module, const char *a, const char *b, + const char *c, Py_ssize_t c_length) +/*[clinic end generated code: output=475bea40548c8cd6 input=bff2656c92ee25de]*/ +{ + return pack_arguments(3, + PyUnicode_FromString(a), + PyUnicode_FromString(b), + PyUnicode_FromStringAndSize(c, c_length)); +} + + +/*[clinic input] +str_converter_encoding + + a: str(encoding="idna") + b: str(encoding="idna", accept={bytes, bytearray, str}) + c: str(encoding="idna", accept={bytes, bytearray, str}, zeroes=True) + / + +[clinic start generated code]*/ + +static PyObject * +str_converter_encoding_impl(PyObject *module, char *a, char *b, char *c, + Py_ssize_t c_length) +/*[clinic end generated code: output=af68766049248a1c input=0c5cf5159d0e870d]*/ +{ + return pack_arguments(3, + PyUnicode_FromString(a), + PyUnicode_FromString(b), + PyUnicode_FromStringAndSize(c, c_length)); +} + + +/*[clinic input] +py_buffer_converter + + a: Py_buffer(accept={str, buffer, NoneType}) + b: Py_buffer(accept={rwbuffer}) + / + +[clinic start generated code]*/ + +static PyObject * +py_buffer_converter_impl(PyObject *module, Py_buffer *a, Py_buffer *b) +/*[clinic end generated code: output=52fb13311e3d6d03 input=775de727de5c7421]*/ +{ + PyObject *new_a = PyBytes_FromStringAndSize(NULL, a->len); + if (!new_a) { + Py_XDECREF(new_a); + return NULL; + } + if (PyBuffer_ToContiguous(((PyBytesObject *) new_a)->ob_sval, a, a->len, 'C') < 0) { + Py_XDECREF(new_a); + return NULL; + } + PyBuffer_Release(a); + + PyObject *new_b = PyBytes_FromStringAndSize(NULL, b->len); + if (!new_b) { + Py_XDECREF(new_b); + return NULL; + } + if (PyBuffer_ToContiguous(((PyBytesObject *) new_b)->ob_sval, b, b->len, 'C') < 0) { + Py_XDECREF(new_b); + return NULL; + } + PyBuffer_Release(b); + + return pack_arguments(2, new_a, new_b); +} + + +/*[clinic input] +keywords + + a: object + b: object + +[clinic start generated code]*/ + +static PyObject * +keywords_impl(PyObject *module, PyObject *a, PyObject *b) +/*[clinic end generated code: output=850aaed53e26729e input=f44b89e718c1a93b]*/ +{ + return pack_arguments(2, a, b); +} + + +/*[clinic input] +keywords_kwonly + + a: object + * + b: object + +[clinic start generated code]*/ + +static PyObject * +keywords_kwonly_impl(PyObject *module, PyObject *a, PyObject *b) +/*[clinic end generated code: output=a45c48241da584dc input=1f08e39c3312b015]*/ +{ + return pack_arguments(2, a, b); +} + + +/*[clinic input] +keywords_opt + + a: object + b: object = None + c: object = None + +[clinic start generated code]*/ + +static PyObject * +keywords_opt_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c) +/*[clinic end generated code: output=25e4b67d91c76a66 input=b0ba0e4f04904556]*/ +{ + return pack_arguments(3, a, b, c); +} + + +/*[clinic input] +keywords_opt_kwonly + + a: object + b: object = None + * + c: object = None + d: object = None + +[clinic start generated code]*/ + +static PyObject * +keywords_opt_kwonly_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d) +/*[clinic end generated code: output=6aa5b655a6e9aeb0 input=f79da689d6c51076]*/ +{ + return pack_arguments(4, a, b, c, d); +} + + +/*[clinic input] +keywords_kwonly_opt + + a: object + * + b: object = None + c: object = None + +[clinic start generated code]*/ + +static PyObject * +keywords_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c) +/*[clinic end generated code: output=707f78eb0f55c2b1 input=e0fa1a0e46dca791]*/ +{ + return pack_arguments(3, a, b, c); +} + + +/*[clinic input] +posonly_keywords + + a: object + / + b: object + +[clinic start generated code]*/ + +static PyObject * +posonly_keywords_impl(PyObject *module, PyObject *a, PyObject *b) +/*[clinic end generated code: output=6ac88f4a5f0bfc8d input=fde0a2f79fe82b06]*/ +{ + return pack_arguments(2, a, b); +} + + +/*[clinic input] +posonly_kwonly + + a: object + / + * + b: object + +[clinic start generated code]*/ + +static PyObject * +posonly_kwonly_impl(PyObject *module, PyObject *a, PyObject *b) +/*[clinic end generated code: output=483e6790d3482185 input=78b3712768da9a19]*/ +{ + return pack_arguments(2, a, b); +} + + +/*[clinic input] +posonly_keywords_kwonly + + a: object + / + b: object + * + c: object + +[clinic start generated code]*/ + +static PyObject * +posonly_keywords_kwonly_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c) +/*[clinic end generated code: output=2fae573e8cc3fad8 input=a1ad5d2295eb803c]*/ +{ + return pack_arguments(3, a, b, c); +} + + +/*[clinic input] +posonly_keywords_opt + + a: object + / + b: object + c: object = None + d: object = None + +[clinic start generated code]*/ + +static PyObject * +posonly_keywords_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d) +/*[clinic end generated code: output=f5eb66241bcf68fb input=51c10de2a120e279]*/ +{ + return pack_arguments(4, a, b, c, d); +} + + +/*[clinic input] +posonly_opt_keywords_opt + + a: object + b: object = None + / + c: object = None + d: object = None + +[clinic start generated code]*/ + +static PyObject * +posonly_opt_keywords_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d) +/*[clinic end generated code: output=d54a30e549296ffd input=f408a1de7dfaf31f]*/ +{ + return pack_arguments(4, a, b, c, d); +} + + +/*[clinic input] +posonly_kwonly_opt + + a: object + / + * + b: object + c: object = None + d: object = None + +[clinic start generated code]*/ + +static PyObject * +posonly_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d) +/*[clinic end generated code: output=a20503fe36b4fd62 input=3494253975272f52]*/ +{ + return pack_arguments(4, a, b, c, d); +} + + +/*[clinic input] +posonly_opt_kwonly_opt + + a: object + b: object = None + / + * + c: object = None + d: object = None + +[clinic start generated code]*/ + +static PyObject * +posonly_opt_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d) +/*[clinic end generated code: output=64f3204a3a0413b6 input=d17516581e478412]*/ +{ + return pack_arguments(4, a, b, c, d); +} + + +/*[clinic input] +posonly_keywords_kwonly_opt + + a: object + / + b: object + * + c: object + d: object = None + e: object = None + +[clinic start generated code]*/ + +static PyObject * +posonly_keywords_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d, PyObject *e) +/*[clinic end generated code: output=dbd7e7ddd6257fa0 input=33529f29e97e5adb]*/ +{ + return pack_arguments(5, a, b, c, d, e); +} + + +/*[clinic input] +posonly_keywords_opt_kwonly_opt + + a: object + / + b: object + c: object = None + * + d: object = None + e: object = None + +[clinic start generated code]*/ + +static PyObject * +posonly_keywords_opt_kwonly_opt_impl(PyObject *module, PyObject *a, + PyObject *b, PyObject *c, PyObject *d, + PyObject *e) +/*[clinic end generated code: output=775d12ae44653045 input=4d4cc62f11441301]*/ +{ + return pack_arguments(5, a, b, c, d, e); +} + + +/*[clinic input] +posonly_opt_keywords_opt_kwonly_opt + + a: object + b: object = None + / + c: object = None + * + d: object = None + +[clinic start generated code]*/ + +static PyObject * +posonly_opt_keywords_opt_kwonly_opt_impl(PyObject *module, PyObject *a, + PyObject *b, PyObject *c, + PyObject *d) +/*[clinic end generated code: output=40c6dc422591eade input=3964960a68622431]*/ +{ + return pack_arguments(4, a, b, c, d); +} + + +/*[clinic input] +keyword_only_parameter + + * + a: object + +[clinic start generated code]*/ + +static PyObject * +keyword_only_parameter_impl(PyObject *module, PyObject *a) +/*[clinic end generated code: output=c454b6ce98232787 input=8d2868b8d0b27bdb]*/ +{ + return pack_arguments(1, 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(2, a, Py_NewRef(args)); +} + + +/*[clinic input] +vararg + + a: object + *args: object + +[clinic start generated code]*/ + +static PyObject * +vararg_impl(PyObject *module, PyObject *a, PyObject *args) +/*[clinic end generated code: output=91ab7a0efc52dd5e input=02c0f772d05f591e]*/ +{ + return pack_arguments(2, a, Py_NewRef(args)); +} + + +/*[clinic input] +vararg_with_default + + a: object + *args: object + b: bool = False + +[clinic start generated code]*/ + +static PyObject * +vararg_with_default_impl(PyObject *module, PyObject *a, PyObject *args, + int b) +/*[clinic end generated code: output=182c01035958ce92 input=68cafa6a79f89e36]*/ +{ + if (!(b == 0 || b == 1)) { + PyErr_SetString(PyExc_AssertionError, "argument b is not a bool value"); + } + PyObject *obj_b = b ? Py_True : Py_False; + return pack_arguments(3, a, Py_NewRef(args), obj_b); +} + + +/*[clinic input] +vararg_with_only_defaults + + *args: object + b: object = None + +[clinic start generated code]*/ + +static PyObject * +vararg_with_only_defaults_impl(PyObject *module, PyObject *args, PyObject *b) +/*[clinic end generated code: output=c06b1826d91f2f7b input=678c069bc67550e1]*/ +{ + return pack_arguments(2, Py_NewRef(args), b); +} + /*[clinic input] gh_32092_oob @@ -55,6 +980,7 @@ gh_32092_oob_impl(PyObject *module, PyObject *pos1, PyObject *pos2, Py_RETURN_NONE; } + /*[clinic input] gh_32092_kw_pass @@ -80,8 +1006,53 @@ gh_32092_kw_pass_impl(PyObject *module, PyObject *pos, PyObject *args, Py_RETURN_NONE; } + static PyMethodDef tester_methods[] = { TEST_EMPTY_FUNCTION_METHODDEF + OBJECTS_CONVERTER_METHODDEF + BYTES_OBJECT_CONVERTER_METHODDEF + BYTE_ARRAY_OBJECT_CONVERTER_METHODDEF + UNICODE_CONVERTER_METHODDEF + BOOL_CONVERTER_METHODDEF + CHAR_CONVERTER_METHODDEF + UNSIGNED_CHAR_CONVERTER_METHODDEF + SHORT_CONVERTER_METHODDEF + UNSIGNED_SHORT_CONVERTER_METHODDEF + INT_CONVERTER_METHODDEF + UNSIGNED_INT_CONVERTER_METHODDEF + LONG_CONVERTER_METHODDEF + UNSIGNED_LONG_CONVERTER_METHODDEF + LONG_LONG_CONVERTER_METHODDEF + UNSIGNED_LONG_LONG_CONVERTER_METHODDEF + PY_SSIZE_T_CONVERTER_METHODDEF + SLICE_INDEX_CONVERTER_METHODDEF + SIZE_T_CONVERTER_METHODDEF + FLOAT_CONVERTER_METHODDEF + DOUBLE_CONVERTER_METHODDEF + PY_COMPLEX_CONVERTER_METHODDEF + STR_CONVERTER_METHODDEF + STR_CONVERTER_ENCODING_METHODDEF + PY_BUFFER_CONVERTER_METHODDEF + KEYWORDS_METHODDEF + KEYWORDS_KWONLY_METHODDEF + KEYWORDS_OPT_METHODDEF + KEYWORDS_OPT_KWONLY_METHODDEF + KEYWORDS_KWONLY_OPT_METHODDEF + POSONLY_KEYWORDS_METHODDEF + POSONLY_KWONLY_METHODDEF + POSONLY_KEYWORDS_KWONLY_METHODDEF + POSONLY_KEYWORDS_OPT_METHODDEF + POSONLY_OPT_KEYWORDS_OPT_METHODDEF + POSONLY_KWONLY_OPT_METHODDEF + POSONLY_OPT_KWONLY_OPT_METHODDEF + POSONLY_KEYWORDS_KWONLY_OPT_METHODDEF + POSONLY_KEYWORDS_OPT_KWONLY_OPT_METHODDEF + POSONLY_OPT_KEYWORDS_OPT_KWONLY_OPT_METHODDEF + KEYWORD_ONLY_PARAMETER_METHODDEF + VARARG_AND_POSONLY_METHODDEF + VARARG_METHODDEF + VARARG_WITH_DEFAULT_METHODDEF + VARARG_WITH_ONLY_DEFAULTS_METHODDEF GH_32092_OOB_METHODDEF GH_32092_KW_PASS_METHODDEF {NULL, NULL} diff --git a/Modules/clinic/_testclinic.c.h b/Modules/clinic/_testclinic.c.h index 599fcb46b8d769..b3190fb7d67a54 100644 --- a/Modules/clinic/_testclinic.c.h +++ b/Modules/clinic/_testclinic.c.h @@ -25,6 +25,2535 @@ test_empty_function(PyObject *module, PyObject *Py_UNUSED(ignored)) return test_empty_function_impl(module); } +PyDoc_STRVAR(objects_converter__doc__, +"objects_converter($module, a, b=, /)\n" +"--\n" +"\n"); + +#define OBJECTS_CONVERTER_METHODDEF \ + {"objects_converter", _PyCFunction_CAST(objects_converter), METH_FASTCALL, objects_converter__doc__}, + +static PyObject * +objects_converter_impl(PyObject *module, PyObject *a, PyObject *b); + +static PyObject * +objects_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *a; + PyObject *b = NULL; + + if (!_PyArg_CheckPositional("objects_converter", nargs, 1, 2)) { + goto exit; + } + a = args[0]; + if (nargs < 2) { + goto skip_optional; + } + b = args[1]; +skip_optional: + return_value = objects_converter_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_STRVAR(bytes_object_converter__doc__, +"bytes_object_converter($module, a, /)\n" +"--\n" +"\n"); + +#define BYTES_OBJECT_CONVERTER_METHODDEF \ + {"bytes_object_converter", (PyCFunction)bytes_object_converter, METH_O, bytes_object_converter__doc__}, + +static PyObject * +bytes_object_converter_impl(PyObject *module, PyBytesObject *a); + +static PyObject * +bytes_object_converter(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyBytesObject *a; + + if (!PyBytes_Check(arg)) { + _PyArg_BadArgument("bytes_object_converter", "argument", "bytes", arg); + goto exit; + } + a = (PyBytesObject *)arg; + return_value = bytes_object_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(byte_array_object_converter__doc__, +"byte_array_object_converter($module, a, /)\n" +"--\n" +"\n"); + +#define BYTE_ARRAY_OBJECT_CONVERTER_METHODDEF \ + {"byte_array_object_converter", (PyCFunction)byte_array_object_converter, METH_O, byte_array_object_converter__doc__}, + +static PyObject * +byte_array_object_converter_impl(PyObject *module, PyByteArrayObject *a); + +static PyObject * +byte_array_object_converter(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyByteArrayObject *a; + + if (!PyByteArray_Check(arg)) { + _PyArg_BadArgument("byte_array_object_converter", "argument", "bytearray", arg); + goto exit; + } + a = (PyByteArrayObject *)arg; + return_value = byte_array_object_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(unicode_converter__doc__, +"unicode_converter($module, a, /)\n" +"--\n" +"\n"); + +#define UNICODE_CONVERTER_METHODDEF \ + {"unicode_converter", (PyCFunction)unicode_converter, METH_O, unicode_converter__doc__}, + +static PyObject * +unicode_converter_impl(PyObject *module, PyObject *a); + +static PyObject * +unicode_converter(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *a; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("unicode_converter", "argument", "str", arg); + goto exit; + } + if (PyUnicode_READY(arg) == -1) { + goto exit; + } + a = arg; + return_value = unicode_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(bool_converter__doc__, +"bool_converter($module, a=True, b=True, c=True, /)\n" +"--\n" +"\n"); + +#define BOOL_CONVERTER_METHODDEF \ + {"bool_converter", _PyCFunction_CAST(bool_converter), METH_FASTCALL, bool_converter__doc__}, + +static PyObject * +bool_converter_impl(PyObject *module, int a, int b, int c); + +static PyObject * +bool_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int a = 1; + int b = 1; + int c = 1; + + if (!_PyArg_CheckPositional("bool_converter", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + a = PyObject_IsTrue(args[0]); + if (a < 0) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + b = PyObject_IsTrue(args[1]); + if (b < 0) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + c = _PyLong_AsInt(args[2]); + if (c == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = bool_converter_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(char_converter__doc__, +"char_converter($module, a=b\'A\', b=b\'\\x07\', c=b\'\\x08\', d=b\'\\t\', e=b\'\\n\',\n" +" f=b\'\\x0b\', g=b\'\\x0c\', h=b\'\\r\', i=b\'\"\', j=b\"\'\", k=b\'?\',\n" +" l=b\'\\\\\', m=b\'\\x00\', n=b\'\\xff\', /)\n" +"--\n" +"\n"); + +#define CHAR_CONVERTER_METHODDEF \ + {"char_converter", _PyCFunction_CAST(char_converter), METH_FASTCALL, char_converter__doc__}, + +static PyObject * +char_converter_impl(PyObject *module, char a, char b, char c, char d, char e, + char f, char g, char h, char i, char j, char k, char l, + char m, char n); + +static PyObject * +char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + char a = 'A'; + char b = '\x07'; + char c = '\x08'; + char d = '\t'; + char e = '\n'; + char f = '\x0b'; + char g = '\x0c'; + char h = '\r'; + char i = '"'; + char j = '\''; + char k = '?'; + char l = '\\'; + char m = '\x00'; + char n = '\xff'; + + if (!_PyArg_CheckPositional("char_converter", nargs, 0, 14)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + if (PyBytes_Check(args[0]) && PyBytes_GET_SIZE(args[0]) == 1) { + a = PyBytes_AS_STRING(args[0])[0]; + } + else if (PyByteArray_Check(args[0]) && PyByteArray_GET_SIZE(args[0]) == 1) { + a = PyByteArray_AS_STRING(args[0])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 1", "a byte string of length 1", args[0]); + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + if (PyBytes_Check(args[1]) && PyBytes_GET_SIZE(args[1]) == 1) { + b = PyBytes_AS_STRING(args[1])[0]; + } + else if (PyByteArray_Check(args[1]) && PyByteArray_GET_SIZE(args[1]) == 1) { + b = PyByteArray_AS_STRING(args[1])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 2", "a byte string of length 1", args[1]); + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + if (PyBytes_Check(args[2]) && PyBytes_GET_SIZE(args[2]) == 1) { + c = PyBytes_AS_STRING(args[2])[0]; + } + else if (PyByteArray_Check(args[2]) && PyByteArray_GET_SIZE(args[2]) == 1) { + c = PyByteArray_AS_STRING(args[2])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 3", "a byte string of length 1", args[2]); + goto exit; + } + if (nargs < 4) { + goto skip_optional; + } + if (PyBytes_Check(args[3]) && PyBytes_GET_SIZE(args[3]) == 1) { + d = PyBytes_AS_STRING(args[3])[0]; + } + else if (PyByteArray_Check(args[3]) && PyByteArray_GET_SIZE(args[3]) == 1) { + d = PyByteArray_AS_STRING(args[3])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 4", "a byte string of length 1", args[3]); + goto exit; + } + if (nargs < 5) { + goto skip_optional; + } + if (PyBytes_Check(args[4]) && PyBytes_GET_SIZE(args[4]) == 1) { + e = PyBytes_AS_STRING(args[4])[0]; + } + else if (PyByteArray_Check(args[4]) && PyByteArray_GET_SIZE(args[4]) == 1) { + e = PyByteArray_AS_STRING(args[4])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 5", "a byte string of length 1", args[4]); + goto exit; + } + if (nargs < 6) { + goto skip_optional; + } + if (PyBytes_Check(args[5]) && PyBytes_GET_SIZE(args[5]) == 1) { + f = PyBytes_AS_STRING(args[5])[0]; + } + else if (PyByteArray_Check(args[5]) && PyByteArray_GET_SIZE(args[5]) == 1) { + f = PyByteArray_AS_STRING(args[5])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 6", "a byte string of length 1", args[5]); + goto exit; + } + if (nargs < 7) { + goto skip_optional; + } + if (PyBytes_Check(args[6]) && PyBytes_GET_SIZE(args[6]) == 1) { + g = PyBytes_AS_STRING(args[6])[0]; + } + else if (PyByteArray_Check(args[6]) && PyByteArray_GET_SIZE(args[6]) == 1) { + g = PyByteArray_AS_STRING(args[6])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 7", "a byte string of length 1", args[6]); + goto exit; + } + if (nargs < 8) { + goto skip_optional; + } + if (PyBytes_Check(args[7]) && PyBytes_GET_SIZE(args[7]) == 1) { + h = PyBytes_AS_STRING(args[7])[0]; + } + else if (PyByteArray_Check(args[7]) && PyByteArray_GET_SIZE(args[7]) == 1) { + h = PyByteArray_AS_STRING(args[7])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 8", "a byte string of length 1", args[7]); + goto exit; + } + if (nargs < 9) { + goto skip_optional; + } + if (PyBytes_Check(args[8]) && PyBytes_GET_SIZE(args[8]) == 1) { + i = PyBytes_AS_STRING(args[8])[0]; + } + else if (PyByteArray_Check(args[8]) && PyByteArray_GET_SIZE(args[8]) == 1) { + i = PyByteArray_AS_STRING(args[8])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 9", "a byte string of length 1", args[8]); + goto exit; + } + if (nargs < 10) { + goto skip_optional; + } + if (PyBytes_Check(args[9]) && PyBytes_GET_SIZE(args[9]) == 1) { + j = PyBytes_AS_STRING(args[9])[0]; + } + else if (PyByteArray_Check(args[9]) && PyByteArray_GET_SIZE(args[9]) == 1) { + j = PyByteArray_AS_STRING(args[9])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 10", "a byte string of length 1", args[9]); + goto exit; + } + if (nargs < 11) { + goto skip_optional; + } + if (PyBytes_Check(args[10]) && PyBytes_GET_SIZE(args[10]) == 1) { + k = PyBytes_AS_STRING(args[10])[0]; + } + else if (PyByteArray_Check(args[10]) && PyByteArray_GET_SIZE(args[10]) == 1) { + k = PyByteArray_AS_STRING(args[10])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 11", "a byte string of length 1", args[10]); + goto exit; + } + if (nargs < 12) { + goto skip_optional; + } + if (PyBytes_Check(args[11]) && PyBytes_GET_SIZE(args[11]) == 1) { + l = PyBytes_AS_STRING(args[11])[0]; + } + else if (PyByteArray_Check(args[11]) && PyByteArray_GET_SIZE(args[11]) == 1) { + l = PyByteArray_AS_STRING(args[11])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 12", "a byte string of length 1", args[11]); + goto exit; + } + if (nargs < 13) { + goto skip_optional; + } + if (PyBytes_Check(args[12]) && PyBytes_GET_SIZE(args[12]) == 1) { + m = PyBytes_AS_STRING(args[12])[0]; + } + else if (PyByteArray_Check(args[12]) && PyByteArray_GET_SIZE(args[12]) == 1) { + m = PyByteArray_AS_STRING(args[12])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 13", "a byte string of length 1", args[12]); + goto exit; + } + if (nargs < 14) { + goto skip_optional; + } + if (PyBytes_Check(args[13]) && PyBytes_GET_SIZE(args[13]) == 1) { + n = PyBytes_AS_STRING(args[13])[0]; + } + else if (PyByteArray_Check(args[13]) && PyByteArray_GET_SIZE(args[13]) == 1) { + n = PyByteArray_AS_STRING(args[13])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 14", "a byte string of length 1", args[13]); + goto exit; + } +skip_optional: + return_value = char_converter_impl(module, a, b, c, d, e, f, g, h, i, j, k, l, m, n); + +exit: + return return_value; +} + +PyDoc_STRVAR(unsigned_char_converter__doc__, +"unsigned_char_converter($module, a=12, b=34, c=56, /)\n" +"--\n" +"\n"); + +#define UNSIGNED_CHAR_CONVERTER_METHODDEF \ + {"unsigned_char_converter", _PyCFunction_CAST(unsigned_char_converter), METH_FASTCALL, unsigned_char_converter__doc__}, + +static PyObject * +unsigned_char_converter_impl(PyObject *module, unsigned char a, + unsigned char b, unsigned char c); + +static PyObject * +unsigned_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + unsigned char a = 12; + unsigned char b = 34; + unsigned char c = 56; + + if (!_PyArg_CheckPositional("unsigned_char_converter", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + { + long ival = PyLong_AsLong(args[0]); + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + else if (ival < 0) { + PyErr_SetString(PyExc_OverflowError, + "unsigned byte integer is less than minimum"); + goto exit; + } + else if (ival > UCHAR_MAX) { + PyErr_SetString(PyExc_OverflowError, + "unsigned byte integer is greater than maximum"); + goto exit; + } + else { + a = (unsigned char) ival; + } + } + if (nargs < 2) { + goto skip_optional; + } + { + long ival = PyLong_AsLong(args[1]); + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + else if (ival < 0) { + PyErr_SetString(PyExc_OverflowError, + "unsigned byte integer is less than minimum"); + goto exit; + } + else if (ival > UCHAR_MAX) { + PyErr_SetString(PyExc_OverflowError, + "unsigned byte integer is greater than maximum"); + goto exit; + } + else { + b = (unsigned char) ival; + } + } + if (nargs < 3) { + goto skip_optional; + } + { + unsigned long ival = PyLong_AsUnsignedLongMask(args[2]); + if (ival == (unsigned long)-1 && PyErr_Occurred()) { + goto exit; + } + else { + c = (unsigned char) ival; + } + } +skip_optional: + return_value = unsigned_char_converter_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(short_converter__doc__, +"short_converter($module, a=12, /)\n" +"--\n" +"\n"); + +#define SHORT_CONVERTER_METHODDEF \ + {"short_converter", _PyCFunction_CAST(short_converter), METH_FASTCALL, short_converter__doc__}, + +static PyObject * +short_converter_impl(PyObject *module, short a); + +static PyObject * +short_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + short a = 12; + + if (!_PyArg_CheckPositional("short_converter", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + { + long ival = PyLong_AsLong(args[0]); + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + else if (ival < SHRT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is less than minimum"); + goto exit; + } + else if (ival > SHRT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is greater than maximum"); + goto exit; + } + else { + a = (short) ival; + } + } +skip_optional: + return_value = short_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(unsigned_short_converter__doc__, +"unsigned_short_converter($module, a=12, b=34, c=56, /)\n" +"--\n" +"\n"); + +#define UNSIGNED_SHORT_CONVERTER_METHODDEF \ + {"unsigned_short_converter", _PyCFunction_CAST(unsigned_short_converter), METH_FASTCALL, unsigned_short_converter__doc__}, + +static PyObject * +unsigned_short_converter_impl(PyObject *module, unsigned short a, + unsigned short b, unsigned short c); + +static PyObject * +unsigned_short_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + unsigned short a = 12; + unsigned short b = 34; + unsigned short c = 56; + + if (!_PyArg_CheckPositional("unsigned_short_converter", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + if (!_PyLong_UnsignedShort_Converter(args[0], &a)) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + if (!_PyLong_UnsignedShort_Converter(args[1], &b)) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + c = (unsigned short)PyLong_AsUnsignedLongMask(args[2]); + if (c == (unsigned short)-1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = unsigned_short_converter_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(int_converter__doc__, +"int_converter($module, a=12, b=34, c=45, /)\n" +"--\n" +"\n"); + +#define INT_CONVERTER_METHODDEF \ + {"int_converter", _PyCFunction_CAST(int_converter), METH_FASTCALL, int_converter__doc__}, + +static PyObject * +int_converter_impl(PyObject *module, int a, int b, int c); + +static PyObject * +int_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int a = 12; + int b = 34; + int c = 45; + + if (!_PyArg_CheckPositional("int_converter", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + a = _PyLong_AsInt(args[0]); + if (a == -1 && PyErr_Occurred()) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + b = _PyLong_AsInt(args[1]); + if (b == -1 && PyErr_Occurred()) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + if (!PyUnicode_Check(args[2])) { + _PyArg_BadArgument("int_converter", "argument 3", "a unicode character", args[2]); + goto exit; + } + if (PyUnicode_READY(args[2])) { + goto exit; + } + if (PyUnicode_GET_LENGTH(args[2]) != 1) { + _PyArg_BadArgument("int_converter", "argument 3", "a unicode character", args[2]); + goto exit; + } + c = PyUnicode_READ_CHAR(args[2], 0); +skip_optional: + return_value = int_converter_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(unsigned_int_converter__doc__, +"unsigned_int_converter($module, a=12, b=34, c=56, /)\n" +"--\n" +"\n"); + +#define UNSIGNED_INT_CONVERTER_METHODDEF \ + {"unsigned_int_converter", _PyCFunction_CAST(unsigned_int_converter), METH_FASTCALL, unsigned_int_converter__doc__}, + +static PyObject * +unsigned_int_converter_impl(PyObject *module, unsigned int a, unsigned int b, + unsigned int c); + +static PyObject * +unsigned_int_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + unsigned int a = 12; + unsigned int b = 34; + unsigned int c = 56; + + if (!_PyArg_CheckPositional("unsigned_int_converter", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + if (!_PyLong_UnsignedInt_Converter(args[0], &a)) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + if (!_PyLong_UnsignedInt_Converter(args[1], &b)) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + c = (unsigned int)PyLong_AsUnsignedLongMask(args[2]); + if (c == (unsigned int)-1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = unsigned_int_converter_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(long_converter__doc__, +"long_converter($module, a=12, /)\n" +"--\n" +"\n"); + +#define LONG_CONVERTER_METHODDEF \ + {"long_converter", _PyCFunction_CAST(long_converter), METH_FASTCALL, long_converter__doc__}, + +static PyObject * +long_converter_impl(PyObject *module, long a); + +static PyObject * +long_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + long a = 12; + + if (!_PyArg_CheckPositional("long_converter", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + a = PyLong_AsLong(args[0]); + if (a == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = long_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(unsigned_long_converter__doc__, +"unsigned_long_converter($module, a=12, b=34, c=56, /)\n" +"--\n" +"\n"); + +#define UNSIGNED_LONG_CONVERTER_METHODDEF \ + {"unsigned_long_converter", _PyCFunction_CAST(unsigned_long_converter), METH_FASTCALL, unsigned_long_converter__doc__}, + +static PyObject * +unsigned_long_converter_impl(PyObject *module, unsigned long a, + unsigned long b, unsigned long c); + +static PyObject * +unsigned_long_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + unsigned long a = 12; + unsigned long b = 34; + unsigned long c = 56; + + if (!_PyArg_CheckPositional("unsigned_long_converter", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + if (!_PyLong_UnsignedLong_Converter(args[0], &a)) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + if (!_PyLong_UnsignedLong_Converter(args[1], &b)) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + if (!PyLong_Check(args[2])) { + _PyArg_BadArgument("unsigned_long_converter", "argument 3", "int", args[2]); + goto exit; + } + c = PyLong_AsUnsignedLongMask(args[2]); +skip_optional: + return_value = unsigned_long_converter_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(long_long_converter__doc__, +"long_long_converter($module, a=12, /)\n" +"--\n" +"\n"); + +#define LONG_LONG_CONVERTER_METHODDEF \ + {"long_long_converter", _PyCFunction_CAST(long_long_converter), METH_FASTCALL, long_long_converter__doc__}, + +static PyObject * +long_long_converter_impl(PyObject *module, long long a); + +static PyObject * +long_long_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + long long a = 12; + + if (!_PyArg_CheckPositional("long_long_converter", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + a = PyLong_AsLongLong(args[0]); + if (a == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = long_long_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(unsigned_long_long_converter__doc__, +"unsigned_long_long_converter($module, a=12, b=34, c=56, /)\n" +"--\n" +"\n"); + +#define UNSIGNED_LONG_LONG_CONVERTER_METHODDEF \ + {"unsigned_long_long_converter", _PyCFunction_CAST(unsigned_long_long_converter), METH_FASTCALL, unsigned_long_long_converter__doc__}, + +static PyObject * +unsigned_long_long_converter_impl(PyObject *module, unsigned long long a, + unsigned long long b, unsigned long long c); + +static PyObject * +unsigned_long_long_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + unsigned long long a = 12; + unsigned long long b = 34; + unsigned long long c = 56; + + if (!_PyArg_CheckPositional("unsigned_long_long_converter", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + if (!_PyLong_UnsignedLongLong_Converter(args[0], &a)) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + if (!_PyLong_UnsignedLongLong_Converter(args[1], &b)) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + if (!PyLong_Check(args[2])) { + _PyArg_BadArgument("unsigned_long_long_converter", "argument 3", "int", args[2]); + goto exit; + } + c = PyLong_AsUnsignedLongLongMask(args[2]); +skip_optional: + return_value = unsigned_long_long_converter_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(py_ssize_t_converter__doc__, +"py_ssize_t_converter($module, a=12, b=34, c=56, /)\n" +"--\n" +"\n"); + +#define PY_SSIZE_T_CONVERTER_METHODDEF \ + {"py_ssize_t_converter", _PyCFunction_CAST(py_ssize_t_converter), METH_FASTCALL, py_ssize_t_converter__doc__}, + +static PyObject * +py_ssize_t_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b, + Py_ssize_t c); + +static PyObject * +py_ssize_t_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + Py_ssize_t a = 12; + Py_ssize_t b = 34; + Py_ssize_t c = 56; + + if (!_PyArg_CheckPositional("py_ssize_t_converter", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[0]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + a = ival; + } + if (nargs < 2) { + goto skip_optional; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + b = ival; + } + if (nargs < 3) { + goto skip_optional; + } + if (!_Py_convert_optional_to_ssize_t(args[2], &c)) { + goto exit; + } +skip_optional: + return_value = py_ssize_t_converter_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(slice_index_converter__doc__, +"slice_index_converter($module, a=12, b=34, c=56, /)\n" +"--\n" +"\n"); + +#define SLICE_INDEX_CONVERTER_METHODDEF \ + {"slice_index_converter", _PyCFunction_CAST(slice_index_converter), METH_FASTCALL, slice_index_converter__doc__}, + +static PyObject * +slice_index_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b, + Py_ssize_t c); + +static PyObject * +slice_index_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + Py_ssize_t a = 12; + Py_ssize_t b = 34; + Py_ssize_t c = 56; + + if (!_PyArg_CheckPositional("slice_index_converter", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[0], &a)) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndexNotNone(args[1], &b)) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[2], &c)) { + goto exit; + } +skip_optional: + return_value = slice_index_converter_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(size_t_converter__doc__, +"size_t_converter($module, a=12, /)\n" +"--\n" +"\n"); + +#define SIZE_T_CONVERTER_METHODDEF \ + {"size_t_converter", _PyCFunction_CAST(size_t_converter), METH_FASTCALL, size_t_converter__doc__}, + +static PyObject * +size_t_converter_impl(PyObject *module, size_t a); + +static PyObject * +size_t_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + size_t a = 12; + + if (!_PyArg_CheckPositional("size_t_converter", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + if (!_PyLong_Size_t_Converter(args[0], &a)) { + goto exit; + } +skip_optional: + return_value = size_t_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(float_converter__doc__, +"float_converter($module, a=12.5, /)\n" +"--\n" +"\n"); + +#define FLOAT_CONVERTER_METHODDEF \ + {"float_converter", _PyCFunction_CAST(float_converter), METH_FASTCALL, float_converter__doc__}, + +static PyObject * +float_converter_impl(PyObject *module, float a); + +static PyObject * +float_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + float a = 12.5; + + if (!_PyArg_CheckPositional("float_converter", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + if (PyFloat_CheckExact(args[0])) { + a = (float) (PyFloat_AS_DOUBLE(args[0])); + } + else + { + a = (float) PyFloat_AsDouble(args[0]); + if (a == -1.0 && PyErr_Occurred()) { + goto exit; + } + } +skip_optional: + return_value = float_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(double_converter__doc__, +"double_converter($module, a=12.5, /)\n" +"--\n" +"\n"); + +#define DOUBLE_CONVERTER_METHODDEF \ + {"double_converter", _PyCFunction_CAST(double_converter), METH_FASTCALL, double_converter__doc__}, + +static PyObject * +double_converter_impl(PyObject *module, double a); + +static PyObject * +double_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + double a = 12.5; + + if (!_PyArg_CheckPositional("double_converter", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + if (PyFloat_CheckExact(args[0])) { + a = PyFloat_AS_DOUBLE(args[0]); + } + else + { + a = PyFloat_AsDouble(args[0]); + if (a == -1.0 && PyErr_Occurred()) { + goto exit; + } + } +skip_optional: + return_value = double_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(py_complex_converter__doc__, +"py_complex_converter($module, a, /)\n" +"--\n" +"\n"); + +#define PY_COMPLEX_CONVERTER_METHODDEF \ + {"py_complex_converter", (PyCFunction)py_complex_converter, METH_O, py_complex_converter__doc__}, + +static PyObject * +py_complex_converter_impl(PyObject *module, Py_complex a); + +static PyObject * +py_complex_converter(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + Py_complex a; + + a = PyComplex_AsCComplex(arg); + if (PyErr_Occurred()) { + goto exit; + } + return_value = py_complex_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(str_converter__doc__, +"str_converter($module, a=\'a\', b=\'b\', c=\'c\', /)\n" +"--\n" +"\n"); + +#define STR_CONVERTER_METHODDEF \ + {"str_converter", _PyCFunction_CAST(str_converter), METH_FASTCALL, str_converter__doc__}, + +static PyObject * +str_converter_impl(PyObject *module, const char *a, const char *b, + const char *c, Py_ssize_t c_length); + +static PyObject * +str_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + const char *a = "a"; + const char *b = "b"; + const char *c = "c"; + Py_ssize_t c_length; + + if (!_PyArg_ParseStack(args, nargs, "|sys#:str_converter", + &a, &b, &c, &c_length)) { + goto exit; + } + return_value = str_converter_impl(module, a, b, c, c_length); + +exit: + return return_value; +} + +PyDoc_STRVAR(str_converter_encoding__doc__, +"str_converter_encoding($module, a, b, c, /)\n" +"--\n" +"\n"); + +#define STR_CONVERTER_ENCODING_METHODDEF \ + {"str_converter_encoding", _PyCFunction_CAST(str_converter_encoding), METH_FASTCALL, str_converter_encoding__doc__}, + +static PyObject * +str_converter_encoding_impl(PyObject *module, char *a, char *b, char *c, + Py_ssize_t c_length); + +static PyObject * +str_converter_encoding(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + char *a = NULL; + char *b = NULL; + char *c = NULL; + Py_ssize_t c_length; + + if (!_PyArg_ParseStack(args, nargs, "esetet#:str_converter_encoding", + "idna", &a, "idna", &b, "idna", &c, &c_length)) { + goto exit; + } + return_value = str_converter_encoding_impl(module, a, b, c, c_length); + +exit: + /* Cleanup for a */ + if (a) { + PyMem_FREE(a); + } + /* Cleanup for b */ + if (b) { + PyMem_FREE(b); + } + /* Cleanup for c */ + if (c) { + PyMem_FREE(c); + } + + return return_value; +} + +PyDoc_STRVAR(py_buffer_converter__doc__, +"py_buffer_converter($module, a, b, /)\n" +"--\n" +"\n"); + +#define PY_BUFFER_CONVERTER_METHODDEF \ + {"py_buffer_converter", _PyCFunction_CAST(py_buffer_converter), METH_FASTCALL, py_buffer_converter__doc__}, + +static PyObject * +py_buffer_converter_impl(PyObject *module, Py_buffer *a, Py_buffer *b); + +static PyObject * +py_buffer_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + Py_buffer a = {NULL, NULL}; + Py_buffer b = {NULL, NULL}; + + if (!_PyArg_ParseStack(args, nargs, "z*w*:py_buffer_converter", + &a, &b)) { + goto exit; + } + return_value = py_buffer_converter_impl(module, &a, &b); + +exit: + /* Cleanup for a */ + if (a.obj) { + PyBuffer_Release(&a); + } + /* Cleanup for b */ + if (b.obj) { + PyBuffer_Release(&b); + } + + return return_value; +} + +PyDoc_STRVAR(keywords__doc__, +"keywords($module, /, a, b)\n" +"--\n" +"\n"); + +#define KEYWORDS_METHODDEF \ + {"keywords", _PyCFunction_CAST(keywords), METH_FASTCALL|METH_KEYWORDS, keywords__doc__}, + +static PyObject * +keywords_impl(PyObject *module, PyObject *a, PyObject *b); + +static PyObject * +keywords(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"a", "b", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "keywords", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + PyObject *a; + PyObject *b; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + return_value = keywords_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_STRVAR(keywords_kwonly__doc__, +"keywords_kwonly($module, /, a, *, b)\n" +"--\n" +"\n"); + +#define KEYWORDS_KWONLY_METHODDEF \ + {"keywords_kwonly", _PyCFunction_CAST(keywords_kwonly), METH_FASTCALL|METH_KEYWORDS, keywords_kwonly__doc__}, + +static PyObject * +keywords_kwonly_impl(PyObject *module, PyObject *a, PyObject *b); + +static PyObject * +keywords_kwonly(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"a", "b", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "keywords_kwonly", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + PyObject *a; + PyObject *b; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + return_value = keywords_kwonly_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_STRVAR(keywords_opt__doc__, +"keywords_opt($module, /, a, b=None, c=None)\n" +"--\n" +"\n"); + +#define KEYWORDS_OPT_METHODDEF \ + {"keywords_opt", _PyCFunction_CAST(keywords_opt), METH_FASTCALL|METH_KEYWORDS, keywords_opt__doc__}, + +static PyObject * +keywords_opt_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c); + +static PyObject * +keywords_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"a", "b", "c", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "keywords_opt", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *a; + PyObject *b = Py_None; + PyObject *c = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + b = args[1]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + c = args[2]; +skip_optional_pos: + return_value = keywords_opt_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(keywords_opt_kwonly__doc__, +"keywords_opt_kwonly($module, /, a, b=None, *, c=None, d=None)\n" +"--\n" +"\n"); + +#define KEYWORDS_OPT_KWONLY_METHODDEF \ + {"keywords_opt_kwonly", _PyCFunction_CAST(keywords_opt_kwonly), METH_FASTCALL|METH_KEYWORDS, keywords_opt_kwonly__doc__}, + +static PyObject * +keywords_opt_kwonly_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d); + +static PyObject * +keywords_opt_kwonly(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"a", "b", "c", "d", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "keywords_opt_kwonly", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *a; + PyObject *b = Py_None; + PyObject *c = Py_None; + PyObject *d = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + b = args[1]; + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[2]) { + c = args[2]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + d = args[3]; +skip_optional_kwonly: + return_value = keywords_opt_kwonly_impl(module, a, b, c, d); + +exit: + return return_value; +} + +PyDoc_STRVAR(keywords_kwonly_opt__doc__, +"keywords_kwonly_opt($module, /, a, *, b=None, c=None)\n" +"--\n" +"\n"); + +#define KEYWORDS_KWONLY_OPT_METHODDEF \ + {"keywords_kwonly_opt", _PyCFunction_CAST(keywords_kwonly_opt), METH_FASTCALL|METH_KEYWORDS, keywords_kwonly_opt__doc__}, + +static PyObject * +keywords_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c); + +static PyObject * +keywords_kwonly_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), &_Py_ID(c), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"a", "b", "c", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "keywords_kwonly_opt", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *a; + PyObject *b = Py_None; + PyObject *c = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[1]) { + b = args[1]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + c = args[2]; +skip_optional_kwonly: + return_value = keywords_kwonly_opt_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_keywords__doc__, +"posonly_keywords($module, a, /, b)\n" +"--\n" +"\n"); + +#define POSONLY_KEYWORDS_METHODDEF \ + {"posonly_keywords", _PyCFunction_CAST(posonly_keywords), METH_FASTCALL|METH_KEYWORDS, posonly_keywords__doc__}, + +static PyObject * +posonly_keywords_impl(PyObject *module, PyObject *a, PyObject *b); + +static PyObject * +posonly_keywords(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(b), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "b", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "posonly_keywords", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + PyObject *a; + PyObject *b; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + return_value = posonly_keywords_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_kwonly__doc__, +"posonly_kwonly($module, a, /, *, b)\n" +"--\n" +"\n"); + +#define POSONLY_KWONLY_METHODDEF \ + {"posonly_kwonly", _PyCFunction_CAST(posonly_kwonly), METH_FASTCALL|METH_KEYWORDS, posonly_kwonly__doc__}, + +static PyObject * +posonly_kwonly_impl(PyObject *module, PyObject *a, PyObject *b); + +static PyObject * +posonly_kwonly(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(b), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "b", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "posonly_kwonly", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + PyObject *a; + PyObject *b; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + return_value = posonly_kwonly_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_keywords_kwonly__doc__, +"posonly_keywords_kwonly($module, a, /, b, *, c)\n" +"--\n" +"\n"); + +#define POSONLY_KEYWORDS_KWONLY_METHODDEF \ + {"posonly_keywords_kwonly", _PyCFunction_CAST(posonly_keywords_kwonly), METH_FASTCALL|METH_KEYWORDS, posonly_keywords_kwonly__doc__}, + +static PyObject * +posonly_keywords_kwonly_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c); + +static PyObject * +posonly_keywords_kwonly(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(b), &_Py_ID(c), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "b", "c", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "posonly_keywords_kwonly", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + PyObject *a; + PyObject *b; + PyObject *c; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + c = args[2]; + return_value = posonly_keywords_kwonly_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_keywords_opt__doc__, +"posonly_keywords_opt($module, a, /, b, c=None, d=None)\n" +"--\n" +"\n"); + +#define POSONLY_KEYWORDS_OPT_METHODDEF \ + {"posonly_keywords_opt", _PyCFunction_CAST(posonly_keywords_opt), METH_FASTCALL|METH_KEYWORDS, posonly_keywords_opt__doc__}, + +static PyObject * +posonly_keywords_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d); + +static PyObject * +posonly_keywords_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "b", "c", "d", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "posonly_keywords_opt", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + PyObject *a; + PyObject *b; + PyObject *c = Py_None; + PyObject *d = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 4, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + if (!noptargs) { + goto skip_optional_pos; + } + if (args[2]) { + c = args[2]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + d = args[3]; +skip_optional_pos: + return_value = posonly_keywords_opt_impl(module, a, b, c, d); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_opt_keywords_opt__doc__, +"posonly_opt_keywords_opt($module, a, b=None, /, c=None, d=None)\n" +"--\n" +"\n"); + +#define POSONLY_OPT_KEYWORDS_OPT_METHODDEF \ + {"posonly_opt_keywords_opt", _PyCFunction_CAST(posonly_opt_keywords_opt), METH_FASTCALL|METH_KEYWORDS, posonly_opt_keywords_opt__doc__}, + +static PyObject * +posonly_opt_keywords_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d); + +static PyObject * +posonly_opt_keywords_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(c), &_Py_ID(d), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "", "c", "d", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "posonly_opt_keywords_opt", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *a; + PyObject *b = Py_None; + PyObject *c = Py_None; + PyObject *d = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 4, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + if (nargs < 2) { + goto skip_optional_posonly; + } + noptargs--; + b = args[1]; +skip_optional_posonly: + if (!noptargs) { + goto skip_optional_pos; + } + if (args[2]) { + c = args[2]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + d = args[3]; +skip_optional_pos: + return_value = posonly_opt_keywords_opt_impl(module, a, b, c, d); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_kwonly_opt__doc__, +"posonly_kwonly_opt($module, a, /, *, b, c=None, d=None)\n" +"--\n" +"\n"); + +#define POSONLY_KWONLY_OPT_METHODDEF \ + {"posonly_kwonly_opt", _PyCFunction_CAST(posonly_kwonly_opt), METH_FASTCALL|METH_KEYWORDS, posonly_kwonly_opt__doc__}, + +static PyObject * +posonly_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d); + +static PyObject * +posonly_kwonly_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "b", "c", "d", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "posonly_kwonly_opt", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + PyObject *a; + PyObject *b; + PyObject *c = Py_None; + PyObject *d = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[2]) { + c = args[2]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + d = args[3]; +skip_optional_kwonly: + return_value = posonly_kwonly_opt_impl(module, a, b, c, d); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_opt_kwonly_opt__doc__, +"posonly_opt_kwonly_opt($module, a, b=None, /, *, c=None, d=None)\n" +"--\n" +"\n"); + +#define POSONLY_OPT_KWONLY_OPT_METHODDEF \ + {"posonly_opt_kwonly_opt", _PyCFunction_CAST(posonly_opt_kwonly_opt), METH_FASTCALL|METH_KEYWORDS, posonly_opt_kwonly_opt__doc__}, + +static PyObject * +posonly_opt_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d); + +static PyObject * +posonly_opt_kwonly_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(c), &_Py_ID(d), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "", "c", "d", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "posonly_opt_kwonly_opt", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *a; + PyObject *b = Py_None; + PyObject *c = Py_None; + PyObject *d = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + if (nargs < 2) { + goto skip_optional_posonly; + } + noptargs--; + b = args[1]; +skip_optional_posonly: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[2]) { + c = args[2]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + d = args[3]; +skip_optional_kwonly: + return_value = posonly_opt_kwonly_opt_impl(module, a, b, c, d); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_keywords_kwonly_opt__doc__, +"posonly_keywords_kwonly_opt($module, a, /, b, *, c, d=None, e=None)\n" +"--\n" +"\n"); + +#define POSONLY_KEYWORDS_KWONLY_OPT_METHODDEF \ + {"posonly_keywords_kwonly_opt", _PyCFunction_CAST(posonly_keywords_kwonly_opt), METH_FASTCALL|METH_KEYWORDS, posonly_keywords_kwonly_opt__doc__}, + +static PyObject * +posonly_keywords_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d, PyObject *e); + +static PyObject * +posonly_keywords_kwonly_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), &_Py_ID(e), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "b", "c", "d", "e", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "posonly_keywords_kwonly_opt", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; + PyObject *a; + PyObject *b; + PyObject *c; + PyObject *d = Py_None; + PyObject *e = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + c = args[2]; + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[3]) { + d = args[3]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + e = args[4]; +skip_optional_kwonly: + return_value = posonly_keywords_kwonly_opt_impl(module, a, b, c, d, e); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_keywords_opt_kwonly_opt__doc__, +"posonly_keywords_opt_kwonly_opt($module, a, /, b, c=None, *, d=None,\n" +" e=None)\n" +"--\n" +"\n"); + +#define POSONLY_KEYWORDS_OPT_KWONLY_OPT_METHODDEF \ + {"posonly_keywords_opt_kwonly_opt", _PyCFunction_CAST(posonly_keywords_opt_kwonly_opt), METH_FASTCALL|METH_KEYWORDS, posonly_keywords_opt_kwonly_opt__doc__}, + +static PyObject * +posonly_keywords_opt_kwonly_opt_impl(PyObject *module, PyObject *a, + PyObject *b, PyObject *c, PyObject *d, + PyObject *e); + +static PyObject * +posonly_keywords_opt_kwonly_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(b), &_Py_ID(c), &_Py_ID(d), &_Py_ID(e), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "b", "c", "d", "e", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "posonly_keywords_opt_kwonly_opt", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + PyObject *a; + PyObject *b; + PyObject *c = Py_None; + PyObject *d = Py_None; + PyObject *e = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + if (!noptargs) { + goto skip_optional_pos; + } + if (args[2]) { + c = args[2]; + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[3]) { + d = args[3]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + e = args[4]; +skip_optional_kwonly: + return_value = posonly_keywords_opt_kwonly_opt_impl(module, a, b, c, d, e); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_opt_keywords_opt_kwonly_opt__doc__, +"posonly_opt_keywords_opt_kwonly_opt($module, a, b=None, /, c=None, *,\n" +" d=None)\n" +"--\n" +"\n"); + +#define POSONLY_OPT_KEYWORDS_OPT_KWONLY_OPT_METHODDEF \ + {"posonly_opt_keywords_opt_kwonly_opt", _PyCFunction_CAST(posonly_opt_keywords_opt_kwonly_opt), METH_FASTCALL|METH_KEYWORDS, posonly_opt_keywords_opt_kwonly_opt__doc__}, + +static PyObject * +posonly_opt_keywords_opt_kwonly_opt_impl(PyObject *module, PyObject *a, + PyObject *b, PyObject *c, + PyObject *d); + +static PyObject * +posonly_opt_keywords_opt_kwonly_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(c), &_Py_ID(d), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "", "c", "d", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "posonly_opt_keywords_opt_kwonly_opt", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *a; + PyObject *b = Py_None; + PyObject *c = Py_None; + PyObject *d = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + if (nargs < 2) { + goto skip_optional_posonly; + } + noptargs--; + b = args[1]; +skip_optional_posonly: + if (!noptargs) { + goto skip_optional_pos; + } + if (args[2]) { + c = args[2]; + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + d = args[3]; +skip_optional_kwonly: + return_value = posonly_opt_keywords_opt_kwonly_opt_impl(module, a, b, c, d); + +exit: + return return_value; +} + +PyDoc_STRVAR(keyword_only_parameter__doc__, +"keyword_only_parameter($module, /, *, a)\n" +"--\n" +"\n"); + +#define KEYWORD_ONLY_PARAMETER_METHODDEF \ + {"keyword_only_parameter", _PyCFunction_CAST(keyword_only_parameter), METH_FASTCALL|METH_KEYWORDS, keyword_only_parameter__doc__}, + +static PyObject * +keyword_only_parameter_impl(PyObject *module, PyObject *a); + +static PyObject * +keyword_only_parameter(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"a", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "keyword_only_parameter", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *a; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + return_value = keyword_only_parameter_impl(module, a); + +exit: + return return_value; +} + +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, args[1 + i]); + } + return_value = vararg_and_posonly_impl(module, a, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + +PyDoc_STRVAR(vararg__doc__, +"vararg($module, /, a, *args)\n" +"--\n" +"\n"); + +#define VARARG_METHODDEF \ + {"vararg", _PyCFunction_CAST(vararg), METH_FASTCALL|METH_KEYWORDS, vararg__doc__}, + +static PyObject * +vararg_impl(PyObject *module, PyObject *a, PyObject *args); + +static PyObject * +vararg(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"a", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "vararg", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *a; + PyObject *__clinic_args = NULL; + + args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + __clinic_args = args[1]; + return_value = vararg_impl(module, a, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + +PyDoc_STRVAR(vararg_with_default__doc__, +"vararg_with_default($module, /, a, *args, b=False)\n" +"--\n" +"\n"); + +#define VARARG_WITH_DEFAULT_METHODDEF \ + {"vararg_with_default", _PyCFunction_CAST(vararg_with_default), METH_FASTCALL|METH_KEYWORDS, vararg_with_default__doc__}, + +static PyObject * +vararg_with_default_impl(PyObject *module, PyObject *a, PyObject *args, + int b); + +static PyObject * +vararg_with_default(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(a), &_Py_ID(b), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"a", "b", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "vararg_with_default", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *a; + PyObject *__clinic_args = NULL; + int b = 0; + + args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + __clinic_args = args[1]; + if (!noptargs) { + goto skip_optional_kwonly; + } + b = PyObject_IsTrue(args[2]); + if (b < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = vararg_with_default_impl(module, a, __clinic_args, b); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + +PyDoc_STRVAR(vararg_with_only_defaults__doc__, +"vararg_with_only_defaults($module, /, *args, b=None)\n" +"--\n" +"\n"); + +#define VARARG_WITH_ONLY_DEFAULTS_METHODDEF \ + {"vararg_with_only_defaults", _PyCFunction_CAST(vararg_with_only_defaults), METH_FASTCALL|METH_KEYWORDS, vararg_with_only_defaults__doc__}, + +static PyObject * +vararg_with_only_defaults_impl(PyObject *module, PyObject *args, PyObject *b); + +static PyObject * +vararg_with_only_defaults(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(b), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"b", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "vararg_with_only_defaults", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyObject *__clinic_args = NULL; + PyObject *b = Py_None; + + args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf); + if (!args) { + goto exit; + } + __clinic_args = args[0]; + if (!noptargs) { + goto skip_optional_kwonly; + } + b = args[1]; +skip_optional_kwonly: + return_value = vararg_with_only_defaults_impl(module, __clinic_args, b); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(gh_32092_oob__doc__, "gh_32092_oob($module, /, pos1, pos2, *varargs, kw1=None, kw2=None)\n" "--\n" @@ -177,4 +2706,4 @@ gh_32092_kw_pass(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb Py_XDECREF(__clinic_args); return return_value; } -/*[clinic end generated code: output=f1f47303a227104b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e3773f2b7cac0719 input=a9049054013a1b77]*/ From 7c269d0dc67b020ef5cb18f28fbcf1b1a1cc4702 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Tue, 1 Nov 2022 11:09:51 +0800 Subject: [PATCH 13/29] Rename class TestClinicFunctionality to ClinicFunctionalTest --- Lib/test/test_clinic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index f34d02f13b22d1..f1fb3d2c0d2f93 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -823,7 +823,7 @@ def test_external(self): ac_tester = import_helper.import_module('_testclinic') -class TestClinicFunctionality(unittest.TestCase): +class ClinicFunctionalTest(unittest.TestCase): locals().update((name, getattr(ac_tester, name)) for name in dir(ac_tester) if name.startswith('test_')) From a3a3455a784c82f04089f78823a7e77c2134f825 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Wed, 2 Nov 2022 12:01:39 +0800 Subject: [PATCH 14/29] Fix UB problem --- Modules/_testclinic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index 9e744080b335e7..b65c289f7e5da6 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -23,6 +23,7 @@ pack_arguments(int arg_num, ...) { PyErr_Format(PyExc_AssertionError, "argument %d at %p is freed or corrupted!", i, arg); + va_end(vargs); return NULL; } } else { From 80ba71a4614b7ff4d315f2f2865e36bda7e4cc21 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Fri, 4 Nov 2022 23:59:55 +0800 Subject: [PATCH 15/29] Fix refleaks --- Modules/_testclinic.c | 93 ++++++++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 36 deletions(-) diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index b65c289f7e5da6..5e30db20a22d86 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -11,12 +11,15 @@ #include "clinic/_testclinic.c.h" -PyObject * -pack_arguments(int arg_num, ...) { +static PyObject * +pack_arguments_newref(int argc, ...) { va_list vargs; - va_start(vargs, arg_num); - PyObject *tuple = PyTuple_New(arg_num); - for (int i = 0; i < arg_num; i++) { + va_start(vargs, argc); + PyObject *tuple = PyTuple_New(argc); + if (!tuple) { + return NULL; + } + for (int i = 0; i < argc; i++) { PyObject *arg = va_arg(vargs, PyObject *); if (arg) { if (_PyObject_IsFreed(arg)) { @@ -24,6 +27,7 @@ pack_arguments(int arg_num, ...) { "argument %d at %p is freed or corrupted!", i, arg); va_end(vargs); + Py_DECREF(tuple); return NULL; } } else { @@ -35,6 +39,23 @@ pack_arguments(int arg_num, ...) { return tuple; } +static PyObject * +pack_arguments(int argc, ...) { + va_list vargs; + va_start(vargs, argc); + PyObject *tuple = PyTuple_New(argc); + if (!tuple) { + return NULL; + } + for (int i = 0; i < argc; i++) { + PyObject *arg = va_arg(vargs, PyObject *); + assert(arg && !_PyObject_IsFreed(arg)); + PyTuple_SET_ITEM(tuple, i, arg); + } + va_end(vargs); + return tuple; +} + /*[clinic input] module _testclinic @@ -68,7 +89,7 @@ static PyObject * objects_converter_impl(PyObject *module, PyObject *a, PyObject *b) /*[clinic end generated code: output=3f9c9415ec86c695 input=1533b1bd94187de4]*/ { - return pack_arguments(2, a, b); + return pack_arguments_newref(2, a, b); } @@ -87,7 +108,7 @@ bytes_object_converter_impl(PyObject *module, PyBytesObject *a) if (!PyBytes_Check(a)) { PyErr_SetString(PyExc_AssertionError, "argument a is not a PyBytesObject"); } - return pack_arguments(1, a); + return pack_arguments_newref(1, a); } @@ -106,7 +127,7 @@ byte_array_object_converter_impl(PyObject *module, PyByteArrayObject *a) if (!PyByteArray_Check(a)) { PyErr_SetString(PyExc_AssertionError, "argument a is not a PyByteArrayObject"); } - return pack_arguments(1, a); + return pack_arguments_newref(1, a); } @@ -125,7 +146,7 @@ unicode_converter_impl(PyObject *module, PyObject *a) if (!PyUnicode_Check(a)) { PyErr_SetString(PyExc_AssertionError, "argument a is not a unicode object"); } - return pack_arguments(1, a); + return pack_arguments_newref(1, a); } @@ -155,7 +176,7 @@ bool_converter_impl(PyObject *module, int a, int b, int c) PyObject *obj_a = a ? Py_True : Py_False; PyObject *obj_b = b ? Py_True : Py_False; PyObject *obj_c = c ? Py_True : Py_False; - return pack_arguments(3, obj_a, obj_b, obj_c); + return pack_arguments_newref(3, obj_a, obj_b, obj_c); } @@ -550,22 +571,22 @@ py_buffer_converter_impl(PyObject *module, Py_buffer *a, Py_buffer *b) { PyObject *new_a = PyBytes_FromStringAndSize(NULL, a->len); if (!new_a) { - Py_XDECREF(new_a); return NULL; } - if (PyBuffer_ToContiguous(((PyBytesObject *) new_a)->ob_sval, a, a->len, 'C') < 0) { - Py_XDECREF(new_a); + if (PyBuffer_ToContiguous(((PyBytesObject *)new_a)->ob_sval, a, a->len, 'C') < 0) { + Py_DECREF(new_a); return NULL; } PyBuffer_Release(a); PyObject *new_b = PyBytes_FromStringAndSize(NULL, b->len); if (!new_b) { - Py_XDECREF(new_b); + Py_DECREF(new_a); return NULL; } - if (PyBuffer_ToContiguous(((PyBytesObject *) new_b)->ob_sval, b, b->len, 'C') < 0) { - Py_XDECREF(new_b); + if (PyBuffer_ToContiguous(((PyBytesObject *)new_b)->ob_sval, b, b->len, 'C') < 0) { + Py_DECREF(new_a); + Py_DECREF(new_b); return NULL; } PyBuffer_Release(b); @@ -586,7 +607,7 @@ static PyObject * keywords_impl(PyObject *module, PyObject *a, PyObject *b) /*[clinic end generated code: output=850aaed53e26729e input=f44b89e718c1a93b]*/ { - return pack_arguments(2, a, b); + return pack_arguments_newref(2, a, b); } @@ -603,7 +624,7 @@ static PyObject * keywords_kwonly_impl(PyObject *module, PyObject *a, PyObject *b) /*[clinic end generated code: output=a45c48241da584dc input=1f08e39c3312b015]*/ { - return pack_arguments(2, a, b); + return pack_arguments_newref(2, a, b); } @@ -620,7 +641,7 @@ static PyObject * keywords_opt_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c) /*[clinic end generated code: output=25e4b67d91c76a66 input=b0ba0e4f04904556]*/ { - return pack_arguments(3, a, b, c); + return pack_arguments_newref(3, a, b, c); } @@ -640,7 +661,7 @@ keywords_opt_kwonly_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c, PyObject *d) /*[clinic end generated code: output=6aa5b655a6e9aeb0 input=f79da689d6c51076]*/ { - return pack_arguments(4, a, b, c, d); + return pack_arguments_newref(4, a, b, c, d); } @@ -659,7 +680,7 @@ keywords_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c) /*[clinic end generated code: output=707f78eb0f55c2b1 input=e0fa1a0e46dca791]*/ { - return pack_arguments(3, a, b, c); + return pack_arguments_newref(3, a, b, c); } @@ -676,7 +697,7 @@ static PyObject * posonly_keywords_impl(PyObject *module, PyObject *a, PyObject *b) /*[clinic end generated code: output=6ac88f4a5f0bfc8d input=fde0a2f79fe82b06]*/ { - return pack_arguments(2, a, b); + return pack_arguments_newref(2, a, b); } @@ -694,7 +715,7 @@ static PyObject * posonly_kwonly_impl(PyObject *module, PyObject *a, PyObject *b) /*[clinic end generated code: output=483e6790d3482185 input=78b3712768da9a19]*/ { - return pack_arguments(2, a, b); + return pack_arguments_newref(2, a, b); } @@ -714,7 +735,7 @@ posonly_keywords_kwonly_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c) /*[clinic end generated code: output=2fae573e8cc3fad8 input=a1ad5d2295eb803c]*/ { - return pack_arguments(3, a, b, c); + return pack_arguments_newref(3, a, b, c); } @@ -734,7 +755,7 @@ posonly_keywords_opt_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c, PyObject *d) /*[clinic end generated code: output=f5eb66241bcf68fb input=51c10de2a120e279]*/ { - return pack_arguments(4, a, b, c, d); + return pack_arguments_newref(4, a, b, c, d); } @@ -754,7 +775,7 @@ posonly_opt_keywords_opt_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c, PyObject *d) /*[clinic end generated code: output=d54a30e549296ffd input=f408a1de7dfaf31f]*/ { - return pack_arguments(4, a, b, c, d); + return pack_arguments_newref(4, a, b, c, d); } @@ -775,7 +796,7 @@ posonly_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c, PyObject *d) /*[clinic end generated code: output=a20503fe36b4fd62 input=3494253975272f52]*/ { - return pack_arguments(4, a, b, c, d); + return pack_arguments_newref(4, a, b, c, d); } @@ -796,7 +817,7 @@ posonly_opt_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c, PyObject *d) /*[clinic end generated code: output=64f3204a3a0413b6 input=d17516581e478412]*/ { - return pack_arguments(4, a, b, c, d); + return pack_arguments_newref(4, a, b, c, d); } @@ -818,7 +839,7 @@ posonly_keywords_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c, PyObject *d, PyObject *e) /*[clinic end generated code: output=dbd7e7ddd6257fa0 input=33529f29e97e5adb]*/ { - return pack_arguments(5, a, b, c, d, e); + return pack_arguments_newref(5, a, b, c, d, e); } @@ -841,7 +862,7 @@ posonly_keywords_opt_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *e) /*[clinic end generated code: output=775d12ae44653045 input=4d4cc62f11441301]*/ { - return pack_arguments(5, a, b, c, d, e); + return pack_arguments_newref(5, a, b, c, d, e); } @@ -863,7 +884,7 @@ posonly_opt_keywords_opt_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *d) /*[clinic end generated code: output=40c6dc422591eade input=3964960a68622431]*/ { - return pack_arguments(4, a, b, c, d); + return pack_arguments_newref(4, a, b, c, d); } @@ -879,7 +900,7 @@ static PyObject * keyword_only_parameter_impl(PyObject *module, PyObject *a) /*[clinic end generated code: output=c454b6ce98232787 input=8d2868b8d0b27bdb]*/ { - return pack_arguments(1, a); + return pack_arguments_newref(1, a); } @@ -896,7 +917,7 @@ static PyObject * vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args) /*[clinic end generated code: output=42792f799465a14d input=defe017b19ba52e8]*/ { - return pack_arguments(2, a, Py_NewRef(args)); + return pack_arguments_newref(2, a, args); } @@ -912,7 +933,7 @@ static PyObject * vararg_impl(PyObject *module, PyObject *a, PyObject *args) /*[clinic end generated code: output=91ab7a0efc52dd5e input=02c0f772d05f591e]*/ { - return pack_arguments(2, a, Py_NewRef(args)); + return pack_arguments_newref(2, a, args); } @@ -934,7 +955,7 @@ vararg_with_default_impl(PyObject *module, PyObject *a, PyObject *args, PyErr_SetString(PyExc_AssertionError, "argument b is not a bool value"); } PyObject *obj_b = b ? Py_True : Py_False; - return pack_arguments(3, a, Py_NewRef(args), obj_b); + return pack_arguments_newref(3, a, args, obj_b); } @@ -950,7 +971,7 @@ static PyObject * vararg_with_only_defaults_impl(PyObject *module, PyObject *args, PyObject *b) /*[clinic end generated code: output=c06b1826d91f2f7b input=678c069bc67550e1]*/ { - return pack_arguments(2, Py_NewRef(args), b); + return pack_arguments_newref(2, args, b); } From cf77785b02564c8e7fb97a608650c3b5b982ac14 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Sat, 5 Nov 2022 00:01:51 +0800 Subject: [PATCH 16/29] Clean code --- Lib/test/test_clinic.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index f1fb3d2c0d2f93..0a5b708a2aefc8 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -1251,14 +1251,10 @@ def test_vararg_with_only_defaults(self): self.assertEqual(ac_tester.vararg_with_only_defaults(1, 2, 3, 4, b=5), ((1, 2, 3, 4), 5)) def test_gh_32092_oob(self): - res = ac_tester.gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6) - expect = (1, 2, (3, 4), 5, 6) - self.assertEqual(res, expect) + ac_tester.gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6) def test_gh_32092_kw_pass(self): - res = ac_tester.gh_32092_kw_pass(1, 2, 3) - expect = (1, (2, 3), None) - self.assertEqual(res, expect) + ac_tester.gh_32092_kw_pass(1, 2, 3) if __name__ == "__main__": From 10ce3c7d28412b0fcff516cdb9ed4f8494d55b23 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Tue, 8 Nov 2022 16:28:59 +0800 Subject: [PATCH 17/29] Add PoC of GH-99233 --- Lib/test/test_clinic.py | 6 ++++++ Modules/_testclinic.c | 24 +++++++++++++++++++++ Modules/clinic/_testclinic.c.h | 39 +++++++++++++++++++++++++++++++++- 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 0a5b708a2aefc8..014df211e6e424 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -1256,6 +1256,12 @@ def test_gh_32092_oob(self): def test_gh_32092_kw_pass(self): ac_tester.gh_32092_kw_pass(1, 2, 3) + 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/Modules/_testclinic.c b/Modules/_testclinic.c index 5e30db20a22d86..7c421164701d4b 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -1029,6 +1029,29 @@ gh_32092_kw_pass_impl(PyObject *module, PyObject *pos, PyObject *args, } +/*[clinic input] +gh_99233_refcount + + *args: object + / + +Proof-of-concept of GH-99233 refcount error bug. + +While AC-generated code is packing varargs to a tuple, the arguments' refcounts are not increased. +So all the packed argumentsā€˜ refcounts are decreased 1 improperly when the tuple is released later. + +Call this function with whatever arguments and check if the arguments' refcount is correct. + +[clinic start generated code]*/ + +static PyObject * +gh_99233_refcount_impl(PyObject *module, PyObject *args) +/*[clinic end generated code: output=585855abfbca9a7f input=574e697575fafec5]*/ +{ + Py_RETURN_NONE; +} + + static PyMethodDef tester_methods[] = { TEST_EMPTY_FUNCTION_METHODDEF OBJECTS_CONVERTER_METHODDEF @@ -1077,6 +1100,7 @@ static PyMethodDef tester_methods[] = { VARARG_WITH_ONLY_DEFAULTS_METHODDEF GH_32092_OOB_METHODDEF GH_32092_KW_PASS_METHODDEF + GH_99233_REFCOUNT_METHODDEF {NULL, NULL} }; diff --git a/Modules/clinic/_testclinic.c.h b/Modules/clinic/_testclinic.c.h index b3190fb7d67a54..0a7223d20d530b 100644 --- a/Modules/clinic/_testclinic.c.h +++ b/Modules/clinic/_testclinic.c.h @@ -2706,4 +2706,41 @@ gh_32092_kw_pass(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb Py_XDECREF(__clinic_args); return return_value; } -/*[clinic end generated code: output=e3773f2b7cac0719 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(gh_99233_refcount__doc__, +"gh_99233_refcount($module, /, *args)\n" +"--\n" +"\n" +"Proof-of-concept of GH-99233 refcount error bug.\n" +"\n" +"While AC-generated code is packing varargs to a tuple, the arguments\' refcounts are not increased.\n" +"So all the packed argumentsā€˜ refcounts are decreased 1 improperly when the tuple is released later.\n" +"\n" +"Call this function with whatever arguments and check if the arguments\' refcount is correct."); + +#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, 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=ad9e0740f86bd28b input=a9049054013a1b77]*/ From 2cc6c0a55d6950375a2364f63af4ada878ccc48a Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Tue, 8 Nov 2022 16:50:51 +0800 Subject: [PATCH 18/29] Add PoC of GH-99240 --- Lib/test/test_clinic.py | 7 ++++- Modules/_testclinic.c | 29 ++++++++++++++++++++ Modules/clinic/_testclinic.c.h | 49 +++++++++++++++++++++++++++++++++- 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 014df211e6e424..e830a1e6306706 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -1049,7 +1049,7 @@ def test_str_converter_encoding(self): with self.assertRaises(TypeError): ac_tester.str_converter_encoding(1) self.assertEqual(ac_tester.str_converter_encoding('a', 'b', 'c'), ('a', 'b', 'c')) - with self.assertRaises(ValueError): + with self.assertRaises(TypeError): ac_tester.str_converter_encoding('a', b'b\0b', 'c') self.assertEqual(ac_tester.str_converter_encoding('a', b'b', bytearray([ord('c')])), ('a', 'b', 'c')) self.assertEqual(ac_tester.str_converter_encoding('a', b'b', bytearray([ord('c'), 0, ord('c')])), @@ -1263,5 +1263,10 @@ def test_gh_99233_refcount(self): arg_refcount_after = sys.getrefcount(arg) self.assertEqual(arg_refcount_origin, arg_refcount_after) + def test_gh_99240_double_free(self): + expected_error = r'gh_99240_double_free\(\) argument 2 must be encoded string without null bytes, not str' + with self.assertRaisesRegex(TypeError, expected_error): + ac_tester.gh_99240_double_free('a', '\0b') + if __name__ == "__main__": unittest.main() diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index 7c421164701d4b..4c5ffb317aaf50 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -1052,6 +1052,34 @@ gh_99233_refcount_impl(PyObject *module, PyObject *args) } +/*[clinic input] +gh_99240_double_free + + a: str(encoding="idna") + b: str(encoding="idna") + / + +Proof-of-concept of GH-99240 double-free bug. + +If parsing `a` successes, `a` will be assigned an address points to an allocated memory. +After that, if parsing `b` fails, the memory which `a` points to is freed by function `_PyArg_ParseStack`, +and `_PyArg_ParseStack` returns 0, then control flow goes to label "exit". +At this time, `a` is not NULL, so the memory it points to is freed again, +which cause a double-free problem and a runtime crash. + +Calling this function by gh_99240_double_free('a', '\0b') +to trigger this bug (crash). + +[clinic start generated code]*/ + +static PyObject * +gh_99240_double_free_impl(PyObject *module, char *a, char *b) +/*[clinic end generated code: output=586dc714992fe2ed input=419d3a3790de435e]*/ +{ + Py_RETURN_NONE; +} + + static PyMethodDef tester_methods[] = { TEST_EMPTY_FUNCTION_METHODDEF OBJECTS_CONVERTER_METHODDEF @@ -1101,6 +1129,7 @@ static PyMethodDef tester_methods[] = { GH_32092_OOB_METHODDEF GH_32092_KW_PASS_METHODDEF GH_99233_REFCOUNT_METHODDEF + GH_99240_DOUBLE_FREE_METHODDEF {NULL, NULL} }; diff --git a/Modules/clinic/_testclinic.c.h b/Modules/clinic/_testclinic.c.h index 0a7223d20d530b..e3b5d17a1ce713 100644 --- a/Modules/clinic/_testclinic.c.h +++ b/Modules/clinic/_testclinic.c.h @@ -2743,4 +2743,51 @@ gh_99233_refcount(PyObject *module, PyObject *const *args, Py_ssize_t nargs) Py_XDECREF(__clinic_args); return return_value; } -/*[clinic end generated code: output=ad9e0740f86bd28b input=a9049054013a1b77]*/ + +PyDoc_STRVAR(gh_99240_double_free__doc__, +"gh_99240_double_free($module, a, b, /)\n" +"--\n" +"\n" +"Proof-of-concept of GH-99240 double-free bug.\n" +"\n" +"If parsing `a` successes, `a` will be assigned an address points to an allocated memory.\n" +"After that, if parsing `b` fails, the memory which `a` points to is freed by function `_PyArg_ParseStack`,\n" +"and `_PyArg_ParseStack` returns 0, then control flow goes to label \"exit\".\n" +"At this time, `a` is not NULL, so the memory it points to is freed again,\n" +"which cause a double-free problem and a runtime crash.\n" +"\n" +"Calling this function by gh_99240_double_free(\'a\', \'\\0b\')\n" +"to trigger this bug (crash)."); + +#define GH_99240_DOUBLE_FREE_METHODDEF \ + {"gh_99240_double_free", _PyCFunction_CAST(gh_99240_double_free), METH_FASTCALL, gh_99240_double_free__doc__}, + +static PyObject * +gh_99240_double_free_impl(PyObject *module, char *a, char *b); + +static PyObject * +gh_99240_double_free(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + char *a = NULL; + char *b = NULL; + + if (!_PyArg_ParseStack(args, nargs, "eses:gh_99240_double_free", + "idna", &a, "idna", &b)) { + goto exit; + } + return_value = gh_99240_double_free_impl(module, a, b); + +exit: + /* Cleanup for a */ + if (a) { + PyMem_FREE(a); + } + /* Cleanup for b */ + if (b) { + PyMem_FREE(b); + } + + return return_value; +} +/*[clinic end generated code: output=8f0d1bbae0d775e3 input=a9049054013a1b77]*/ From 6a2d3345735be41e8c34ae028d775c67c68a6cba Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Thu, 10 Nov 2022 10:24:50 +0800 Subject: [PATCH 19/29] Delete test cases which fail this test --- Include/internal/pycore_global_strings.h | 5 - .../internal/pycore_runtime_init_generated.h | 35 -- Lib/test/test_clinic.py | 56 -- Modules/_testclinic.c | 207 ------- Modules/clinic/_testclinic.c.h | 504 +----------------- 5 files changed, 1 insertion(+), 806 deletions(-) diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 651d99b44f4ea0..bb30e0e6dfa7c1 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -432,9 +432,6 @@ struct _Py_global_strings { STRUCT_FOR_ID(keyfile) STRUCT_FOR_ID(keys) STRUCT_FOR_ID(kind) - STRUCT_FOR_ID(kw) - STRUCT_FOR_ID(kw1) - STRUCT_FOR_ID(kw2) STRUCT_FOR_ID(lambda) STRUCT_FOR_ID(last) STRUCT_FOR_ID(last_node) @@ -532,8 +529,6 @@ struct _Py_global_strings { STRUCT_FOR_ID(pid) STRUCT_FOR_ID(policy) STRUCT_FOR_ID(pos) - STRUCT_FOR_ID(pos1) - STRUCT_FOR_ID(pos2) STRUCT_FOR_ID(print_file_and_line) STRUCT_FOR_ID(priority) STRUCT_FOR_ID(progress) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index ed6fe616746937..94d1810f50624b 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -941,9 +941,6 @@ extern "C" { INIT_ID(keyfile), \ INIT_ID(keys), \ INIT_ID(kind), \ - INIT_ID(kw), \ - INIT_ID(kw1), \ - INIT_ID(kw2), \ INIT_ID(lambda), \ INIT_ID(last), \ INIT_ID(last_node), \ @@ -1041,8 +1038,6 @@ extern "C" { INIT_ID(pid), \ INIT_ID(policy), \ INIT_ID(pos), \ - INIT_ID(pos1), \ - INIT_ID(pos2), \ INIT_ID(print_file_and_line), \ INIT_ID(priority), \ INIT_ID(progress), \ @@ -2203,12 +2198,6 @@ _PyUnicode_InitStaticStrings(void) { PyUnicode_InternInPlace(&string); string = &_Py_ID(kind); PyUnicode_InternInPlace(&string); - string = &_Py_ID(kw); - PyUnicode_InternInPlace(&string); - string = &_Py_ID(kw1); - PyUnicode_InternInPlace(&string); - string = &_Py_ID(kw2); - PyUnicode_InternInPlace(&string); string = &_Py_ID(lambda); PyUnicode_InternInPlace(&string); string = &_Py_ID(last); @@ -2403,10 +2392,6 @@ _PyUnicode_InitStaticStrings(void) { PyUnicode_InternInPlace(&string); string = &_Py_ID(pos); PyUnicode_InternInPlace(&string); - string = &_Py_ID(pos1); - PyUnicode_InternInPlace(&string); - string = &_Py_ID(pos2); - PyUnicode_InternInPlace(&string); string = &_Py_ID(print_file_and_line); PyUnicode_InternInPlace(&string); string = &_Py_ID(priority); @@ -6348,18 +6333,6 @@ _PyStaticObjects_CheckRefcnt(void) { _PyObject_Dump((PyObject *)&_Py_ID(kind)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); }; - if (Py_REFCNT((PyObject *)&_Py_ID(kw)) < _PyObject_IMMORTAL_REFCNT) { - _PyObject_Dump((PyObject *)&_Py_ID(kw)); - Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); - }; - if (Py_REFCNT((PyObject *)&_Py_ID(kw1)) < _PyObject_IMMORTAL_REFCNT) { - _PyObject_Dump((PyObject *)&_Py_ID(kw1)); - Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); - }; - if (Py_REFCNT((PyObject *)&_Py_ID(kw2)) < _PyObject_IMMORTAL_REFCNT) { - _PyObject_Dump((PyObject *)&_Py_ID(kw2)); - Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); - }; if (Py_REFCNT((PyObject *)&_Py_ID(lambda)) < _PyObject_IMMORTAL_REFCNT) { _PyObject_Dump((PyObject *)&_Py_ID(lambda)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); @@ -6748,14 +6721,6 @@ _PyStaticObjects_CheckRefcnt(void) { _PyObject_Dump((PyObject *)&_Py_ID(pos)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); }; - if (Py_REFCNT((PyObject *)&_Py_ID(pos1)) < _PyObject_IMMORTAL_REFCNT) { - _PyObject_Dump((PyObject *)&_Py_ID(pos1)); - Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); - }; - if (Py_REFCNT((PyObject *)&_Py_ID(pos2)) < _PyObject_IMMORTAL_REFCNT) { - _PyObject_Dump((PyObject *)&_Py_ID(pos2)); - Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); - }; if (Py_REFCNT((PyObject *)&_Py_ID(print_file_and_line)) < _PyObject_IMMORTAL_REFCNT) { _PyObject_Dump((PyObject *)&_Py_ID(print_file_and_line)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index e830a1e6306706..846f8af52cca41 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -1045,17 +1045,6 @@ def test_str_converter(self): self.assertEqual(ac_tester.str_converter('a', b'b', b'c'), ('a', 'b', 'c')) self.assertEqual(ac_tester.str_converter('a', b'b', 'c\0c'), ('a', 'b', 'c\0c')) - def test_str_converter_encoding(self): - with self.assertRaises(TypeError): - ac_tester.str_converter_encoding(1) - self.assertEqual(ac_tester.str_converter_encoding('a', 'b', 'c'), ('a', 'b', 'c')) - with self.assertRaises(TypeError): - ac_tester.str_converter_encoding('a', b'b\0b', 'c') - self.assertEqual(ac_tester.str_converter_encoding('a', b'b', bytearray([ord('c')])), ('a', 'b', 'c')) - self.assertEqual(ac_tester.str_converter_encoding('a', b'b', bytearray([ord('c'), 0, ord('c')])), - ('a', 'b', 'c\x00c')) - self.assertEqual(ac_tester.str_converter_encoding('a', b'b', b'c\x00c'), ('a', 'b', 'c\x00c')) - def test_py_buffer_converter(self): with self.assertRaises(TypeError): ac_tester.py_buffer_converter('a', 'b') @@ -1222,51 +1211,6 @@ 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_vararg(self): - with self.assertRaises(TypeError): - ac_tester.vararg() - with self.assertRaises(TypeError): - ac_tester.vararg(1, b=2) - self.assertEqual(ac_tester.vararg(1, 2, 3, 4), (1, (2, 3, 4))) - - def test_vararg_with_default(self): - with self.assertRaises(TypeError): - ac_tester.vararg_with_default() - self.assertEqual(ac_tester.vararg_with_default(1, b=False), (1, (), False)) - self.assertEqual(ac_tester.vararg_with_default(1, 2, 3, 4), (1, (2, 3, 4), False)) - self.assertEqual(ac_tester.vararg_with_default(1, 2, 3, 4, b=True), (1, (2, 3, 4), True)) - - def test_vararg_with_only_defaults(self): - self.assertEqual(ac_tester.vararg_with_only_defaults(), ((), None)) - self.assertEqual(ac_tester.vararg_with_only_defaults(b=2), ((), 2)) - self.assertEqual(ac_tester.vararg_with_only_defaults(1, b=2), ((1, ), 2)) - self.assertEqual(ac_tester.vararg_with_only_defaults(1, 2, 3, 4), ((1, 2, 3, 4), None)) - self.assertEqual(ac_tester.vararg_with_only_defaults(1, 2, 3, 4, b=5), ((1, 2, 3, 4), 5)) - - def test_gh_32092_oob(self): - ac_tester.gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6) - - def test_gh_32092_kw_pass(self): - ac_tester.gh_32092_kw_pass(1, 2, 3) - - 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) - - def test_gh_99240_double_free(self): - expected_error = r'gh_99240_double_free\(\) argument 2 must be encoded string without null bytes, not str' - with self.assertRaisesRegex(TypeError, expected_error): - ac_tester.gh_99240_double_free('a', '\0b') if __name__ == "__main__": unittest.main() diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index 4c5ffb317aaf50..573f303c366c2b 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -534,28 +534,6 @@ str_converter_impl(PyObject *module, const char *a, const char *b, } -/*[clinic input] -str_converter_encoding - - a: str(encoding="idna") - b: str(encoding="idna", accept={bytes, bytearray, str}) - c: str(encoding="idna", accept={bytes, bytearray, str}, zeroes=True) - / - -[clinic start generated code]*/ - -static PyObject * -str_converter_encoding_impl(PyObject *module, char *a, char *b, char *c, - Py_ssize_t c_length) -/*[clinic end generated code: output=af68766049248a1c input=0c5cf5159d0e870d]*/ -{ - return pack_arguments(3, - PyUnicode_FromString(a), - PyUnicode_FromString(b), - PyUnicode_FromStringAndSize(c, c_length)); -} - - /*[clinic input] py_buffer_converter @@ -904,182 +882,6 @@ 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] -vararg - - a: object - *args: object - -[clinic start generated code]*/ - -static PyObject * -vararg_impl(PyObject *module, PyObject *a, PyObject *args) -/*[clinic end generated code: output=91ab7a0efc52dd5e input=02c0f772d05f591e]*/ -{ - return pack_arguments_newref(2, a, args); -} - - -/*[clinic input] -vararg_with_default - - a: object - *args: object - b: bool = False - -[clinic start generated code]*/ - -static PyObject * -vararg_with_default_impl(PyObject *module, PyObject *a, PyObject *args, - int b) -/*[clinic end generated code: output=182c01035958ce92 input=68cafa6a79f89e36]*/ -{ - if (!(b == 0 || b == 1)) { - PyErr_SetString(PyExc_AssertionError, "argument b is not a bool value"); - } - PyObject *obj_b = b ? Py_True : Py_False; - return pack_arguments_newref(3, a, args, obj_b); -} - - -/*[clinic input] -vararg_with_only_defaults - - *args: object - b: object = None - -[clinic start generated code]*/ - -static PyObject * -vararg_with_only_defaults_impl(PyObject *module, PyObject *args, PyObject *b) -/*[clinic end generated code: output=c06b1826d91f2f7b input=678c069bc67550e1]*/ -{ - return pack_arguments_newref(2, args, b); -} - - -/*[clinic input] -gh_32092_oob - - pos1: object - pos2: object - *varargs: object - kw1: object = None - kw2: object = None - -Proof-of-concept of GH-32092 OOB bug. - -Array index out-of-bound bug in function -`_PyArg_UnpackKeywordsWithVararg` . - -Calling this function by gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6) -to trigger this bug (crash). - -[clinic start generated code]*/ - -static PyObject * -gh_32092_oob_impl(PyObject *module, PyObject *pos1, PyObject *pos2, - PyObject *varargs, PyObject *kw1, PyObject *kw2) -/*[clinic end generated code: output=ee259c130054653f input=568c6276e3fdef62]*/ -{ - Py_RETURN_NONE; -} - - -/*[clinic input] -gh_32092_kw_pass - - pos: object - *args: object - kw: object = None - -Proof-of-concept of GH-32092 keyword args passing bug. - -The calculation of `noptargs` in AC-generated function -`builtin_kw_pass_poc` is incorrect. - -Calling this function by gh_32092_kw_pass(1, 2, 3) -to trigger this bug (crash). - -[clinic start generated code]*/ - -static PyObject * -gh_32092_kw_pass_impl(PyObject *module, PyObject *pos, PyObject *args, - PyObject *kw) -/*[clinic end generated code: output=4a2bbe4f7c8604e9 input=5bfe6191e1e7a2fb]*/ -{ - Py_RETURN_NONE; -} - - -/*[clinic input] -gh_99233_refcount - - *args: object - / - -Proof-of-concept of GH-99233 refcount error bug. - -While AC-generated code is packing varargs to a tuple, the arguments' refcounts are not increased. -So all the packed argumentsā€˜ refcounts are decreased 1 improperly when the tuple is released later. - -Call this function with whatever arguments and check if the arguments' refcount is correct. - -[clinic start generated code]*/ - -static PyObject * -gh_99233_refcount_impl(PyObject *module, PyObject *args) -/*[clinic end generated code: output=585855abfbca9a7f input=574e697575fafec5]*/ -{ - Py_RETURN_NONE; -} - - -/*[clinic input] -gh_99240_double_free - - a: str(encoding="idna") - b: str(encoding="idna") - / - -Proof-of-concept of GH-99240 double-free bug. - -If parsing `a` successes, `a` will be assigned an address points to an allocated memory. -After that, if parsing `b` fails, the memory which `a` points to is freed by function `_PyArg_ParseStack`, -and `_PyArg_ParseStack` returns 0, then control flow goes to label "exit". -At this time, `a` is not NULL, so the memory it points to is freed again, -which cause a double-free problem and a runtime crash. - -Calling this function by gh_99240_double_free('a', '\0b') -to trigger this bug (crash). - -[clinic start generated code]*/ - -static PyObject * -gh_99240_double_free_impl(PyObject *module, char *a, char *b) -/*[clinic end generated code: output=586dc714992fe2ed input=419d3a3790de435e]*/ -{ - Py_RETURN_NONE; -} - - static PyMethodDef tester_methods[] = { TEST_EMPTY_FUNCTION_METHODDEF OBJECTS_CONVERTER_METHODDEF @@ -1104,7 +906,6 @@ static PyMethodDef tester_methods[] = { DOUBLE_CONVERTER_METHODDEF PY_COMPLEX_CONVERTER_METHODDEF STR_CONVERTER_METHODDEF - STR_CONVERTER_ENCODING_METHODDEF PY_BUFFER_CONVERTER_METHODDEF KEYWORDS_METHODDEF KEYWORDS_KWONLY_METHODDEF @@ -1122,14 +923,6 @@ 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 - VARARG_METHODDEF - VARARG_WITH_DEFAULT_METHODDEF - VARARG_WITH_ONLY_DEFAULTS_METHODDEF - GH_32092_OOB_METHODDEF - GH_32092_KW_PASS_METHODDEF - GH_99233_REFCOUNT_METHODDEF - GH_99240_DOUBLE_FREE_METHODDEF {NULL, NULL} }; diff --git a/Modules/clinic/_testclinic.c.h b/Modules/clinic/_testclinic.c.h index e3b5d17a1ce713..b0ac4c2eef8340 100644 --- a/Modules/clinic/_testclinic.c.h +++ b/Modules/clinic/_testclinic.c.h @@ -1165,50 +1165,6 @@ str_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -PyDoc_STRVAR(str_converter_encoding__doc__, -"str_converter_encoding($module, a, b, c, /)\n" -"--\n" -"\n"); - -#define STR_CONVERTER_ENCODING_METHODDEF \ - {"str_converter_encoding", _PyCFunction_CAST(str_converter_encoding), METH_FASTCALL, str_converter_encoding__doc__}, - -static PyObject * -str_converter_encoding_impl(PyObject *module, char *a, char *b, char *c, - Py_ssize_t c_length); - -static PyObject * -str_converter_encoding(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - char *a = NULL; - char *b = NULL; - char *c = NULL; - Py_ssize_t c_length; - - if (!_PyArg_ParseStack(args, nargs, "esetet#:str_converter_encoding", - "idna", &a, "idna", &b, "idna", &c, &c_length)) { - goto exit; - } - return_value = str_converter_encoding_impl(module, a, b, c, c_length); - -exit: - /* Cleanup for a */ - if (a) { - PyMem_FREE(a); - } - /* Cleanup for b */ - if (b) { - PyMem_FREE(b); - } - /* Cleanup for c */ - if (c) { - PyMem_FREE(c); - } - - return return_value; -} - PyDoc_STRVAR(py_buffer_converter__doc__, "py_buffer_converter($module, a, b, /)\n" "--\n" @@ -2332,462 +2288,4 @@ keyword_only_parameter(PyObject *module, PyObject *const *args, Py_ssize_t nargs exit: return return_value; } - -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, args[1 + i]); - } - return_value = vararg_and_posonly_impl(module, a, __clinic_args); - -exit: - Py_XDECREF(__clinic_args); - return return_value; -} - -PyDoc_STRVAR(vararg__doc__, -"vararg($module, /, a, *args)\n" -"--\n" -"\n"); - -#define VARARG_METHODDEF \ - {"vararg", _PyCFunction_CAST(vararg), METH_FASTCALL|METH_KEYWORDS, vararg__doc__}, - -static PyObject * -vararg_impl(PyObject *module, PyObject *a, PyObject *args); - -static PyObject * -vararg(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(a), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"a", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "vararg", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - PyObject *a; - PyObject *__clinic_args = NULL; - - args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf); - if (!args) { - goto exit; - } - a = args[0]; - __clinic_args = args[1]; - return_value = vararg_impl(module, a, __clinic_args); - -exit: - Py_XDECREF(__clinic_args); - return return_value; -} - -PyDoc_STRVAR(vararg_with_default__doc__, -"vararg_with_default($module, /, a, *args, b=False)\n" -"--\n" -"\n"); - -#define VARARG_WITH_DEFAULT_METHODDEF \ - {"vararg_with_default", _PyCFunction_CAST(vararg_with_default), METH_FASTCALL|METH_KEYWORDS, vararg_with_default__doc__}, - -static PyObject * -vararg_with_default_impl(PyObject *module, PyObject *a, PyObject *args, - int b); - -static PyObject * -vararg_with_default(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(a), &_Py_ID(b), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"a", "b", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "vararg_with_default", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - PyObject *a; - PyObject *__clinic_args = NULL; - int b = 0; - - args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf); - if (!args) { - goto exit; - } - a = args[0]; - __clinic_args = args[1]; - if (!noptargs) { - goto skip_optional_kwonly; - } - b = PyObject_IsTrue(args[2]); - if (b < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = vararg_with_default_impl(module, a, __clinic_args, b); - -exit: - Py_XDECREF(__clinic_args); - return return_value; -} - -PyDoc_STRVAR(vararg_with_only_defaults__doc__, -"vararg_with_only_defaults($module, /, *args, b=None)\n" -"--\n" -"\n"); - -#define VARARG_WITH_ONLY_DEFAULTS_METHODDEF \ - {"vararg_with_only_defaults", _PyCFunction_CAST(vararg_with_only_defaults), METH_FASTCALL|METH_KEYWORDS, vararg_with_only_defaults__doc__}, - -static PyObject * -vararg_with_only_defaults_impl(PyObject *module, PyObject *args, PyObject *b); - -static PyObject * -vararg_with_only_defaults(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(b), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"b", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "vararg_with_only_defaults", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - PyObject *__clinic_args = NULL; - PyObject *b = Py_None; - - args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf); - if (!args) { - goto exit; - } - __clinic_args = args[0]; - if (!noptargs) { - goto skip_optional_kwonly; - } - b = args[1]; -skip_optional_kwonly: - return_value = vararg_with_only_defaults_impl(module, __clinic_args, b); - -exit: - Py_XDECREF(__clinic_args); - return return_value; -} - -PyDoc_STRVAR(gh_32092_oob__doc__, -"gh_32092_oob($module, /, pos1, pos2, *varargs, kw1=None, kw2=None)\n" -"--\n" -"\n" -"Proof-of-concept of GH-32092 OOB bug.\n" -"\n" -"Array index out-of-bound bug in function\n" -"`_PyArg_UnpackKeywordsWithVararg` .\n" -"\n" -"Calling this function by gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6)\n" -"to trigger this bug (crash)."); - -#define GH_32092_OOB_METHODDEF \ - {"gh_32092_oob", _PyCFunction_CAST(gh_32092_oob), METH_FASTCALL|METH_KEYWORDS, gh_32092_oob__doc__}, - -static PyObject * -gh_32092_oob_impl(PyObject *module, PyObject *pos1, PyObject *pos2, - PyObject *varargs, PyObject *kw1, PyObject *kw2); - -static PyObject * -gh_32092_oob(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(pos1), &_Py_ID(pos2), &_Py_ID(kw1), &_Py_ID(kw2), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"pos1", "pos2", "kw1", "kw2", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "gh_32092_oob", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[5]; - Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - PyObject *pos1; - PyObject *pos2; - PyObject *varargs = NULL; - PyObject *kw1 = Py_None; - PyObject *kw2 = Py_None; - - args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, 2, argsbuf); - if (!args) { - goto exit; - } - pos1 = args[0]; - pos2 = args[1]; - varargs = args[2]; - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[3]) { - kw1 = args[3]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - kw2 = args[4]; -skip_optional_kwonly: - return_value = gh_32092_oob_impl(module, pos1, pos2, varargs, kw1, kw2); - -exit: - Py_XDECREF(varargs); - return return_value; -} - -PyDoc_STRVAR(gh_32092_kw_pass__doc__, -"gh_32092_kw_pass($module, /, pos, *args, kw=None)\n" -"--\n" -"\n" -"Proof-of-concept of GH-32092 keyword args passing bug.\n" -"\n" -"The calculation of `noptargs` in AC-generated function\n" -"`builtin_kw_pass_poc` is incorrect.\n" -"\n" -"Calling this function by gh_32092_kw_pass(1, 2, 3)\n" -"to trigger this bug (crash)."); - -#define GH_32092_KW_PASS_METHODDEF \ - {"gh_32092_kw_pass", _PyCFunction_CAST(gh_32092_kw_pass), METH_FASTCALL|METH_KEYWORDS, gh_32092_kw_pass__doc__}, - -static PyObject * -gh_32092_kw_pass_impl(PyObject *module, PyObject *pos, PyObject *args, - PyObject *kw); - -static PyObject * -gh_32092_kw_pass(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(pos), &_Py_ID(kw), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"pos", "kw", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "gh_32092_kw_pass", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - PyObject *pos; - PyObject *__clinic_args = NULL; - PyObject *kw = Py_None; - - args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf); - if (!args) { - goto exit; - } - pos = args[0]; - __clinic_args = args[1]; - if (!noptargs) { - goto skip_optional_kwonly; - } - kw = args[2]; -skip_optional_kwonly: - return_value = gh_32092_kw_pass_impl(module, pos, __clinic_args, kw); - -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.\n" -"\n" -"While AC-generated code is packing varargs to a tuple, the arguments\' refcounts are not increased.\n" -"So all the packed argumentsā€˜ refcounts are decreased 1 improperly when the tuple is released later.\n" -"\n" -"Call this function with whatever arguments and check if the arguments\' refcount is correct."); - -#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, args[0 + i]); - } - return_value = gh_99233_refcount_impl(module, __clinic_args); - -exit: - Py_XDECREF(__clinic_args); - return return_value; -} - -PyDoc_STRVAR(gh_99240_double_free__doc__, -"gh_99240_double_free($module, a, b, /)\n" -"--\n" -"\n" -"Proof-of-concept of GH-99240 double-free bug.\n" -"\n" -"If parsing `a` successes, `a` will be assigned an address points to an allocated memory.\n" -"After that, if parsing `b` fails, the memory which `a` points to is freed by function `_PyArg_ParseStack`,\n" -"and `_PyArg_ParseStack` returns 0, then control flow goes to label \"exit\".\n" -"At this time, `a` is not NULL, so the memory it points to is freed again,\n" -"which cause a double-free problem and a runtime crash.\n" -"\n" -"Calling this function by gh_99240_double_free(\'a\', \'\\0b\')\n" -"to trigger this bug (crash)."); - -#define GH_99240_DOUBLE_FREE_METHODDEF \ - {"gh_99240_double_free", _PyCFunction_CAST(gh_99240_double_free), METH_FASTCALL, gh_99240_double_free__doc__}, - -static PyObject * -gh_99240_double_free_impl(PyObject *module, char *a, char *b); - -static PyObject * -gh_99240_double_free(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - char *a = NULL; - char *b = NULL; - - if (!_PyArg_ParseStack(args, nargs, "eses:gh_99240_double_free", - "idna", &a, "idna", &b)) { - goto exit; - } - return_value = gh_99240_double_free_impl(module, a, b); - -exit: - /* Cleanup for a */ - if (a) { - PyMem_FREE(a); - } - /* Cleanup for b */ - if (b) { - PyMem_FREE(b); - } - - return return_value; -} -/*[clinic end generated code: output=8f0d1bbae0d775e3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a9212f8e6ba18bba input=a9049054013a1b77]*/ From b27b43d218eaacc8aa8c2a05c9ce47b9f2b83859 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Thu, 10 Nov 2022 10:41:46 +0800 Subject: [PATCH 20/29] Rerun `make regen-all` --- Include/internal/pycore_global_objects_fini_generated.h | 3 +++ Include/internal/pycore_unicodeobject_generated.h | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index f734e4b48a34ae..e35bc9dbc3ddca 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -798,6 +798,7 @@ _PyStaticObjects_CheckRefcnt(void) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(byteorder)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(bytes)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(bytes_per_sep)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(c)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(c_call)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(c_exception)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(c_return)); @@ -847,6 +848,7 @@ _PyStaticObjects_CheckRefcnt(void) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(coro)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(count)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cwd)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(d)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(data)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(database)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(decode)); @@ -874,6 +876,7 @@ _PyStaticObjects_CheckRefcnt(void) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(dst)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(dst_dir_fd)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(duration)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(e)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(effective_ids)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(element_factory)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(encode)); diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index 026945f1e342a9..5fad2005361c38 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -478,6 +478,8 @@ _PyUnicode_InitStaticStrings(void) { PyUnicode_InternInPlace(&string); string = &_Py_ID(bytes_per_sep); PyUnicode_InternInPlace(&string); + string = &_Py_ID(c); + PyUnicode_InternInPlace(&string); string = &_Py_ID(c_call); PyUnicode_InternInPlace(&string); string = &_Py_ID(c_exception); @@ -576,6 +578,8 @@ _PyUnicode_InitStaticStrings(void) { PyUnicode_InternInPlace(&string); string = &_Py_ID(cwd); PyUnicode_InternInPlace(&string); + string = &_Py_ID(d); + PyUnicode_InternInPlace(&string); string = &_Py_ID(data); PyUnicode_InternInPlace(&string); string = &_Py_ID(database); @@ -630,6 +634,8 @@ _PyUnicode_InitStaticStrings(void) { PyUnicode_InternInPlace(&string); string = &_Py_ID(duration); PyUnicode_InternInPlace(&string); + string = &_Py_ID(e); + PyUnicode_InternInPlace(&string); string = &_Py_ID(effective_ids); PyUnicode_InternInPlace(&string); string = &_Py_ID(element_factory); From 1cae160474a9550c99fe2e306b4c9f91a86549c1 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Sun, 13 Nov 2022 22:22:15 +0800 Subject: [PATCH 21/29] Fix leaking --- Modules/_testclinic.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index 573f303c366c2b..492719d4d6007b 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -11,14 +11,18 @@ #include "clinic/_testclinic.c.h" +/* Pack arguments to a tuple, implicitly increase all the arguments' refcount. + * NULL arguments will be replaced to Py_None. */ static PyObject * pack_arguments_newref(int argc, ...) { - va_list vargs; - va_start(vargs, argc); + assert(!PyErr_Occurred()); PyObject *tuple = PyTuple_New(argc); if (!tuple) { return NULL; } + + va_list vargs; + va_start(vargs, argc); for (int i = 0; i < argc; i++) { PyObject *arg = va_arg(vargs, PyObject *); if (arg) { @@ -39,17 +43,26 @@ pack_arguments_newref(int argc, ...) { return tuple; } +/* Pack arguments to a tuple, all the arguments' refcounts should be increased before passing in. + * Do not accept NULL arguments unless error occurs. */ static PyObject * pack_arguments(int argc, ...) { - va_list vargs; - va_start(vargs, argc); + assert(!PyErr_Occurred()); PyObject *tuple = PyTuple_New(argc); if (!tuple) { return NULL; } + + va_list vargs; + va_start(vargs, argc); for (int i = 0; i < argc; i++) { PyObject *arg = va_arg(vargs, PyObject *); - assert(arg && !_PyObject_IsFreed(arg)); + assert(arg || PyErr_Occurred()); + if (!arg) { + va_end(vargs); + Py_DECREF(tuple); + return NULL; + } PyTuple_SET_ITEM(tuple, i, arg); } va_end(vargs); From fb6d3be51c3abd92967557db63f0d166148ba94e Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Mon, 14 Nov 2022 01:49:34 +0800 Subject: [PATCH 22/29] Fix code style --- Lib/test/test_clinic.py | 44 ++++++++++++++++++------------------ Modules/_testclinic.c | 49 +++++++++++++++++++++++------------------ 2 files changed, 50 insertions(+), 43 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 846f8af52cca41..7c1bd1c10d2ab6 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -837,25 +837,25 @@ def test_objects_converter(self): def test_bytes_object_converter(self): with self.assertRaises(TypeError): ac_tester.bytes_object_converter(1) - self.assertEqual(ac_tester.bytes_object_converter(b'BytesObject'), (b'BytesObject', )) + self.assertEqual(ac_tester.bytes_object_converter(b'BytesObject'), (b'BytesObject',)) def test_byte_array_object_converter(self): with self.assertRaises(TypeError): ac_tester.byte_array_object_converter(1) byte_arr = bytearray(b'ByteArrayObject') - self.assertEqual(ac_tester.byte_array_object_converter(byte_arr), (byte_arr, )) + self.assertEqual(ac_tester.byte_array_object_converter(byte_arr), (byte_arr,)) def test_unicode_converter(self): with self.assertRaises(TypeError): ac_tester.unicode_converter(1) - self.assertEqual(ac_tester.unicode_converter('unicode'), ('unicode', )) + self.assertEqual(ac_tester.unicode_converter('unicode'), ('unicode',)) def test_bool_converter(self): with self.assertRaises(TypeError): ac_tester.bool_converter(False, False, 'not a int') self.assertEqual(ac_tester.bool_converter(), (True, True, True)) self.assertEqual(ac_tester.bool_converter('', [], 5), (False, False, True)) - self.assertEqual(ac_tester.bool_converter(('not empty', ), {1: 2}, 0), (True, True, False)) + self.assertEqual(ac_tester.bool_converter(('not empty',), {1: 2}, 0), (True, True, False)) def test_char_converter(self): with self.assertRaises(TypeError): @@ -863,10 +863,10 @@ def test_char_converter(self): with self.assertRaises(TypeError): ac_tester.char_converter(b'ab') chars = [b'A', b'\a', b'\b', b'\t', b'\n', b'\v', b'\f', b'\r', b'"', b"'", b'?', b'\\', b'\000', b'\377'] - expected = tuple([ord(c) for c in chars]) + expected = tuple(ord(c) for c in chars) self.assertEqual(ac_tester.char_converter(), expected) chars = [b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'0', b'a', b'b', b'c', b'd'] - expected = tuple([ord(c) for c in chars]) + expected = tuple(ord(c) for c in chars) self.assertEqual(ac_tester.char_converter(*chars), expected) def test_unsigned_char_converter(self): @@ -891,8 +891,8 @@ def test_short_converter(self): ac_tester.short_converter(SHRT_MAX + 1) with self.assertRaises(TypeError): ac_tester.short_converter([]) - self.assertEqual(ac_tester.short_converter(-1234), (-1234, )) - self.assertEqual(ac_tester.short_converter(4321), (4321, )) + self.assertEqual(ac_tester.short_converter(-1234), (-1234,)) + self.assertEqual(ac_tester.short_converter(4321), (4321,)) def test_unsigned_short_converter(self): from _testcapi import USHRT_MAX @@ -943,8 +943,8 @@ def test_long_converter(self): ac_tester.long_converter(LONG_MAX + 1) with self.assertRaises(TypeError): ac_tester.long_converter([]) - self.assertEqual(ac_tester.long_converter(), (12, )) - self.assertEqual(ac_tester.long_converter(-1234), (-1234, )) + self.assertEqual(ac_tester.long_converter(), (12,)) + self.assertEqual(ac_tester.long_converter(-1234), (-1234,)) def test_unsigned_long_converter(self): from _testcapi import ULONG_MAX @@ -968,8 +968,8 @@ def test_long_long_converter(self): ac_tester.long_long_converter(LLONG_MAX + 1) with self.assertRaises(TypeError): ac_tester.long_long_converter([]) - self.assertEqual(ac_tester.long_long_converter(), (12, )) - self.assertEqual(ac_tester.long_long_converter(-1234), (-1234, )) + self.assertEqual(ac_tester.long_long_converter(), (12,)) + self.assertEqual(ac_tester.long_long_converter(-1234), (-1234,)) def test_unsigned_long_long_converter(self): from _testcapi import ULLONG_MAX @@ -1012,27 +1012,27 @@ def test_size_t_converter(self): ac_tester.size_t_converter(-1) with self.assertRaises(TypeError): ac_tester.size_t_converter([]) - self.assertEqual(ac_tester.size_t_converter(), (12, )) + self.assertEqual(ac_tester.size_t_converter(), (12,)) def test_float_converter(self): with self.assertRaises(TypeError): ac_tester.float_converter([]) - self.assertEqual(ac_tester.float_converter(), (12.5, )) - self.assertEqual(ac_tester.float_converter(-0.5), (-0.5, )) + self.assertEqual(ac_tester.float_converter(), (12.5,)) + self.assertEqual(ac_tester.float_converter(-0.5), (-0.5,)) def test_double_converter(self): with self.assertRaises(TypeError): ac_tester.double_converter([]) - self.assertEqual(ac_tester.double_converter(), (12.5, )) - self.assertEqual(ac_tester.double_converter(-0.5), (-0.5, )) + self.assertEqual(ac_tester.double_converter(), (12.5,)) + self.assertEqual(ac_tester.double_converter(-0.5), (-0.5,)) def test_py_complex_converter(self): with self.assertRaises(TypeError): ac_tester.py_complex_converter([]) - self.assertEqual(ac_tester.py_complex_converter(complex(1, 2)), (complex(1, 2), )) - self.assertEqual(ac_tester.py_complex_converter(complex('-1-2j')), (complex('-1-2j'), )) - self.assertEqual(ac_tester.py_complex_converter(-0.5), (-0.5, )) - self.assertEqual(ac_tester.py_complex_converter(10), (10, )) + self.assertEqual(ac_tester.py_complex_converter(complex(1, 2)), (complex(1, 2),)) + self.assertEqual(ac_tester.py_complex_converter(complex('-1-2j')), (complex('-1-2j'),)) + self.assertEqual(ac_tester.py_complex_converter(-0.5), (-0.5,)) + self.assertEqual(ac_tester.py_complex_converter(10), (10,)) def test_str_converter(self): with self.assertRaises(TypeError): @@ -1209,7 +1209,7 @@ def test_keyword_only_parameter(self): ac_tester.keyword_only_parameter() with self.assertRaises(TypeError): 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,)) if __name__ == "__main__": diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index 492719d4d6007b..0dc93606b9b20f 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -11,6 +11,7 @@ #include "clinic/_testclinic.c.h" + /* Pack arguments to a tuple, implicitly increase all the arguments' refcount. * NULL arguments will be replaced to Py_None. */ static PyObject * @@ -34,7 +35,8 @@ pack_arguments_newref(int argc, ...) { Py_DECREF(tuple); return NULL; } - } else { + } + else { arg = Py_None; } PyTuple_SET_ITEM(tuple, i, Py_NewRef(arg)); @@ -119,7 +121,8 @@ bytes_object_converter_impl(PyObject *module, PyBytesObject *a) /*[clinic end generated code: output=7732da869d74b784 input=94211751e7996236]*/ { if (!PyBytes_Check(a)) { - PyErr_SetString(PyExc_AssertionError, "argument a is not a PyBytesObject"); + PyErr_SetString(PyExc_AssertionError, + "argument a is not a PyBytesObject"); } return pack_arguments_newref(1, a); } @@ -138,7 +141,8 @@ byte_array_object_converter_impl(PyObject *module, PyByteArrayObject *a) /*[clinic end generated code: output=51f15c76f302b1f7 input=b04d253db51c6f56]*/ { if (!PyByteArray_Check(a)) { - PyErr_SetString(PyExc_AssertionError, "argument a is not a PyByteArrayObject"); + PyErr_SetString(PyExc_AssertionError, + "argument a is not a PyByteArrayObject"); } return pack_arguments_newref(1, a); } @@ -157,7 +161,8 @@ unicode_converter_impl(PyObject *module, PyObject *a) /*[clinic end generated code: output=1b4a4adbb6ac6e34 input=de7b5adbf07435ba]*/ { if (!PyUnicode_Check(a)) { - PyErr_SetString(PyExc_AssertionError, "argument a is not a unicode object"); + PyErr_SetString(PyExc_AssertionError, + "argument a is not a unicode object"); } return pack_arguments_newref(1, a); } @@ -221,20 +226,20 @@ char_converter_impl(PyObject *module, char a, char b, char c, char d, char e, /*[clinic end generated code: output=f929dbd2e55a9871 input=b601bc5bc7fe85e3]*/ { return pack_arguments(14, - PyLong_FromUnsignedLong((unsigned char) a), - PyLong_FromUnsignedLong((unsigned char) b), - PyLong_FromUnsignedLong((unsigned char) c), - PyLong_FromUnsignedLong((unsigned char) d), - PyLong_FromUnsignedLong((unsigned char) e), - PyLong_FromUnsignedLong((unsigned char) f), - PyLong_FromUnsignedLong((unsigned char) g), - PyLong_FromUnsignedLong((unsigned char) h), - PyLong_FromUnsignedLong((unsigned char) i), - PyLong_FromUnsignedLong((unsigned char) j), - PyLong_FromUnsignedLong((unsigned char) k), - PyLong_FromUnsignedLong((unsigned char) l), - PyLong_FromUnsignedLong((unsigned char) m), - PyLong_FromUnsignedLong((unsigned char) n)); + PyLong_FromUnsignedLong((unsigned char)a), + PyLong_FromUnsignedLong((unsigned char)b), + PyLong_FromUnsignedLong((unsigned char)c), + PyLong_FromUnsignedLong((unsigned char)d), + PyLong_FromUnsignedLong((unsigned char)e), + PyLong_FromUnsignedLong((unsigned char)f), + PyLong_FromUnsignedLong((unsigned char)g), + PyLong_FromUnsignedLong((unsigned char)h), + PyLong_FromUnsignedLong((unsigned char)i), + PyLong_FromUnsignedLong((unsigned char)j), + PyLong_FromUnsignedLong((unsigned char)k), + PyLong_FromUnsignedLong((unsigned char)l), + PyLong_FromUnsignedLong((unsigned char)m), + PyLong_FromUnsignedLong((unsigned char)n)); } @@ -489,7 +494,7 @@ static PyObject * float_converter_impl(PyObject *module, float a) /*[clinic end generated code: output=1c98f64f2cf1d55c input=a625b59ad68047d8]*/ { - return pack_arguments(1, PyFloat_FromDouble((double) a)); + return pack_arguments(1, PyFloat_FromDouble((double)a)); } @@ -564,7 +569,8 @@ py_buffer_converter_impl(PyObject *module, Py_buffer *a, Py_buffer *b) if (!new_a) { return NULL; } - if (PyBuffer_ToContiguous(((PyBytesObject *)new_a)->ob_sval, a, a->len, 'C') < 0) { + if (PyBuffer_ToContiguous(((PyBytesObject *)new_a)->ob_sval, a, a->len, + 'C') < 0) { Py_DECREF(new_a); return NULL; } @@ -575,7 +581,8 @@ py_buffer_converter_impl(PyObject *module, Py_buffer *a, Py_buffer *b) Py_DECREF(new_a); return NULL; } - if (PyBuffer_ToContiguous(((PyBytesObject *)new_b)->ob_sval, b, b->len, 'C') < 0) { + if (PyBuffer_ToContiguous(((PyBytesObject *)new_b)->ob_sval, b, b->len, + 'C') < 0) { Py_DECREF(new_a); Py_DECREF(new_b); return NULL; From e82c88a7d053d9640a61042a6185415ff23a8f18 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Mon, 14 Nov 2022 02:24:45 +0800 Subject: [PATCH 23/29] Rerun `make regen-all` --- Include/internal/pycore_runtime_init_generated.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index e7fba8db16fd7b..b089e9ed7843a1 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -793,6 +793,7 @@ extern "C" { INIT_ID(byteorder), \ INIT_ID(bytes), \ INIT_ID(bytes_per_sep), \ + INIT_ID(c), \ INIT_ID(c_call), \ INIT_ID(c_exception), \ INIT_ID(c_return), \ @@ -842,6 +843,7 @@ extern "C" { INIT_ID(coro), \ INIT_ID(count), \ INIT_ID(cwd), \ + INIT_ID(d), \ INIT_ID(data), \ INIT_ID(database), \ INIT_ID(decode), \ @@ -869,6 +871,7 @@ extern "C" { INIT_ID(dst), \ INIT_ID(dst_dir_fd), \ INIT_ID(duration), \ + INIT_ID(e), \ INIT_ID(effective_ids), \ INIT_ID(element_factory), \ INIT_ID(encode), \ From 598568c65e0d6a81c2121b31bd2887cddb2a2e8f Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Mon, 14 Nov 2022 15:49:57 +0800 Subject: [PATCH 24/29] Fix object leaking and code style --- Modules/_testclinic.c | 191 +++++++++++++++++++++--------------------- 1 file changed, 95 insertions(+), 96 deletions(-) diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index 0dc93606b9b20f..af4f7075d571da 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -15,7 +15,8 @@ /* Pack arguments to a tuple, implicitly increase all the arguments' refcount. * NULL arguments will be replaced to Py_None. */ static PyObject * -pack_arguments_newref(int argc, ...) { +pack_arguments_newref(int argc, ...) +{ assert(!PyErr_Occurred()); PyObject *tuple = PyTuple_New(argc); if (!tuple) { @@ -47,29 +48,31 @@ pack_arguments_newref(int argc, ...) { /* Pack arguments to a tuple, all the arguments' refcounts should be increased before passing in. * Do not accept NULL arguments unless error occurs. */ -static PyObject * -pack_arguments(int argc, ...) { - assert(!PyErr_Occurred()); - PyObject *tuple = PyTuple_New(argc); - if (!tuple) { - return NULL; - } - - va_list vargs; - va_start(vargs, argc); - for (int i = 0; i < argc; i++) { - PyObject *arg = va_arg(vargs, PyObject *); - assert(arg || PyErr_Occurred()); - if (!arg) { - va_end(vargs); - Py_DECREF(tuple); - return NULL; - } - PyTuple_SET_ITEM(tuple, i, arg); - } - va_end(vargs); - return tuple; -} +#define PACK_ARGUMENTS(argc, ...) do { \ + assert(!PyErr_Occurred()); \ + PyObject *out[argc] = {NULL,}; \ + for (int _i = 0; _i < argc; _i++) { \ + out[_i] = ((PyObject *[]){__VA_ARGS__})[_i]; \ + assert(out[_i] || PyErr_Occurred()); \ + if (!out[_i]) { \ + for (int _j = _i - 1; _j >= 0; _j--) { \ + Py_DECREF(out[_j]); \ + } \ + return NULL; \ + } \ + } \ + PyObject *tuple = PyTuple_New(argc); \ + if (!tuple) { \ + for (int _i = 0; _i < argc; _i++) { \ + Py_DECREF(out[_i]); \ + } \ + return NULL; \ + } \ + for (int _i = 0; _i < argc; _i++) { \ + PyTuple_SET_ITEM(tuple, _i, out[_i]); \ + } \ + return tuple; \ + } while (0) /*[clinic input] @@ -123,6 +126,7 @@ bytes_object_converter_impl(PyObject *module, PyBytesObject *a) if (!PyBytes_Check(a)) { PyErr_SetString(PyExc_AssertionError, "argument a is not a PyBytesObject"); + return NULL; } return pack_arguments_newref(1, a); } @@ -143,6 +147,7 @@ byte_array_object_converter_impl(PyObject *module, PyByteArrayObject *a) if (!PyByteArray_Check(a)) { PyErr_SetString(PyExc_AssertionError, "argument a is not a PyByteArrayObject"); + return NULL; } return pack_arguments_newref(1, a); } @@ -163,6 +168,7 @@ unicode_converter_impl(PyObject *module, PyObject *a) if (!PyUnicode_Check(a)) { PyErr_SetString(PyExc_AssertionError, "argument a is not a unicode object"); + return NULL; } return pack_arguments_newref(1, a); } @@ -182,15 +188,6 @@ static PyObject * bool_converter_impl(PyObject *module, int a, int b, int c) /*[clinic end generated code: output=17005b0c29afd590 input=7f6537705b2f32f4]*/ { - if (!(a == 0 || a == 1)) { - PyErr_SetString(PyExc_AssertionError, "argument a is not a bool value"); - } - if (!(a == 0 || a == 1)) { - PyErr_SetString(PyExc_AssertionError, "argument b is not a bool value"); - } - if (!(a == 0 || a == 1)) { - PyErr_SetString(PyExc_AssertionError, "argument c is not a bool value"); - } PyObject *obj_a = a ? Py_True : Py_False; PyObject *obj_b = b ? Py_True : Py_False; PyObject *obj_c = c ? Py_True : Py_False; @@ -225,21 +222,21 @@ char_converter_impl(PyObject *module, char a, char b, char c, char d, char e, char m, char n) /*[clinic end generated code: output=f929dbd2e55a9871 input=b601bc5bc7fe85e3]*/ { - return pack_arguments(14, - PyLong_FromUnsignedLong((unsigned char)a), - PyLong_FromUnsignedLong((unsigned char)b), - PyLong_FromUnsignedLong((unsigned char)c), - PyLong_FromUnsignedLong((unsigned char)d), - PyLong_FromUnsignedLong((unsigned char)e), - PyLong_FromUnsignedLong((unsigned char)f), - PyLong_FromUnsignedLong((unsigned char)g), - PyLong_FromUnsignedLong((unsigned char)h), - PyLong_FromUnsignedLong((unsigned char)i), - PyLong_FromUnsignedLong((unsigned char)j), - PyLong_FromUnsignedLong((unsigned char)k), - PyLong_FromUnsignedLong((unsigned char)l), - PyLong_FromUnsignedLong((unsigned char)m), - PyLong_FromUnsignedLong((unsigned char)n)); + PACK_ARGUMENTS(14, + PyLong_FromUnsignedLong((unsigned char)a), + PyLong_FromUnsignedLong((unsigned char)b), + PyLong_FromUnsignedLong((unsigned char)c), + PyLong_FromUnsignedLong((unsigned char)d), + PyLong_FromUnsignedLong((unsigned char)e), + PyLong_FromUnsignedLong((unsigned char)f), + PyLong_FromUnsignedLong((unsigned char)g), + PyLong_FromUnsignedLong((unsigned char)h), + PyLong_FromUnsignedLong((unsigned char)i), + PyLong_FromUnsignedLong((unsigned char)j), + PyLong_FromUnsignedLong((unsigned char)k), + PyLong_FromUnsignedLong((unsigned char)l), + PyLong_FromUnsignedLong((unsigned char)m), + PyLong_FromUnsignedLong((unsigned char)n)); } @@ -258,10 +255,10 @@ unsigned_char_converter_impl(PyObject *module, unsigned char a, unsigned char b, unsigned char c) /*[clinic end generated code: output=490af3b39ce0b199 input=e859502fbe0b3185]*/ { - return pack_arguments(3, - PyLong_FromUnsignedLong(a), - PyLong_FromUnsignedLong(b), - PyLong_FromUnsignedLong(c)); + PACK_ARGUMENTS(3, + PyLong_FromUnsignedLong(a), + PyLong_FromUnsignedLong(b), + PyLong_FromUnsignedLong(c)); } @@ -277,7 +274,7 @@ static PyObject * short_converter_impl(PyObject *module, short a) /*[clinic end generated code: output=1ebb7ddb64248988 input=b4e2309a66f650ae]*/ { - return pack_arguments(1, PyLong_FromLong(a)); + PACK_ARGUMENTS(1, PyLong_FromLong(a)); } @@ -296,10 +293,10 @@ unsigned_short_converter_impl(PyObject *module, unsigned short a, unsigned short b, unsigned short c) /*[clinic end generated code: output=5f92cc72fc8707a7 input=9d15cd11e741d0c6]*/ { - return pack_arguments(3, - PyLong_FromUnsignedLong(a), - PyLong_FromUnsignedLong(b), - PyLong_FromUnsignedLong(c)); + PACK_ARGUMENTS(3, + PyLong_FromUnsignedLong(a), + PyLong_FromUnsignedLong(b), + PyLong_FromUnsignedLong(c)); } @@ -317,10 +314,10 @@ static PyObject * int_converter_impl(PyObject *module, int a, int b, int c) /*[clinic end generated code: output=8e56b59be7d0c306 input=a1dbc6344853db7a]*/ { - return pack_arguments(3, - PyLong_FromLong(a), - PyLong_FromLong(b), - PyLong_FromLong(c)); + PACK_ARGUMENTS(3, + PyLong_FromLong(a), + PyLong_FromLong(b), + PyLong_FromLong(c)); } @@ -339,10 +336,10 @@ unsigned_int_converter_impl(PyObject *module, unsigned int a, unsigned int b, unsigned int c) /*[clinic end generated code: output=399a57a05c494cc7 input=8427ed9a3f96272d]*/ { - return pack_arguments(3, - PyLong_FromUnsignedLong(a), - PyLong_FromUnsignedLong(b), - PyLong_FromUnsignedLong(c)); + PACK_ARGUMENTS(3, + PyLong_FromUnsignedLong(a), + PyLong_FromUnsignedLong(b), + PyLong_FromUnsignedLong(c)); } @@ -358,7 +355,7 @@ static PyObject * long_converter_impl(PyObject *module, long a) /*[clinic end generated code: output=9663d936a652707a input=84ad0ef28f24bd85]*/ { - return pack_arguments(1, PyLong_FromLong(a)); + PACK_ARGUMENTS(1, PyLong_FromLong(a)); } @@ -377,10 +374,10 @@ unsigned_long_converter_impl(PyObject *module, unsigned long a, unsigned long b, unsigned long c) /*[clinic end generated code: output=120b82ea9ebd93a8 input=440dd6f1817f5d91]*/ { - return pack_arguments(3, - PyLong_FromUnsignedLong(a), - PyLong_FromUnsignedLong(b), - PyLong_FromUnsignedLong(c)); + PACK_ARGUMENTS(3, + PyLong_FromUnsignedLong(a), + PyLong_FromUnsignedLong(b), + PyLong_FromUnsignedLong(c)); } @@ -396,7 +393,7 @@ static PyObject * long_long_converter_impl(PyObject *module, long long a) /*[clinic end generated code: output=5fb5f2220770c3e1 input=730fcb3eecf4d993]*/ { - return pack_arguments(1, PyLong_FromLongLong(a)); + PACK_ARGUMENTS(1, PyLong_FromLongLong(a)); } @@ -415,10 +412,10 @@ unsigned_long_long_converter_impl(PyObject *module, unsigned long long a, unsigned long long b, unsigned long long c) /*[clinic end generated code: output=65b7273e63501762 input=300737b0bdb230e9]*/ { - return pack_arguments(3, - PyLong_FromUnsignedLongLong(a), - PyLong_FromUnsignedLongLong(b), - PyLong_FromUnsignedLongLong(c)); + PACK_ARGUMENTS(3, + PyLong_FromUnsignedLongLong(a), + PyLong_FromUnsignedLongLong(b), + PyLong_FromUnsignedLongLong(c)); } @@ -437,10 +434,10 @@ py_ssize_t_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b, Py_ssize_t c) /*[clinic end generated code: output=ce252143e0ed0372 input=76d0f342e9317a1f]*/ { - return pack_arguments(3, - PyLong_FromSsize_t(a), - PyLong_FromSsize_t(b), - PyLong_FromSsize_t(c)); + PACK_ARGUMENTS(3, + PyLong_FromSsize_t(a), + PyLong_FromSsize_t(b), + PyLong_FromSsize_t(c)); } @@ -459,10 +456,10 @@ slice_index_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b, Py_ssize_t c) /*[clinic end generated code: output=923c6cac77666a6b input=64f99f3f83265e47]*/ { - return pack_arguments(3, - PyLong_FromSsize_t(a), - PyLong_FromSsize_t(b), - PyLong_FromSsize_t(c)); + PACK_ARGUMENTS(3, + PyLong_FromSsize_t(a), + PyLong_FromSsize_t(b), + PyLong_FromSsize_t(c)); } @@ -478,7 +475,7 @@ static PyObject * size_t_converter_impl(PyObject *module, size_t a) /*[clinic end generated code: output=412b5b7334ab444d input=83ae7d9171fbf208]*/ { - return pack_arguments(1, PyLong_FromSize_t(a)); + PACK_ARGUMENTS(1, PyLong_FromSize_t(a)); } @@ -494,7 +491,7 @@ static PyObject * float_converter_impl(PyObject *module, float a) /*[clinic end generated code: output=1c98f64f2cf1d55c input=a625b59ad68047d8]*/ { - return pack_arguments(1, PyFloat_FromDouble((double)a)); + PACK_ARGUMENTS(1, PyFloat_FromDouble((double)a)); } @@ -510,7 +507,7 @@ static PyObject * double_converter_impl(PyObject *module, double a) /*[clinic end generated code: output=a4e8532d284d035d input=098df188f24e7c62]*/ { - return pack_arguments(1, PyFloat_FromDouble(a)); + PACK_ARGUMENTS(1, PyFloat_FromDouble(a)); } @@ -526,7 +523,7 @@ static PyObject * py_complex_converter_impl(PyObject *module, Py_complex a) /*[clinic end generated code: output=9e6ca2eb53b14846 input=e9148a8ca1dbf195]*/ { - return pack_arguments(1, PyComplex_FromCComplex(a)); + PACK_ARGUMENTS(1, PyComplex_FromCComplex(a)); } @@ -545,10 +542,10 @@ str_converter_impl(PyObject *module, const char *a, const char *b, const char *c, Py_ssize_t c_length) /*[clinic end generated code: output=475bea40548c8cd6 input=bff2656c92ee25de]*/ { - return pack_arguments(3, - PyUnicode_FromString(a), - PyUnicode_FromString(b), - PyUnicode_FromStringAndSize(c, c_length)); + PACK_ARGUMENTS(3, + PyUnicode_FromString(a), + PyUnicode_FromString(b), + PyUnicode_FromStringAndSize(c, c_length)); } @@ -569,8 +566,8 @@ py_buffer_converter_impl(PyObject *module, Py_buffer *a, Py_buffer *b) if (!new_a) { return NULL; } - if (PyBuffer_ToContiguous(((PyBytesObject *)new_a)->ob_sval, a, a->len, - 'C') < 0) { + void *new_a_buf = ((PyBytesObject *)new_a)->ob_sval; + if (PyBuffer_ToContiguous(new_a_buf, a, a->len, 'C') < 0) { Py_DECREF(new_a); return NULL; } @@ -581,15 +578,15 @@ py_buffer_converter_impl(PyObject *module, Py_buffer *a, Py_buffer *b) Py_DECREF(new_a); return NULL; } - if (PyBuffer_ToContiguous(((PyBytesObject *)new_b)->ob_sval, b, b->len, - 'C') < 0) { + void *new_b_buf = ((PyBytesObject *)new_b)->ob_sval; + if (PyBuffer_ToContiguous(new_b_buf, b, b->len, 'C') < 0) { Py_DECREF(new_a); Py_DECREF(new_b); return NULL; } PyBuffer_Release(b); - return pack_arguments(2, new_a, new_b); + PACK_ARGUMENTS(2, new_a, new_b); } @@ -958,3 +955,5 @@ PyInit__testclinic(void) { return PyModule_Create(&_testclinic_module); } + +#undef PACK_ARGUMENTS From dd43f240086329270c6735fa7a80fa808ed926b3 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Mon, 14 Nov 2022 16:54:42 +0800 Subject: [PATCH 25/29] Change argument release order Co-authored-by: Erlend E. Aasland --- Modules/_testclinic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index af4f7075d571da..2294b5ce39388f 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -55,7 +55,7 @@ pack_arguments_newref(int argc, ...) out[_i] = ((PyObject *[]){__VA_ARGS__})[_i]; \ assert(out[_i] || PyErr_Occurred()); \ if (!out[_i]) { \ - for (int _j = _i - 1; _j >= 0; _j--) { \ + for (int _j = 0; _j < _i; _j++) { \ Py_DECREF(out[_j]); \ } \ return NULL; \ From 325e35bc1abdb2b10d3838a018d889655facdba7 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Mon, 14 Nov 2022 16:55:04 +0800 Subject: [PATCH 26/29] Rename macro Co-authored-by: Erlend E. Aasland --- Modules/_testclinic.c | 122 +++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index 2294b5ce39388f..0d58bee7bb2fd5 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -48,7 +48,7 @@ pack_arguments_newref(int argc, ...) /* Pack arguments to a tuple, all the arguments' refcounts should be increased before passing in. * Do not accept NULL arguments unless error occurs. */ -#define PACK_ARGUMENTS(argc, ...) do { \ +#define RETURN_PACKED_ARGS(argc, ...) do { \ assert(!PyErr_Occurred()); \ PyObject *out[argc] = {NULL,}; \ for (int _i = 0; _i < argc; _i++) { \ @@ -222,21 +222,21 @@ char_converter_impl(PyObject *module, char a, char b, char c, char d, char e, char m, char n) /*[clinic end generated code: output=f929dbd2e55a9871 input=b601bc5bc7fe85e3]*/ { - PACK_ARGUMENTS(14, - PyLong_FromUnsignedLong((unsigned char)a), - PyLong_FromUnsignedLong((unsigned char)b), - PyLong_FromUnsignedLong((unsigned char)c), - PyLong_FromUnsignedLong((unsigned char)d), - PyLong_FromUnsignedLong((unsigned char)e), - PyLong_FromUnsignedLong((unsigned char)f), - PyLong_FromUnsignedLong((unsigned char)g), - PyLong_FromUnsignedLong((unsigned char)h), - PyLong_FromUnsignedLong((unsigned char)i), - PyLong_FromUnsignedLong((unsigned char)j), - PyLong_FromUnsignedLong((unsigned char)k), - PyLong_FromUnsignedLong((unsigned char)l), - PyLong_FromUnsignedLong((unsigned char)m), - PyLong_FromUnsignedLong((unsigned char)n)); + RETURN_PACKED_ARGS(14, + PyLong_FromUnsignedLong((unsigned char)a), + PyLong_FromUnsignedLong((unsigned char)b), + PyLong_FromUnsignedLong((unsigned char)c), + PyLong_FromUnsignedLong((unsigned char)d), + PyLong_FromUnsignedLong((unsigned char)e), + PyLong_FromUnsignedLong((unsigned char)f), + PyLong_FromUnsignedLong((unsigned char)g), + PyLong_FromUnsignedLong((unsigned char)h), + PyLong_FromUnsignedLong((unsigned char)i), + PyLong_FromUnsignedLong((unsigned char)j), + PyLong_FromUnsignedLong((unsigned char)k), + PyLong_FromUnsignedLong((unsigned char)l), + PyLong_FromUnsignedLong((unsigned char)m), + PyLong_FromUnsignedLong((unsigned char)n)); } @@ -255,10 +255,10 @@ unsigned_char_converter_impl(PyObject *module, unsigned char a, unsigned char b, unsigned char c) /*[clinic end generated code: output=490af3b39ce0b199 input=e859502fbe0b3185]*/ { - PACK_ARGUMENTS(3, - PyLong_FromUnsignedLong(a), - PyLong_FromUnsignedLong(b), - PyLong_FromUnsignedLong(c)); + RETURN_PACKED_ARGS(3, + PyLong_FromUnsignedLong(a), + PyLong_FromUnsignedLong(b), + PyLong_FromUnsignedLong(c)); } @@ -274,7 +274,7 @@ static PyObject * short_converter_impl(PyObject *module, short a) /*[clinic end generated code: output=1ebb7ddb64248988 input=b4e2309a66f650ae]*/ { - PACK_ARGUMENTS(1, PyLong_FromLong(a)); + RETURN_PACKED_ARGS(1, PyLong_FromLong(a)); } @@ -293,10 +293,10 @@ unsigned_short_converter_impl(PyObject *module, unsigned short a, unsigned short b, unsigned short c) /*[clinic end generated code: output=5f92cc72fc8707a7 input=9d15cd11e741d0c6]*/ { - PACK_ARGUMENTS(3, - PyLong_FromUnsignedLong(a), - PyLong_FromUnsignedLong(b), - PyLong_FromUnsignedLong(c)); + RETURN_PACKED_ARGS(3, + PyLong_FromUnsignedLong(a), + PyLong_FromUnsignedLong(b), + PyLong_FromUnsignedLong(c)); } @@ -314,10 +314,10 @@ static PyObject * int_converter_impl(PyObject *module, int a, int b, int c) /*[clinic end generated code: output=8e56b59be7d0c306 input=a1dbc6344853db7a]*/ { - PACK_ARGUMENTS(3, - PyLong_FromLong(a), - PyLong_FromLong(b), - PyLong_FromLong(c)); + RETURN_PACKED_ARGS(3, + PyLong_FromLong(a), + PyLong_FromLong(b), + PyLong_FromLong(c)); } @@ -336,10 +336,10 @@ unsigned_int_converter_impl(PyObject *module, unsigned int a, unsigned int b, unsigned int c) /*[clinic end generated code: output=399a57a05c494cc7 input=8427ed9a3f96272d]*/ { - PACK_ARGUMENTS(3, - PyLong_FromUnsignedLong(a), - PyLong_FromUnsignedLong(b), - PyLong_FromUnsignedLong(c)); + RETURN_PACKED_ARGS(3, + PyLong_FromUnsignedLong(a), + PyLong_FromUnsignedLong(b), + PyLong_FromUnsignedLong(c)); } @@ -355,7 +355,7 @@ static PyObject * long_converter_impl(PyObject *module, long a) /*[clinic end generated code: output=9663d936a652707a input=84ad0ef28f24bd85]*/ { - PACK_ARGUMENTS(1, PyLong_FromLong(a)); + RETURN_PACKED_ARGS(1, PyLong_FromLong(a)); } @@ -374,10 +374,10 @@ unsigned_long_converter_impl(PyObject *module, unsigned long a, unsigned long b, unsigned long c) /*[clinic end generated code: output=120b82ea9ebd93a8 input=440dd6f1817f5d91]*/ { - PACK_ARGUMENTS(3, - PyLong_FromUnsignedLong(a), - PyLong_FromUnsignedLong(b), - PyLong_FromUnsignedLong(c)); + RETURN_PACKED_ARGS(3, + PyLong_FromUnsignedLong(a), + PyLong_FromUnsignedLong(b), + PyLong_FromUnsignedLong(c)); } @@ -393,7 +393,7 @@ static PyObject * long_long_converter_impl(PyObject *module, long long a) /*[clinic end generated code: output=5fb5f2220770c3e1 input=730fcb3eecf4d993]*/ { - PACK_ARGUMENTS(1, PyLong_FromLongLong(a)); + RETURN_PACKED_ARGS(1, PyLong_FromLongLong(a)); } @@ -412,10 +412,10 @@ unsigned_long_long_converter_impl(PyObject *module, unsigned long long a, unsigned long long b, unsigned long long c) /*[clinic end generated code: output=65b7273e63501762 input=300737b0bdb230e9]*/ { - PACK_ARGUMENTS(3, - PyLong_FromUnsignedLongLong(a), - PyLong_FromUnsignedLongLong(b), - PyLong_FromUnsignedLongLong(c)); + RETURN_PACKED_ARGS(3, + PyLong_FromUnsignedLongLong(a), + PyLong_FromUnsignedLongLong(b), + PyLong_FromUnsignedLongLong(c)); } @@ -434,10 +434,10 @@ py_ssize_t_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b, Py_ssize_t c) /*[clinic end generated code: output=ce252143e0ed0372 input=76d0f342e9317a1f]*/ { - PACK_ARGUMENTS(3, - PyLong_FromSsize_t(a), - PyLong_FromSsize_t(b), - PyLong_FromSsize_t(c)); + RETURN_PACKED_ARGS(3, + PyLong_FromSsize_t(a), + PyLong_FromSsize_t(b), + PyLong_FromSsize_t(c)); } @@ -456,10 +456,10 @@ slice_index_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b, Py_ssize_t c) /*[clinic end generated code: output=923c6cac77666a6b input=64f99f3f83265e47]*/ { - PACK_ARGUMENTS(3, - PyLong_FromSsize_t(a), - PyLong_FromSsize_t(b), - PyLong_FromSsize_t(c)); + RETURN_PACKED_ARGS(3, + PyLong_FromSsize_t(a), + PyLong_FromSsize_t(b), + PyLong_FromSsize_t(c)); } @@ -475,7 +475,7 @@ static PyObject * size_t_converter_impl(PyObject *module, size_t a) /*[clinic end generated code: output=412b5b7334ab444d input=83ae7d9171fbf208]*/ { - PACK_ARGUMENTS(1, PyLong_FromSize_t(a)); + RETURN_PACKED_ARGS(1, PyLong_FromSize_t(a)); } @@ -491,7 +491,7 @@ static PyObject * float_converter_impl(PyObject *module, float a) /*[clinic end generated code: output=1c98f64f2cf1d55c input=a625b59ad68047d8]*/ { - PACK_ARGUMENTS(1, PyFloat_FromDouble((double)a)); + RETURN_PACKED_ARGS(1, PyFloat_FromDouble((double)a)); } @@ -507,7 +507,7 @@ static PyObject * double_converter_impl(PyObject *module, double a) /*[clinic end generated code: output=a4e8532d284d035d input=098df188f24e7c62]*/ { - PACK_ARGUMENTS(1, PyFloat_FromDouble(a)); + RETURN_PACKED_ARGS(1, PyFloat_FromDouble(a)); } @@ -523,7 +523,7 @@ static PyObject * py_complex_converter_impl(PyObject *module, Py_complex a) /*[clinic end generated code: output=9e6ca2eb53b14846 input=e9148a8ca1dbf195]*/ { - PACK_ARGUMENTS(1, PyComplex_FromCComplex(a)); + RETURN_PACKED_ARGS(1, PyComplex_FromCComplex(a)); } @@ -542,10 +542,10 @@ str_converter_impl(PyObject *module, const char *a, const char *b, const char *c, Py_ssize_t c_length) /*[clinic end generated code: output=475bea40548c8cd6 input=bff2656c92ee25de]*/ { - PACK_ARGUMENTS(3, - PyUnicode_FromString(a), - PyUnicode_FromString(b), - PyUnicode_FromStringAndSize(c, c_length)); + RETURN_PACKED_ARGS(3, + PyUnicode_FromString(a), + PyUnicode_FromString(b), + PyUnicode_FromStringAndSize(c, c_length)); } @@ -586,7 +586,7 @@ py_buffer_converter_impl(PyObject *module, Py_buffer *a, Py_buffer *b) } PyBuffer_Release(b); - PACK_ARGUMENTS(2, new_a, new_b); + RETURN_PACKED_ARGS(2, new_a, new_b); } @@ -956,4 +956,4 @@ PyInit__testclinic(void) return PyModule_Create(&_testclinic_module); } -#undef PACK_ARGUMENTS +#undef RETURN_PACKED_ARGS From 967dda6087109c0f61c7ff036cace4600110bba0 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Mon, 14 Nov 2022 16:57:56 +0800 Subject: [PATCH 27/29] Update news --- .../next/Tests/2022-08-22-15-49-14.gh-issue-96002.4UE9UE.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Tests/2022-08-22-15-49-14.gh-issue-96002.4UE9UE.rst b/Misc/NEWS.d/next/Tests/2022-08-22-15-49-14.gh-issue-96002.4UE9UE.rst index d0597e956e2b5d..dc86e1d70f1289 100644 --- a/Misc/NEWS.d/next/Tests/2022-08-22-15-49-14.gh-issue-96002.4UE9UE.rst +++ b/Misc/NEWS.d/next/Tests/2022-08-22-15-49-14.gh-issue-96002.4UE9UE.rst @@ -1 +1 @@ -Add functional test (``test_clinic_functionality``) for Argument Clinic. +Add functional test for Argument Clinic. From d56868310000a32c1559387de393b49413847b18 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Tue, 15 Nov 2022 01:09:49 +0800 Subject: [PATCH 28/29] Fix object leaking --- Modules/_testclinic.c | 168 ++++++++++++++++++++---------------------- 1 file changed, 81 insertions(+), 87 deletions(-) diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index 0d58bee7bb2fd5..1a9d93c882678a 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -46,13 +46,15 @@ pack_arguments_newref(int argc, ...) return tuple; } -/* Pack arguments to a tuple, all the arguments' refcounts should be increased before passing in. - * Do not accept NULL arguments unless error occurs. */ -#define RETURN_PACKED_ARGS(argc, ...) do { \ +/* Pack arguments to a tuple. + * `wrapper` is function which converts primitive type to PyObject. + * `arg_type` is type that arguments should be converted to before wrapped. */ +#define RETURN_PACKED_ARGS(argc, wrapper, arg_type, ...) do { \ assert(!PyErr_Occurred()); \ + arg_type in[argc] = {__VA_ARGS__}; \ PyObject *out[argc] = {NULL,}; \ for (int _i = 0; _i < argc; _i++) { \ - out[_i] = ((PyObject *[]){__VA_ARGS__})[_i]; \ + out[_i] = wrapper((arg_type)in[_i]); \ assert(out[_i] || PyErr_Occurred()); \ if (!out[_i]) { \ for (int _j = 0; _j < _i; _j++) { \ @@ -222,21 +224,8 @@ char_converter_impl(PyObject *module, char a, char b, char c, char d, char e, char m, char n) /*[clinic end generated code: output=f929dbd2e55a9871 input=b601bc5bc7fe85e3]*/ { - RETURN_PACKED_ARGS(14, - PyLong_FromUnsignedLong((unsigned char)a), - PyLong_FromUnsignedLong((unsigned char)b), - PyLong_FromUnsignedLong((unsigned char)c), - PyLong_FromUnsignedLong((unsigned char)d), - PyLong_FromUnsignedLong((unsigned char)e), - PyLong_FromUnsignedLong((unsigned char)f), - PyLong_FromUnsignedLong((unsigned char)g), - PyLong_FromUnsignedLong((unsigned char)h), - PyLong_FromUnsignedLong((unsigned char)i), - PyLong_FromUnsignedLong((unsigned char)j), - PyLong_FromUnsignedLong((unsigned char)k), - PyLong_FromUnsignedLong((unsigned char)l), - PyLong_FromUnsignedLong((unsigned char)m), - PyLong_FromUnsignedLong((unsigned char)n)); + RETURN_PACKED_ARGS(14, PyLong_FromUnsignedLong, unsigned char, + a, b, c, d, e, f, g, h, i, j, k, l, m, n); } @@ -255,10 +244,7 @@ unsigned_char_converter_impl(PyObject *module, unsigned char a, unsigned char b, unsigned char c) /*[clinic end generated code: output=490af3b39ce0b199 input=e859502fbe0b3185]*/ { - RETURN_PACKED_ARGS(3, - PyLong_FromUnsignedLong(a), - PyLong_FromUnsignedLong(b), - PyLong_FromUnsignedLong(c)); + RETURN_PACKED_ARGS(3, PyLong_FromUnsignedLong, unsigned char, a, b, c); } @@ -274,7 +260,7 @@ static PyObject * short_converter_impl(PyObject *module, short a) /*[clinic end generated code: output=1ebb7ddb64248988 input=b4e2309a66f650ae]*/ { - RETURN_PACKED_ARGS(1, PyLong_FromLong(a)); + RETURN_PACKED_ARGS(1, PyLong_FromLong, long, a); } @@ -293,10 +279,7 @@ unsigned_short_converter_impl(PyObject *module, unsigned short a, unsigned short b, unsigned short c) /*[clinic end generated code: output=5f92cc72fc8707a7 input=9d15cd11e741d0c6]*/ { - RETURN_PACKED_ARGS(3, - PyLong_FromUnsignedLong(a), - PyLong_FromUnsignedLong(b), - PyLong_FromUnsignedLong(c)); + RETURN_PACKED_ARGS(3, PyLong_FromUnsignedLong, unsigned long, a, b, c); } @@ -314,10 +297,7 @@ static PyObject * int_converter_impl(PyObject *module, int a, int b, int c) /*[clinic end generated code: output=8e56b59be7d0c306 input=a1dbc6344853db7a]*/ { - RETURN_PACKED_ARGS(3, - PyLong_FromLong(a), - PyLong_FromLong(b), - PyLong_FromLong(c)); + RETURN_PACKED_ARGS(3, PyLong_FromLong, long, a, b, c); } @@ -336,10 +316,7 @@ unsigned_int_converter_impl(PyObject *module, unsigned int a, unsigned int b, unsigned int c) /*[clinic end generated code: output=399a57a05c494cc7 input=8427ed9a3f96272d]*/ { - RETURN_PACKED_ARGS(3, - PyLong_FromUnsignedLong(a), - PyLong_FromUnsignedLong(b), - PyLong_FromUnsignedLong(c)); + RETURN_PACKED_ARGS(3, PyLong_FromUnsignedLong, unsigned long, a, b, c); } @@ -355,7 +332,7 @@ static PyObject * long_converter_impl(PyObject *module, long a) /*[clinic end generated code: output=9663d936a652707a input=84ad0ef28f24bd85]*/ { - RETURN_PACKED_ARGS(1, PyLong_FromLong(a)); + RETURN_PACKED_ARGS(1, PyLong_FromLong, long, a); } @@ -374,10 +351,7 @@ unsigned_long_converter_impl(PyObject *module, unsigned long a, unsigned long b, unsigned long c) /*[clinic end generated code: output=120b82ea9ebd93a8 input=440dd6f1817f5d91]*/ { - RETURN_PACKED_ARGS(3, - PyLong_FromUnsignedLong(a), - PyLong_FromUnsignedLong(b), - PyLong_FromUnsignedLong(c)); + RETURN_PACKED_ARGS(3, PyLong_FromUnsignedLong, unsigned long, a, b, c); } @@ -393,7 +367,7 @@ static PyObject * long_long_converter_impl(PyObject *module, long long a) /*[clinic end generated code: output=5fb5f2220770c3e1 input=730fcb3eecf4d993]*/ { - RETURN_PACKED_ARGS(1, PyLong_FromLongLong(a)); + RETURN_PACKED_ARGS(1, PyLong_FromLongLong, long long, a); } @@ -412,10 +386,8 @@ unsigned_long_long_converter_impl(PyObject *module, unsigned long long a, unsigned long long b, unsigned long long c) /*[clinic end generated code: output=65b7273e63501762 input=300737b0bdb230e9]*/ { - RETURN_PACKED_ARGS(3, - PyLong_FromUnsignedLongLong(a), - PyLong_FromUnsignedLongLong(b), - PyLong_FromUnsignedLongLong(c)); + RETURN_PACKED_ARGS(3, PyLong_FromUnsignedLongLong, unsigned long long, + a, b, c); } @@ -434,10 +406,7 @@ py_ssize_t_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b, Py_ssize_t c) /*[clinic end generated code: output=ce252143e0ed0372 input=76d0f342e9317a1f]*/ { - RETURN_PACKED_ARGS(3, - PyLong_FromSsize_t(a), - PyLong_FromSsize_t(b), - PyLong_FromSsize_t(c)); + RETURN_PACKED_ARGS(3, PyLong_FromSsize_t, Py_ssize_t, a, b, c); } @@ -456,10 +425,7 @@ slice_index_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b, Py_ssize_t c) /*[clinic end generated code: output=923c6cac77666a6b input=64f99f3f83265e47]*/ { - RETURN_PACKED_ARGS(3, - PyLong_FromSsize_t(a), - PyLong_FromSsize_t(b), - PyLong_FromSsize_t(c)); + RETURN_PACKED_ARGS(3, PyLong_FromSsize_t, Py_ssize_t, a, b, c); } @@ -475,7 +441,7 @@ static PyObject * size_t_converter_impl(PyObject *module, size_t a) /*[clinic end generated code: output=412b5b7334ab444d input=83ae7d9171fbf208]*/ { - RETURN_PACKED_ARGS(1, PyLong_FromSize_t(a)); + RETURN_PACKED_ARGS(1, PyLong_FromSize_t, size_t, a); } @@ -491,7 +457,7 @@ static PyObject * float_converter_impl(PyObject *module, float a) /*[clinic end generated code: output=1c98f64f2cf1d55c input=a625b59ad68047d8]*/ { - RETURN_PACKED_ARGS(1, PyFloat_FromDouble((double)a)); + RETURN_PACKED_ARGS(1, PyFloat_FromDouble, double, a); } @@ -507,7 +473,7 @@ static PyObject * double_converter_impl(PyObject *module, double a) /*[clinic end generated code: output=a4e8532d284d035d input=098df188f24e7c62]*/ { - RETURN_PACKED_ARGS(1, PyFloat_FromDouble(a)); + RETURN_PACKED_ARGS(1, PyFloat_FromDouble, double, a); } @@ -523,7 +489,7 @@ static PyObject * py_complex_converter_impl(PyObject *module, Py_complex a) /*[clinic end generated code: output=9e6ca2eb53b14846 input=e9148a8ca1dbf195]*/ { - RETURN_PACKED_ARGS(1, PyComplex_FromCComplex(a)); + RETURN_PACKED_ARGS(1, PyComplex_FromCComplex, Py_complex, a); } @@ -542,13 +508,65 @@ str_converter_impl(PyObject *module, const char *a, const char *b, const char *c, Py_ssize_t c_length) /*[clinic end generated code: output=475bea40548c8cd6 input=bff2656c92ee25de]*/ { - RETURN_PACKED_ARGS(3, - PyUnicode_FromString(a), - PyUnicode_FromString(b), - PyUnicode_FromStringAndSize(c, c_length)); + assert(!PyErr_Occurred()); + PyObject *out[3] = {NULL,}; + int i = 0; + PyObject *arg; + + arg = PyUnicode_FromString(a); + assert(arg || PyErr_Occurred()); + if (!arg) { + goto error; + } + out[i++] = arg; + + arg = PyUnicode_FromString(b); + assert(arg || PyErr_Occurred()); + if (!arg) { + goto error; + } + out[i++] = arg; + + arg = PyUnicode_FromStringAndSize(c, c_length); + assert(arg || PyErr_Occurred()); + if (!arg) { + goto error; + } + out[i++] = arg; + + PyObject *tuple = PyTuple_New(3); + if (!tuple) { + goto error; + } + for (int j = 0; j < 3; j++) { + PyTuple_SET_ITEM(tuple, j, out[j]); + } + return tuple; + +error: + for (int j = 0; j < i; j++) { + Py_DECREF(out[j]); + } + return NULL; } +static PyObject * +bytes_from_buffer(Py_buffer *buf) +{ + PyObject *bytes_obj = PyBytes_FromStringAndSize(NULL, buf->len); + if (!bytes_obj) { + return NULL; + } + void *bytes_obj_buf = ((PyBytesObject *)bytes_obj)->ob_sval; + if (PyBuffer_ToContiguous(bytes_obj_buf, buf, buf->len, 'C') < 0) { + Py_DECREF(bytes_obj); + return NULL; + } + PyBuffer_Release(buf); + return bytes_obj; +} + /*[clinic input] py_buffer_converter @@ -562,31 +580,7 @@ static PyObject * py_buffer_converter_impl(PyObject *module, Py_buffer *a, Py_buffer *b) /*[clinic end generated code: output=52fb13311e3d6d03 input=775de727de5c7421]*/ { - PyObject *new_a = PyBytes_FromStringAndSize(NULL, a->len); - if (!new_a) { - return NULL; - } - void *new_a_buf = ((PyBytesObject *)new_a)->ob_sval; - if (PyBuffer_ToContiguous(new_a_buf, a, a->len, 'C') < 0) { - Py_DECREF(new_a); - return NULL; - } - PyBuffer_Release(a); - - PyObject *new_b = PyBytes_FromStringAndSize(NULL, b->len); - if (!new_b) { - Py_DECREF(new_a); - return NULL; - } - void *new_b_buf = ((PyBytesObject *)new_b)->ob_sval; - if (PyBuffer_ToContiguous(new_b_buf, b, b->len, 'C') < 0) { - Py_DECREF(new_a); - Py_DECREF(new_b); - return NULL; - } - PyBuffer_Release(b); - - RETURN_PACKED_ARGS(2, new_a, new_b); + RETURN_PACKED_ARGS(2, bytes_from_buffer, Py_buffer *, a, b); } From ce337e89e5955fdf5e1148073287c74cd9c38946 Mon Sep 17 00:00:00 2001 From: colorfulappl Date: Tue, 15 Nov 2022 10:31:51 +0800 Subject: [PATCH 29/29] Remove unnecessary logic --- Modules/_testclinic.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index 1a9d93c882678a..c9858e96445714 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -54,7 +54,7 @@ pack_arguments_newref(int argc, ...) arg_type in[argc] = {__VA_ARGS__}; \ PyObject *out[argc] = {NULL,}; \ for (int _i = 0; _i < argc; _i++) { \ - out[_i] = wrapper((arg_type)in[_i]); \ + out[_i] = wrapper(in[_i]); \ assert(out[_i] || PyErr_Occurred()); \ if (!out[_i]) { \ for (int _j = 0; _j < _i; _j++) { \ @@ -563,7 +563,6 @@ bytes_from_buffer(Py_buffer *buf) Py_DECREF(bytes_obj); return NULL; } - PyBuffer_Release(buf); return bytes_obj; }