Based on https://github.com/blender/blender/commit/780c0ea097444c3be60314dffd203c099720badb diff --git source/blender/python/generic/py_capi_utils.c source/blender/python/generic/py_capi_utils.c index 44293759672..2b2ca4acced 100644 --- source/blender/python/generic/py_capi_utils.c +++ source/blender/python/generic/py_capi_utils.c @@ -402,6 +402,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; @@ -410,13 +411,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 source/blender/python/intern/bpy_driver.c source/blender/python/intern/bpy_driver.c index 6c078e4228c..af5a04c60c6 100644 --- source/blender/python/intern/bpy_driver.c +++ source/blender/python/intern/bpy_driver.c @@ -276,6 +276,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), @@ -338,6 +388,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 @@ -375,7 +427,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 source/blender/python/intern/bpy_interface.c source/blender/python/intern/bpy_interface.c index 5f31e0bb74d..c07ea42c872 100644 --- source/blender/python/intern/bpy_interface.c +++ source/blender/python/intern/bpy_interface.c @@ -589,16 +589,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 *filename = 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", filename, 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 source/blender/python/intern/bpy_traceback.c source/blender/python/intern/bpy_traceback.c index 00b414e027e..019dc38488f 100644 --- source/blender/python/intern/bpy_traceback.c +++ source/blender/python/intern/bpy_traceback.c @@ -34,7 +34,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); }