aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Objects/funcobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/funcobject.c')
-rw-r--r--Objects/funcobject.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index 56df5730db0..27214a129c2 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -1,12 +1,14 @@
/* Function object implementation */
#include "Python.h"
+#include "pycore_code.h" // _PyCode_VerifyStateless()
#include "pycore_dict.h" // _Py_INCREF_DICT()
#include "pycore_function.h" // _PyFunction_Vectorcall
#include "pycore_long.h" // _PyLong_GetOne()
#include "pycore_modsupport.h" // _PyArg_NoKeywords()
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
#include "pycore_pyerrors.h" // _PyErr_Occurred()
+#include "pycore_setobject.h" // _PySet_NextEntry()
#include "pycore_stats.h"
@@ -1240,6 +1242,58 @@ PyTypeObject PyFunction_Type = {
};
+int
+_PyFunction_VerifyStateless(PyThreadState *tstate, PyObject *func)
+{
+ assert(!PyErr_Occurred());
+ assert(PyFunction_Check(func));
+
+ // Check the globals.
+ PyObject *globalsns = PyFunction_GET_GLOBALS(func);
+ if (globalsns != NULL && !PyDict_Check(globalsns)) {
+ _PyErr_Format(tstate, PyExc_TypeError,
+ "unsupported globals %R", globalsns);
+ return -1;
+ }
+ // Check the builtins.
+ PyObject *builtinsns = PyFunction_GET_BUILTINS(func);
+ if (builtinsns != NULL && !PyDict_Check(builtinsns)) {
+ _PyErr_Format(tstate, PyExc_TypeError,
+ "unsupported builtins %R", builtinsns);
+ return -1;
+ }
+ // Disallow __defaults__.
+ PyObject *defaults = PyFunction_GET_DEFAULTS(func);
+ if (defaults != NULL && defaults != Py_None && PyDict_Size(defaults) > 0)
+ {
+ _PyErr_SetString(tstate, PyExc_ValueError, "defaults not supported");
+ return -1;
+ }
+ // Disallow __kwdefaults__.
+ PyObject *kwdefaults = PyFunction_GET_KW_DEFAULTS(func);
+ if (kwdefaults != NULL && kwdefaults != Py_None
+ && PyDict_Size(kwdefaults) > 0)
+ {
+ _PyErr_SetString(tstate, PyExc_ValueError,
+ "keyword defaults not supported");
+ return -1;
+ }
+ // Disallow __closure__.
+ PyObject *closure = PyFunction_GET_CLOSURE(func);
+ if (closure != NULL && closure != Py_None && PyTuple_GET_SIZE(closure) > 0)
+ {
+ _PyErr_SetString(tstate, PyExc_ValueError, "closures not supported");
+ return -1;
+ }
+ // Check the code.
+ PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
+ if (_PyCode_VerifyStateless(tstate, co, NULL, globalsns, builtinsns) < 0) {
+ return -1;
+ }
+ return 0;
+}
+
+
static int
functools_copy_attr(PyObject *wrapper, PyObject *wrapped, PyObject *name)
{