26#include "RNA_prototypes.hh"
37#define USE_RNA_AS_PYOBJECT
39#define USE_BYTECODE_WHITELIST
41#ifdef USE_BYTECODE_WHITELIST
45#if PY_VERSION_HEX >= 0x030d0000
49# include <internal/pycore_code.h>
54#ifdef USE_BYTECODE_WHITELIST
75 PyDict_SetItemString(d,
"__builtins__", PyEval_GetBuiltins());
77 mod = PyImport_ImportModule(
"math");
79 PyDict_Merge(d, PyModule_GetDict(
mod), 0);
82#ifdef USE_BYTECODE_WHITELIST
83 PyObject *mod_math =
mod;
87 mod = PyImport_ImportModuleLevel(
"bpy",
nullptr,
nullptr,
nullptr, 0);
94 mod = PyImport_ImportModuleLevel(
"mathutils",
nullptr,
nullptr,
nullptr, 0);
96 PyObject *modsub = PyDict_GetItemString(PyModule_GetDict(
mod),
"noise");
102 mod = PyImport_ImportModuleLevel(
"bl_math",
nullptr,
nullptr,
nullptr, 0);
104 static const char *names[] = {
"clamp",
"lerp",
"smoothstep",
nullptr};
106 for (
const char **pname = names; *pname; ++pname) {
107 PyObject *func = PyDict_GetItemString(PyModule_GetDict(
mod), *pname);
114#ifdef USE_BYTECODE_WHITELIST
118 const char *whitelist[] = {
141 for (
int i = 0; whitelist[
i];
i++) {
146 if (mod_math !=
nullptr) {
147 PyObject *mod_math_dict = PyModule_GetDict(mod_math);
148 PyObject *arg_key, *arg_value;
149 Py_ssize_t arg_pos = 0;
150 while (PyDict_Next(mod_math_dict, &arg_pos, &arg_key, &arg_value)) {
151 const char *arg_str = PyUnicode_AsUTF8(arg_key);
152 if (arg_str[0] && arg_str[1] !=
'_') {
179 PyObject *item = PyFloat_FromDouble(
evaltime);
249#ifdef USE_BYTECODE_WHITELIST
266 PyGILState_STATE gilstate;
267 const bool use_gil =
true;
269 gilstate = PyGILState_Ensure();
276 PyGILState_Release(gilstate);
289 const char *null_str =
"<null>";
293 "Error in PyDriver: expression failed: %s\n"
294 "For target: (type=%s, name=\"%s\", property=%s, property_index=%d)\n"
298 id ? id->
name + 2 : null_str,
306#ifdef USE_BYTECODE_WHITELIST
322# if PY_VERSION_HEX < 0x030c0000
323 OK_OP(UNARY_POSITIVE)
325 OK_OP(UNARY_NEGATIVE)
328# if PY_VERSION_HEX < 0x030e0000
332# if PY_VERSION_HEX < 0x030c0000
343# if PY_VERSION_HEX < 0x030c0000
344 OK_OP(JUMP_IF_FALSE_OR_POP)
345 OK_OP(JUMP_IF_TRUE_OR_POP)
346 OK_OP(POP_JUMP_FORWARD_IF_FALSE)
347 OK_OP(POP_JUMP_FORWARD_IF_TRUE)
356# if PY_VERSION_HEX < 0x030c0000
357 OK_OP(POP_JUMP_FORWARD_IF_NOT_NONE)
358 OK_OP(POP_JUMP_FORWARD_IF_NONE)
373# if PY_VERSION_HEX < 0x030c0000
374 OK_OP(POP_JUMP_BACKWARD_IF_NOT_NONE)
375 OK_OP(POP_JUMP_BACKWARD_IF_NONE)
376 OK_OP(POP_JUMP_BACKWARD_IF_FALSE)
377 OK_OP(POP_JUMP_BACKWARD_IF_TRUE)
384# if PY_VERSION_HEX >= 0x030d0000
387 OK_OP(CALL_FUNCTION_EX);
390 OK_OP(CALL_ALLOC_AND_ENTER_INIT)
391 OK_OP(CALL_BOUND_METHOD_EXACT_ARGS)
392 OK_OP(CALL_BOUND_METHOD_GENERAL)
393 OK_OP(CALL_BUILTIN_CLASS)
394 OK_OP(CALL_BUILTIN_FAST)
395 OK_OP(CALL_BUILTIN_FAST_WITH_KEYWORDS)
396 OK_OP(CALL_BUILTIN_O)
397 OK_OP(CALL_ISINSTANCE)
399 OK_OP(CALL_LIST_APPEND)
400 OK_OP(CALL_METHOD_DESCRIPTOR_FAST)
401 OK_OP(CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS)
402 OK_OP(CALL_METHOD_DESCRIPTOR_NOARGS)
403 OK_OP(CALL_METHOD_DESCRIPTOR_O)
404 OK_OP(CALL_NON_PY_GENERAL)
405 OK_OP(CALL_PY_EXACT_ARGS)
406 OK_OP(CALL_PY_GENERAL)
414# if PY_VERSION_HEX < 0x030c0000
424 PyObject *py_namespace_array[],
426 const char *error_prefix)
428 PyCodeObject *py_code = (PyCodeObject *)expr_code;
432 for (
int i = 0;
i < PyTuple_GET_SIZE(py_code->co_names);
i++) {
433 PyObject *
name = PyTuple_GET_ITEM(py_code->co_names,
i);
434 const char *name_str = PyUnicode_AsUTF8(
name);
435 bool contains_name =
false;
436 for (
int j = 0; py_namespace_array[j]; j++) {
437 if (PyDict_Contains(py_namespace_array[j],
name)) {
438 contains_name =
true;
443 if ((contains_name ==
false) || (name_str[0] ==
'_')) {
446 "\t%s: restricted access disallows name '%s', "
447 "enable auto-execution to support\n",
458 const _Py_CODEUNIT *codestr;
463 co_code = PyCode_GetCode(py_code);
469 PyBytes_AsStringAndSize(co_code, (
char **)&codestr, &code_len);
470 code_len /=
sizeof(*codestr);
474 for (Py_ssize_t
i = 0;
i < code_len;
i++) {
475 const int opcode = _Py_OPCODE(codestr[
i]);
479 "\t%s: restricted access disallows opcode '%d', "
480 "enable auto-execution to support\n",
499 PyObject *py_namespace,
505 fprintf(stderr,
"%s: couldn't create Python dictionary\n", __func__);
509 PyObject *py_namespaces[] = {
533 PyObject *driver_vars =
nullptr;
534 PyObject *retval =
nullptr;
540 PyGILState_STATE gilstate;
546 bool targets_ok =
true;
551 if (expr[0] ==
'\0') {
555#ifndef USE_BYTECODE_WHITELIST
561 printf(
"skipping driver '%s', automatic scripts are disabled\n", expr);
567 bool is_recompile =
false;
573 gilstate = PyGILState_Ensure();
582 fprintf(stderr,
"%s: couldn't create Python dictionary\n", __func__);
584 PyGILState_Release(gilstate);
611 expr_code = Py_CompileString(expr,
"<bpy driver>", Py_eval_input);
612 PyTuple_SET_ITEM(((PyObject *)driver_orig->
expr_comp), 0, expr_code);
620#ifdef USE_BYTECODE_WHITELIST
625 expr_code = PyTuple_GET_ITEM(((PyObject *)driver_orig->
expr_comp), 0);
630 expr_vars = PyTuple_GET_ITEM(((PyObject *)driver_orig->
expr_comp), 1);
631 Py_XDECREF(expr_vars);
634 PyTuple_SET_ITEM(((PyObject *)driver_orig->
expr_comp), 1, expr_vars);
639 PyTuple_SET_ITEM(expr_vars,
i++, PyUnicode_FromString(dvar->
name));
645 expr_vars = PyTuple_GET_ITEM(((PyObject *)driver_orig->
expr_comp), 1);
649 driver_vars = _PyDict_NewPresized(PyTuple_GET_SIZE(expr_vars));
651 PyObject *driver_arg =
nullptr;
654#ifdef USE_RNA_AS_PYOBJECT
657 anim_eval_context, driver, dvar, &dvar->
targets[0]);
659 if (driver_arg ==
nullptr) {
660 driver_arg = PyFloat_FromDouble(0.0);
665 if (PyFloat_CheckExact(driver_arg)) {
666 dvar->
curval =
float(PyFloat_AsDouble(driver_arg));
668 else if (PyLong_CheckExact(driver_arg)) {
671 else if (PyBool_Check(driver_arg)) {
684 driver_arg = PyFloat_FromDouble(
double(tval));
689 if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars,
i++), driver_arg) != -1) {
696 fprintf(stderr,
"\n%s: Error while evaluating PyDriver:\n", __func__);
700 fprintf(stderr,
"\t%s: couldn't add variable '%s' to namespace\n", __func__, dvar->
name);
707#ifdef USE_BYTECODE_WHITELIST
708 if (is_recompile && expr_code) {
710 PyObject *py_namespaces[] = {
726 PyTuple_SET_ITEM(((PyObject *)driver_orig->
expr_comp), 0,
nullptr);
739 retval = PyEval_EvalCode(
748 if (retval ==
nullptr) {
752 if (
UNLIKELY((
result = PyFloat_AsDouble(retval)) == -1.0 && PyErr_Occurred())) {
764 PyGILState_Release(gilstate);
768 fprintf(stderr,
"\t%s: driver '%s' evaluates to '%f'\n", __func__, driver->
expression,
result);
float driver_get_variable_value(const struct AnimationEvalContext *anim_eval_context, struct ChannelDriver *driver, struct DriverVar *dvar)
@ G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET
@ G_FLAG_SCRIPT_AUTOEXEC_FAIL
const char * BKE_idtype_idcode_to_name(short idcode)
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define SNPRINTF_UTF8(dst, format,...)
@ DRIVER_FLAG_PYTHON_BLOCKED
static PyObject * bpy_pydriver_Dict__whitelist
static bool is_opcode_secure(const int opcode)
PyObject * bpy_pydriver_Dict
static struct @227352076010261012140035020175267314002332116034 g_pydriver_state_prev
static void bpy_pydriver_namespace_update_depsgraph(Depsgraph *depsgraph)
static void pydriver_error(ChannelDriver *driver, const PathResolvedRNA *anim_rna)
static void bpy_pydriver_namespace_update_self(PathResolvedRNA *anim_rna)
float BPY_driver_exec(PathResolvedRNA *anim_rna, ChannelDriver *driver, ChannelDriver *driver_orig, const AnimationEvalContext *anim_eval_context)
BPy_StructRNA * depsgraph
static void bpy_pydriver_namespace_update_frame(const float evaltime)
int bpy_pydriver_create_dict()
bool BPY_driver_secure_bytecode_test_ex(PyObject *expr_code, PyObject *py_namespace_array[], const bool verbose, const char *error_prefix)
static PyObject * bpy_pydriver_depsgraph_as_pyobject(Depsgraph *depsgraph)
static void bpy_pydriver_namespace_clear_self()
bool BPY_driver_secure_bytecode_test(PyObject *expr_code, PyObject *py_namespace, const bool verbose)
PyObject * bpy_intern_str_depsgraph
PyObject * bpy_intern_str_self
PyObject * bpy_intern_str_frame
void BPY_update_rna_module()
PyObject * pyrna_struct_CreatePyObject(PointerRNA *ptr)
PyObject * pyrna_driver_get_variable_value(const AnimationEvalContext *anim_eval_context, ChannelDriver *driver, DriverVar *dvar, DriverTarget *dtar)
PyObject * pyrna_driver_self_from_anim_rna(PathResolvedRNA *anim_rna)
bool pyrna_driver_is_equal_anim_rna(const PathResolvedRNA *anim_rna, const PyObject *py_anim_rna)
VecBase< float, D > constexpr mod(VecOp< float, D >, VecOp< float, D >) RET
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
const char * RNA_property_identifier(const PropertyRNA *prop)
#define CALL(member, value_str)
struct Depsgraph * depsgraph