[Python-checkins] bpo-45439: _PyObject_Call() only checks tp_vectorcall_offset once (GH-28890)

vstinner webhook-mailer at python.org
Mon Oct 11 18:18:34 EDT 2021


https://github.com/python/cpython/commit/fb8f208a4ddb38eedee71f9ecd0f22058802dab1
commit: fb8f208a4ddb38eedee71f9ecd0f22058802dab1
branch: main
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2021-10-12T00:18:26+02:00
summary:

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().

files:
M Include/cpython/abstract.h
M Objects/call.c

diff --git a/Include/cpython/abstract.h b/Include/cpython/abstract.h
index db85021964528..ea269f7320405 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 960c37e1961f0..ecf6e68a2c8ee 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);
 
@@ -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;



More information about the Python-checkins mailing list