Tests: add test to ensure restricted py-driver execution is working
Add internal function (only used for testing at the moment)
`_bpy._driver_secure_code_test`.
Add test `script_pyapi_bpy_driver_secure_eval` to serves two purposes:
- Ensure expressions that should be insecure remain so when upgrading
Python or making any changes in this area.
- Ensure new versions of Python don't introduce new byte-codes that
prevent existing expressions from being executed
(happened when upgrading from 3.7, see [0]).
[0]: dfa5201763
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
#include "bpy.h"
|
||||
#include "bpy_app.h"
|
||||
#include "bpy_capi_utils.h"
|
||||
#include "bpy_driver.h"
|
||||
#include "bpy_library.h"
|
||||
#include "bpy_operator.h"
|
||||
#include "bpy_props.h"
|
||||
@@ -326,6 +327,49 @@ static PyObject *bpy_resource_path(PyObject *UNUSED(self), PyObject *args, PyObj
|
||||
return PyC_UnicodeFromByte(path ? path : "");
|
||||
}
|
||||
|
||||
/* This is only exposed for tests, see: `tests/python/bl_pyapi_bpy_driver_secure_eval.py`. */
|
||||
PyDoc_STRVAR(bpy_driver_secure_code_test_doc,
|
||||
".. function:: _driver_secure_code_test(code)\n"
|
||||
"\n"
|
||||
" Test if the script should be considered trusted.\n"
|
||||
"\n"
|
||||
" :arg code: The code to test.\n"
|
||||
" :type code: code\n"
|
||||
" :arg namespace: The namespace of values which are allowed.\n"
|
||||
" :type namespace: dict\n"
|
||||
" :arg verbose: Print the reason for considering insecure to the ``stderr``.\n"
|
||||
" :type verbose: bool\n"
|
||||
" :return: True when the script is considered trusted.\n"
|
||||
" :rtype: bool\n");
|
||||
static PyObject *bpy_driver_secure_code_test(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
|
||||
{
|
||||
PyObject *py_code;
|
||||
PyObject *py_namespace = NULL;
|
||||
const bool verbose = false;
|
||||
static const char *_keywords[] = {"code", "namespace", "verbose", NULL};
|
||||
static _PyArg_Parser _parser = {
|
||||
"O!" /* `expression` */
|
||||
"|$" /* Optional keyword only arguments. */
|
||||
"O!" /* `namespace` */
|
||||
"O&" /* `verbose` */
|
||||
":driver_secure_code_test",
|
||||
_keywords,
|
||||
0,
|
||||
};
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(args,
|
||||
kw,
|
||||
&_parser,
|
||||
&PyCode_Type,
|
||||
&py_code,
|
||||
&PyDict_Type,
|
||||
&py_namespace,
|
||||
PyC_ParseBool,
|
||||
&verbose)) {
|
||||
return NULL;
|
||||
}
|
||||
return PyBool_FromLong(BPY_driver_secure_bytecode_test(py_code, py_namespace, verbose));
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(bpy_escape_identifier_doc,
|
||||
".. function:: escape_identifier(string)\n"
|
||||
"\n"
|
||||
@@ -528,6 +572,12 @@ static PyMethodDef meth_bpy_resource_path = {
|
||||
METH_VARARGS | METH_KEYWORDS,
|
||||
bpy_resource_path_doc,
|
||||
};
|
||||
static PyMethodDef meth_bpy_driver_secure_code_test = {
|
||||
"_driver_secure_code_test",
|
||||
(PyCFunction)bpy_driver_secure_code_test,
|
||||
METH_VARARGS | METH_KEYWORDS,
|
||||
bpy_driver_secure_code_test_doc,
|
||||
};
|
||||
static PyMethodDef meth_bpy_escape_identifier = {
|
||||
"escape_identifier",
|
||||
(PyCFunction)bpy_escape_identifier,
|
||||
@@ -647,6 +697,9 @@ void BPy_init_modules(struct bContext *C)
|
||||
PyModule_AddObject(mod,
|
||||
meth_bpy_resource_path.ml_name,
|
||||
(PyObject *)PyCFunction_New(&meth_bpy_resource_path, NULL));
|
||||
PyModule_AddObject(mod,
|
||||
meth_bpy_driver_secure_code_test.ml_name,
|
||||
(PyObject *)PyCFunction_New(&meth_bpy_driver_secure_code_test, NULL));
|
||||
PyModule_AddObject(mod,
|
||||
meth_bpy_escape_identifier.ml_name,
|
||||
(PyObject *)PyCFunction_New(&meth_bpy_escape_identifier, NULL));
|
||||
|
||||
Reference in New Issue
Block a user