diff options
author | Victor Stinner <vstinner@python.org> | 2021-10-11 22:18:26 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-11 22:18:26 (GMT) |
commit | fb8f208a4ddb38eedee71f9ecd0f22058802dab1 (patch) | |
tree | 5968ef94c8b27221c2e1fba4e1c27e5b3c8e6053 | |
parent | 61190e092b8258ede92ac543bb39bad0f7168104 (diff) | |
download | cpython-fb8f208a4ddb38eedee71f9ecd0f22058802dab1.zip cpython-fb8f208a4ddb38eedee71f9ecd0f22058802dab1.tar.gz cpython-fb8f208a4ddb38eedee71f9ecd0f22058802dab1.tar.bz2 |
bpo-45439: _PyObject_Call() only checks tp_vectorcall_offset once (GH-28890)
Add _PyVectorcall_Call() helper function.
Add "assert(PyCallable_Check(callable));" to PyVectorcall_Call(),
similar check than PyVectorcall_Function().
-rw-r--r-- | Include/cpython/abstract.h | 1 | ||||
-rw-r--r-- | Objects/call.c | 59 |
2 files changed, 37 insertions, 23 deletions
diff --git a/Include/cpython/abstract.h b/Include/cpython/abstract.h index db85021..ea269f7 100644 --- a/Include/cpython/abstract.h +++ b/Include/cpython/abstract.h @@ -71,6 +71,7 @@ PyVectorcall_Function(PyObject *callable) return NULL; } assert(PyCallable_Check(callable)); + offset = tp->tp_vectorcall_offset; assert(offset > 0); memcpy(&ptr, (char *) callable + offset, sizeof(ptr)); diff --git a/Objects/call.c b/Objects/call.c index 960c37e..ecf6e68 100644 --- a/Objects/call.c +++ b/Objects/call.c @@ -225,28 +225,11 @@ _PyObject_MakeTpCall(PyThreadState *tstate, PyObject *callable, } -PyObject * -PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs) +static PyObject * +_PyVectorcall_Call(PyThreadState *tstate, vectorcallfunc func, + PyObject *callable, PyObject *tuple, PyObject *kwargs) { - PyThreadState *tstate = _PyThreadState_GET(); - vectorcallfunc func; - - /* get vectorcallfunc as in PyVectorcall_Function, but without - * the Py_TPFLAGS_HAVE_VECTORCALL check */ - Py_ssize_t offset = Py_TYPE(callable)->tp_vectorcall_offset; - if (offset <= 0) { - _PyErr_Format(tstate, PyExc_TypeError, - "'%.200s' object does not support vectorcall", - Py_TYPE(callable)->tp_name); - return NULL; - } - memcpy(&func, (char *) callable + offset, sizeof(func)); - if (func == NULL) { - _PyErr_Format(tstate, PyExc_TypeError, - "'%.200s' object does not support vectorcall", - Py_TYPE(callable)->tp_name); - return NULL; - } + assert(func != NULL); Py_ssize_t nargs = PyTuple_GET_SIZE(tuple); @@ -273,6 +256,35 @@ PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs) PyObject * +PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs) +{ + PyThreadState *tstate = _PyThreadState_GET(); + + /* get vectorcallfunc as in PyVectorcall_Function, but without + * the Py_TPFLAGS_HAVE_VECTORCALL check */ + Py_ssize_t offset = Py_TYPE(callable)->tp_vectorcall_offset; + if (offset <= 0) { + _PyErr_Format(tstate, PyExc_TypeError, + "'%.200s' object does not support vectorcall", + Py_TYPE(callable)->tp_name); + return NULL; + } + assert(PyCallable_Check(callable)); + + vectorcallfunc func; + memcpy(&func, (char *) callable + offset, sizeof(func)); + if (func == NULL) { + _PyErr_Format(tstate, PyExc_TypeError, + "'%.200s' object does not support vectorcall", + Py_TYPE(callable)->tp_name); + return NULL; + } + + return _PyVectorcall_Call(tstate, func, callable, tuple, kwargs); +} + + +PyObject * _PyObject_Call(PyThreadState *tstate, PyObject *callable, PyObject *args, PyObject *kwargs) { @@ -286,8 +298,9 @@ _PyObject_Call(PyThreadState *tstate, PyObject *callable, assert(PyTuple_Check(args)); assert(kwargs == NULL || PyDict_Check(kwargs)); - if (PyVectorcall_Function(callable) != NULL) { - return PyVectorcall_Call(callable, args, kwargs); + vectorcallfunc vector_func = PyVectorcall_Function(callable); + if (vector_func != NULL) { + return _PyVectorcall_Call(tstate, vector_func, callable, args, kwargs); } else { call = Py_TYPE(callable)->tp_call; |