]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-45439: _PyObject_Call() only checks tp_vectorcall_offset once (GH-28890)
authorVictor Stinner <vstinner@python.org>
Mon, 11 Oct 2021 22:18:26 +0000 (00:18 +0200)
committerGitHub <noreply@github.com>
Mon, 11 Oct 2021 22:18:26 +0000 (00:18 +0200)
Add _PyVectorcall_Call() helper function.

Add "assert(PyCallable_Check(callable));" to PyVectorcall_Call(),
similar check than PyVectorcall_Function().

Include/cpython/abstract.h
Objects/call.c

index db8502196452817d456575ceeea64d8595f59dd0..ea269f7320405faea1999dc9602a1870eeffbb11 100644 (file)
@@ -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));
index 960c37e1961f0a73e609237dc6802bef8f8c6288..ecf6e68a2c8eedfa12a62f71bb9ef5d62112e0e9 100644 (file)
@@ -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);
 
@@ -272,6 +255,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;