summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2021-10-11 22:18:26 (GMT)
committerGitHub <noreply@github.com>2021-10-11 22:18:26 (GMT)
commitfb8f208a4ddb38eedee71f9ecd0f22058802dab1 (patch)
tree5968ef94c8b27221c2e1fba4e1c27e5b3c8e6053
parent61190e092b8258ede92ac543bb39bad0f7168104 (diff)
downloadcpython-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.h1
-rw-r--r--Objects/call.c59
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;