diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index d2e3c44c1b6..8230801e184 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -641,6 +641,7 @@ void PyC_StackSpit(void) void PyC_FileAndNum(const char **r_filename, int *r_lineno) { PyFrameObject *frame; + PyCodeObject *code; if (r_filename) { *r_filename = NULL; @@ -649,13 +650,16 @@ void PyC_FileAndNum(const char **r_filename, int *r_lineno) *r_lineno = -1; } - if (!(frame = PyThreadState_GET()->frame)) { + if (!(frame = PyEval_GetFrame())) { + return; + } + if (!(code = PyFrame_GetCode(frame))) { return; } /* when executing a script */ if (r_filename) { - *r_filename = PyUnicode_AsUTF8(frame->f_code->co_filename); + *r_filename = PyUnicode_AsUTF8(code->co_filename); } /* when executing a module */ diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index 05def07a6d7..f71cf164e8c 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -285,6 +285,56 @@ static void pydriver_error(ChannelDriver *driver) # define OK_OP(op) [op] = 1 static const char secure_opcodes[255] = { +# if PY_VERSION_HEX >= 0x030b0000 /* Python 3.11 & newer. */ + + OK_OP(CACHE), + OK_OP(POP_TOP), + OK_OP(PUSH_NULL), + OK_OP(NOP), + OK_OP(UNARY_POSITIVE), + OK_OP(UNARY_NEGATIVE), + OK_OP(UNARY_NOT), + OK_OP(UNARY_INVERT), + OK_OP(BINARY_SUBSCR), + OK_OP(GET_LEN), + OK_OP(RETURN_VALUE), + OK_OP(SWAP), + OK_OP(BUILD_TUPLE), + OK_OP(BUILD_LIST), + OK_OP(BUILD_SET), + OK_OP(BUILD_MAP), + OK_OP(COMPARE_OP), + OK_OP(JUMP_FORWARD), + OK_OP(JUMP_IF_FALSE_OR_POP), + OK_OP(JUMP_IF_TRUE_OR_POP), + OK_OP(POP_JUMP_FORWARD_IF_FALSE), + OK_OP(POP_JUMP_FORWARD_IF_TRUE), + OK_OP(LOAD_GLOBAL), + OK_OP(IS_OP), + OK_OP(BINARY_OP), + OK_OP(LOAD_FAST), + OK_OP(STORE_FAST), + OK_OP(DELETE_FAST), + OK_OP(POP_JUMP_FORWARD_IF_NOT_NONE), + OK_OP(POP_JUMP_FORWARD_IF_NONE), + OK_OP(BUILD_SLICE), + OK_OP(LOAD_DEREF), + OK_OP(STORE_DEREF), + OK_OP(RESUME), + OK_OP(POP_JUMP_BACKWARD_IF_NOT_NONE), + OK_OP(POP_JUMP_BACKWARD_IF_NONE), + OK_OP(POP_JUMP_BACKWARD_IF_FALSE), + OK_OP(POP_JUMP_BACKWARD_IF_TRUE), + + /* Special cases. */ + OK_OP(LOAD_CONST), /* Ok because constants are accepted. */ + OK_OP(LOAD_NAME), /* Ok, because `PyCodeObject.names` is checked. */ + OK_OP(CALL), /* Ok, because we check its "name" before calling. */ + OK_OP(KW_NAMES), /* Ok, because it's used for calling functions with keyword arguments. */ + OK_OP(PRECALL), /* Ok, because it's used for calling. */ + +# else /* Python 3.10 and older. */ + OK_OP(POP_TOP), OK_OP(ROT_TWO), OK_OP(ROT_THREE), @@ -352,6 +402,8 @@ static const char secure_opcodes[255] = { OK_OP(CALL_FUNCTION), /* Ok, because we check its "name" before calling. */ OK_OP(CALL_FUNCTION_KW), OK_OP(CALL_FUNCTION_EX), + +# endif /* Python 3.10 and older. */ }; # undef OK_OP @@ -388,7 +440,15 @@ static bool bpy_driver_secure_bytecode_validate(PyObject *expr_code, PyObject *d const _Py_CODEUNIT *codestr; Py_ssize_t code_len; - PyBytes_AsStringAndSize(py_code->co_code, (char **)&codestr, &code_len); + PyObject *co_code; + +# if PY_VERSION_HEX >= 0x030b0000 /* Python 3.11 & newer. */ + co_code = py_code->_co_code; +# else + co_code = py_code->co_code; +# endif + + PyBytes_AsStringAndSize(co_code, (char **)&codestr, &code_len); code_len /= sizeof(*codestr); for (Py_ssize_t i = 0; i < code_len; i++) { diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 0ab8b4385e5..ea64fa6c098 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -582,16 +582,17 @@ void BPY_python_use_system_env(void) void BPY_python_backtrace(FILE *fp) { fputs("\n# Python backtrace\n", fp); - PyThreadState *tstate = PyGILState_GetThisThreadState(); - if (tstate != NULL && tstate->frame != NULL) { - PyFrameObject *frame = tstate->frame; - do { - const int line = PyCode_Addr2Line(frame->f_code, frame->f_lasti); - const char *filepath = PyUnicode_AsUTF8(frame->f_code->co_filename); - const char *funcname = PyUnicode_AsUTF8(frame->f_code->co_name); - fprintf(fp, " File \"%s\", line %d in %s\n", filepath, line, funcname); - } while ((frame = frame->f_back)); + PyFrameObject *frame; + if (!(frame = PyEval_GetFrame())) { + return; } + do { + PyCodeObject *code = PyFrame_GetCode(frame); + const int line = PyFrame_GetLineNumber(frame); + const char *filepath = PyUnicode_AsUTF8(code->co_filename); + const char *funcname = PyUnicode_AsUTF8(code->co_name); + fprintf(fp, " File \"%s\", line %d in %s\n", filepath, line, funcname); + } while ((frame = PyFrame_GetBack(frame))); } void BPY_DECREF(void *pyob_ptr) diff --git a/source/blender/python/intern/bpy_traceback.c b/source/blender/python/intern/bpy_traceback.c index cb93843a6de..1f2458c752f 100644 --- a/source/blender/python/intern/bpy_traceback.c +++ b/source/blender/python/intern/bpy_traceback.c @@ -20,7 +20,8 @@ static const char *traceback_filepath(PyTracebackObject *tb, PyObject **coerce) { - *coerce = PyUnicode_EncodeFSDefault(tb->tb_frame->f_code->co_filename); + PyCodeObject *code = PyFrame_GetCode(tb->tb_frame); + *coerce = PyUnicode_EncodeFSDefault(code->co_filename); return PyBytes_AS_STRING(*coerce); }