gh-64490: Fix bugs in argument clinic varargs processing (#32092)

This commit is contained in:
colorfulappl 2022-11-25 03:56:50 +08:00 committed by GitHub
parent 351842b46a
commit 0da728387c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 612 additions and 11 deletions

View file

@ -950,6 +950,25 @@ keyword_only_parameter_impl(PyObject *module, PyObject *a)
}
/*[clinic input]
posonly_vararg
a: object
/
b: object
*args: object
[clinic start generated code]*/
static PyObject *
posonly_vararg_impl(PyObject *module, PyObject *a, PyObject *b,
PyObject *args)
/*[clinic end generated code: output=ee6713acda6b954e input=783427fe7ec2b67a]*/
{
return pack_arguments_newref(3, a, b, args);
}
/*[clinic input]
vararg_and_posonly
@ -967,6 +986,100 @@ vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *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]*/
{
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.
[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=46d15c881608f8ff]*/
{
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.
[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=5c0bd5b9079a0cce]*/
{
Py_RETURN_NONE;
}
/*[clinic input]
gh_99233_refcount
@ -1046,7 +1159,13 @@ static PyMethodDef tester_methods[] = {
POSONLY_KEYWORDS_OPT_KWONLY_OPT_METHODDEF
POSONLY_OPT_KEYWORDS_OPT_KWONLY_OPT_METHODDEF
KEYWORD_ONLY_PARAMETER_METHODDEF
POSONLY_VARARG_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}

View file

@ -2326,6 +2326,66 @@ exit:
return return_value;
}
PyDoc_STRVAR(posonly_vararg__doc__,
"posonly_vararg($module, a, /, b, *args)\n"
"--\n"
"\n");
#define POSONLY_VARARG_METHODDEF \
{"posonly_vararg", _PyCFunction_CAST(posonly_vararg), METH_FASTCALL|METH_KEYWORDS, posonly_vararg__doc__},
static PyObject *
posonly_vararg_impl(PyObject *module, PyObject *a, PyObject *b,
PyObject *args);
static PyObject *
posonly_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(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_vararg",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[3];
PyObject *a;
PyObject *b;
PyObject *__clinic_args = NULL;
args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, 2, argsbuf);
if (!args) {
goto exit;
}
a = args[0];
b = args[1];
__clinic_args = args[2];
return_value = posonly_vararg_impl(module, a, b, __clinic_args);
exit:
Py_XDECREF(__clinic_args);
return return_value;
}
PyDoc_STRVAR(vararg_and_posonly__doc__,
"vararg_and_posonly($module, a, /, *args)\n"
"--\n"
@ -2359,6 +2419,334 @@ exit:
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];
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 = Py_MIN(nargs, 1) + (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.");
#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 = Py_MIN(nargs, 2) + (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.");
#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 = Py_MIN(nargs, 1) + (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"
@ -2423,4 +2811,4 @@ gh_99240_double_free(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
exit:
return return_value;
}
/*[clinic end generated code: output=49dced2c99bcd0fb input=a9049054013a1b77]*/
/*[clinic end generated code: output=9a5ca5909c087102 input=a9049054013a1b77]*/