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; } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy