From 2ceff8bd63252924a2ae06451af6080876ed0cb3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 17 Jun 2018 19:51:05 +0200 Subject: [PATCH 1/3] Python: Allow untrusted py-drivers to run limited expressions Limit to a restricted set of built-ins, as well as the math module. Also restrict of op-codes, disallowing imports and attribute access. This allows most math expressions to run without any performance cost once the initial check is done. See: D1862 for details. --- .../editors/space_graph/graph_buttons.c | 2 +- source/blender/python/intern/bpy_driver.c | 212 ++++++++++++++++++ 2 files changed, 213 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index d5586a51a40..cac379f3786 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -782,7 +782,7 @@ static void graph_panel_drivers(const bContext *C, Panel *pa) /* errors? */ if ((G.f & G_SCRIPT_AUTOEXEC) == 0) { - uiItemL(col, IFACE_("ERROR: Python auto-execution disabled"), ICON_CANCEL); + uiItemL(col, IFACE_("WARNING: Python expressions limited for security"), ICON_ERROR); } else if (driver->flag & DRIVER_FLAG_INVALID) { uiItemL(col, IFACE_("ERROR: Invalid Python expression"), ICON_CANCEL); diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index 215a64a4449..bc81eb8ee24 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -52,9 +52,19 @@ extern void BPY_update_rna_module(void); #define USE_RNA_AS_PYOBJECT +#define USE_BYTECODE_WHITELIST + +#ifdef USE_BYTECODE_WHITELIST +# include +#endif + /* for pydrivers (drivers using one-line Python expressions to express relationships between targets) */ PyObject *bpy_pydriver_Dict = NULL; +#ifdef USE_BYTECODE_WHITELIST +static PyObject *bpy_pydriver_Dict__whitelist = NULL; +#endif + /* For faster execution we keep a special dictionary for pydrivers, with * the needed modules and aliases. */ @@ -79,6 +89,9 @@ int bpy_pydriver_create_dict(void) PyDict_Merge(d, PyModule_GetDict(mod), 0); /* 0 - don't overwrite existing values */ Py_DECREF(mod); } +#ifdef USE_BYTECODE_WHITELIST + PyObject *mod_math = mod; +#endif /* add bpy to global namespace */ mod = PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0); @@ -95,6 +108,48 @@ int bpy_pydriver_create_dict(void) Py_DECREF(mod); } +#ifdef USE_BYTECODE_WHITELIST + /* setup the whitelist */ + { + bpy_pydriver_Dict__whitelist = PyDict_New(); + const char *whitelist[] = { + /* builtins (basic) */ + "all", + "any", + "len", + /* builtins (numeric) */ + "max", + "min", + "pow", + "round", + "sum", + /* types */ + "bool", + "float", + "int", + + NULL, + }; + + for (int i = 0; whitelist[i]; i++) { + PyDict_SetItemString(bpy_pydriver_Dict__whitelist, whitelist[i], Py_None); + } + + /* Add all of 'math' functions. */ + if (mod_math != NULL) { + PyObject *mod_math_dict = PyModule_GetDict(mod_math); + PyObject *arg_key, *arg_value; + Py_ssize_t arg_pos = 0; + while (PyDict_Next(mod_math_dict, &arg_pos, &arg_key, &arg_value)) { + const char *arg_str = _PyUnicode_AsString(arg_key); + if (arg_str[0] && arg_str[1] != '_') { + PyDict_SetItem(bpy_pydriver_Dict__whitelist, arg_key, Py_None); + } + } + } + } +#endif /* USE_BYTECODE_WHITELIST */ + return 0; } @@ -163,6 +218,14 @@ void BPY_driver_reset(void) bpy_pydriver_Dict = NULL; } +#ifdef USE_BYTECODE_WHITELIST + if (bpy_pydriver_Dict__whitelist) { + PyDict_Clear(bpy_pydriver_Dict__whitelist); + Py_DECREF(bpy_pydriver_Dict__whitelist); + bpy_pydriver_Dict__whitelist = NULL; + } +#endif + g_pydriver_state_prev.evaltime = FLT_MAX; /* freed when clearing driver dict */ @@ -185,6 +248,130 @@ static void pydriver_error(ChannelDriver *driver) PyErr_Clear(); } +#ifdef USE_BYTECODE_WHITELIST + +#define OK_OP(op) [op] = 1 + +const char secure_opcodes[255] = { + OK_OP(0), + OK_OP(POP_TOP), + OK_OP(ROT_TWO), + OK_OP(ROT_THREE), + OK_OP(DUP_TOP), + OK_OP(DUP_TOP_TWO), + OK_OP(NOP), + OK_OP(UNARY_POSITIVE), + OK_OP(UNARY_NEGATIVE), + OK_OP(UNARY_NOT), + OK_OP(UNARY_INVERT), + OK_OP(BINARY_MATRIX_MULTIPLY), + OK_OP(INPLACE_MATRIX_MULTIPLY), + OK_OP(BINARY_POWER), + OK_OP(BINARY_MULTIPLY), + OK_OP(BINARY_MODULO), + OK_OP(BINARY_ADD), + OK_OP(BINARY_SUBTRACT), + OK_OP(BINARY_SUBSCR), + OK_OP(BINARY_FLOOR_DIVIDE), + OK_OP(BINARY_TRUE_DIVIDE), + OK_OP(INPLACE_FLOOR_DIVIDE), + OK_OP(INPLACE_TRUE_DIVIDE), + OK_OP(INPLACE_ADD), + OK_OP(INPLACE_SUBTRACT), + OK_OP(INPLACE_MULTIPLY), + OK_OP(INPLACE_MODULO), + OK_OP(BINARY_LSHIFT), + OK_OP(BINARY_RSHIFT), + OK_OP(BINARY_AND), + OK_OP(BINARY_XOR), + OK_OP(BINARY_OR), + OK_OP(INPLACE_POWER), + OK_OP(INPLACE_LSHIFT), + OK_OP(INPLACE_RSHIFT), + OK_OP(INPLACE_AND), + OK_OP(INPLACE_XOR), + OK_OP(INPLACE_OR), + OK_OP(RETURN_VALUE), + 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(JUMP_ABSOLUTE), + OK_OP(POP_JUMP_IF_FALSE), + OK_OP(POP_JUMP_IF_TRUE), + OK_OP(LOAD_GLOBAL), + OK_OP(LOAD_FAST), + OK_OP(STORE_FAST), + OK_OP(DELETE_FAST), + OK_OP(LOAD_DEREF), + OK_OP(STORE_DEREF), + + /* special cases */ + OK_OP(LOAD_CONST), /* ok because constants are accepted */ + OK_OP(LOAD_NAME), /* ok, because PyCodeObject.names is checked */ + OK_OP(CALL_FUNCTION), /* ok, because we check its 'name' before calling */ + OK_OP(CALL_FUNCTION_KW), + OK_OP(CALL_FUNCTION_EX), +}; + +#undef OK_OP + +static bool bpy_driver_secure_bytecode_validate(PyObject *expr_code, PyObject *dict_arr[]) +{ + PyCodeObject *py_code = (PyCodeObject *)expr_code; + + /* Check names. */ + { + for (int i = 0; i < PyTuple_GET_SIZE(py_code->co_names); i++) { + PyObject *name = PyTuple_GET_ITEM(py_code->co_names, i); + + bool contains_name = false; + for (int j = 0; dict_arr[j]; j++) { + if (PyDict_Contains(dict_arr[j], name)) { + contains_name = true; + break; + } + } + + if (contains_name == false) { + fprintf(stderr, "\tBPY_driver_eval() - restructed access disallows name '%s', " + "enable auto-execution to support\n", _PyUnicode_AsString(name)); + return false; + } + } + } + + /* Check opcodes. */ + { + const char *codestr; + Py_ssize_t code_len; + + PyBytes_AsStringAndSize(py_code->co_code, (char **)&codestr, &code_len); + +#define CODESIZE(op) (HAS_ARG(op) ? 3 : 1) + + for (Py_ssize_t i = 0; i < code_len; i += CODESIZE(codestr[i])) { + const int opcode = codestr[i]; + if (secure_opcodes[opcode] == 0) { + fprintf(stderr, "\tBPY_driver_eval() - restructed access disallows opcode '%d', " + "enable auto-execution to support\n", opcode); + return false; + } + } + +#undef CODESIZE + } + + return true; +} + +#endif /* USE_BYTECODE_WHITELIST */ + + /* This evals py driver expressions, 'expr' is a Python expression that * should evaluate to a float number, which is returned. * @@ -217,6 +404,7 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, c if (expr[0] == '\0') return 0.0f; +#ifndef USE_BYTECODE_WHITELIST if (!(G.f & G_SCRIPT_AUTOEXEC)) { if (!(G.f & G_SCRIPT_AUTOEXEC_FAIL_QUIET)) { G.f |= G_SCRIPT_AUTOEXEC_FAIL; @@ -226,6 +414,9 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, c } return 0.0f; } +#else + bool is_recompile = false; +#endif use_gil = true; /* !PyC_IsInterpreterActive(); */ @@ -269,6 +460,9 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, c driver->flag &= ~DRIVER_FLAG_RECOMPILE; driver->flag |= DRIVER_FLAG_RENAMEVAR; /* maybe this can be removed but for now best keep until were sure */ +#ifdef USE_BYTECODE_WHITELIST + is_recompile = true; +#endif } else { expr_code = PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 0); @@ -350,6 +544,24 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, c } } +#ifdef USE_BYTECODE_WHITELIST + if (is_recompile) { + if (!(G.f & G_SCRIPT_AUTOEXEC)) { + if (!bpy_driver_secure_bytecode_validate( + expr_code, (PyObject *[]){ + bpy_pydriver_Dict, + bpy_pydriver_Dict__whitelist, + driver_vars, + NULL,} + )) + { + Py_DECREF(expr_code); + expr_code = NULL; + PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 0, NULL); + } + } + } +#endif /* USE_BYTECODE_WHITELIST */ #if 0 /* slow, with this can avoid all Py_CompileString above. */ /* execute expression to get a value */ From e7a68ef84360251bafe2f859aeba6517f9e1f81e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 17 Jun 2018 20:15:24 +0200 Subject: [PATCH 2/3] Cleanup: trailing space in CMake files --- CMakeLists.txt | 4 ++-- extern/recastnavigation/CMakeLists.txt | 4 ++-- intern/audaspace/CMakeLists.txt | 2 +- intern/cycles/blender/CMakeLists.txt | 2 +- intern/cycles/kernel/shaders/CMakeLists.txt | 2 +- intern/dualcon/CMakeLists.txt | 2 +- intern/mikktspace/CMakeLists.txt | 2 +- intern/rigidbody/CMakeLists.txt | 2 +- release/windows/blendthumb/CMakeLists.txt | 17 +++++++++-------- 9 files changed, 19 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cfeaaa1be1..603eb38f92e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -873,11 +873,11 @@ if (NOT CMAKE_BUILD_TYPE MATCHES "Release") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMPILER_ASAN_CXXFLAGS}") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${COMPILER_ASAN_CXXFLAGS}") if(MSVC) - set(COMPILER_ASAN_LINKER_FLAGS "/FUNCTIONPADMIN:6") + set(COMPILER_ASAN_LINKER_FLAGS "/FUNCTIONPADMIN:6") endif() set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS};${COMPILER_ASAN_LIBRARY}") set(PLATFORM_LINKFLAGS "${COMPILER_ASAN_LIBRARY} ${COMPILER_ASAN_LINKER_FLAGS}") - set(PLATFORM_LINKFLAGS_DEBUG "${COMPILER_ASAN_LIBRARY} ${COMPILER_ASAN_LINKER_FLAGS}") + set(PLATFORM_LINKFLAGS_DEBUG "${COMPILER_ASAN_LIBRARY} ${COMPILER_ASAN_LINKER_FLAGS}") endif() endif() diff --git a/extern/recastnavigation/CMakeLists.txt b/extern/recastnavigation/CMakeLists.txt index 19ac6e9dde8..15092631737 100644 --- a/extern/recastnavigation/CMakeLists.txt +++ b/extern/recastnavigation/CMakeLists.txt @@ -25,7 +25,7 @@ remove_cc_flag_unsigned_char() -set(INC +set(INC Recast/Include Detour/Include ) @@ -34,7 +34,7 @@ set(INC_SYS ) -set(SRC +set(SRC recast-capi.cpp recast-capi.h diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt index dd446613fd0..e3c1e81dc06 100644 --- a/intern/audaspace/CMakeLists.txt +++ b/intern/audaspace/CMakeLists.txt @@ -294,7 +294,7 @@ if(WITH_JACK) jack/AUD_JackDevice.h jack/AUD_JackLibrary.h - ) + ) if(WITH_JACK_DYNLOAD) add_definitions(-DWITH_JACK_DYNLOAD) diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt index ae4977aaed0..77c72777aa6 100644 --- a/intern/cycles/blender/CMakeLists.txt +++ b/intern/cycles/blender/CMakeLists.txt @@ -39,7 +39,7 @@ set(SRC set(ADDON_FILES addon/__init__.py - addon/engine.py + addon/engine.py addon/osl.py addon/presets.py addon/properties.py diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt index b28d017c1c2..40720bc3682 100644 --- a/intern/cycles/kernel/shaders/CMakeLists.txt +++ b/intern/cycles/kernel/shaders/CMakeLists.txt @@ -110,7 +110,7 @@ foreach(_file ${SRC_OSL}) string(REPLACE ".osl" ".oso" _OSO_FILE ${_OSL_FILE}) string(REPLACE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} _OSO_FILE ${_OSO_FILE}) add_custom_command( - OUTPUT ${_OSO_FILE} + OUTPUT ${_OSO_FILE} COMMAND ${OSL_COMPILER} -q -O2 -I"${CMAKE_CURRENT_SOURCE_DIR}" -o ${_OSO_FILE} ${_OSL_FILE} DEPENDS ${_OSL_FILE} ${SRC_OSL_HEADERS} ${OSL_COMPILER}) list(APPEND SRC_OSO diff --git a/intern/dualcon/CMakeLists.txt b/intern/dualcon/CMakeLists.txt index 40c8ef8ff9c..213379e852e 100644 --- a/intern/dualcon/CMakeLists.txt +++ b/intern/dualcon/CMakeLists.txt @@ -30,7 +30,7 @@ set(SRC intern/marching_cubes_table.cpp intern/octree.cpp intern/Projections.cpp - + intern/cubes.h intern/GeoCommon.h intern/manifold_table.h diff --git a/intern/mikktspace/CMakeLists.txt b/intern/mikktspace/CMakeLists.txt index 8abd9559358..299ec7fe501 100644 --- a/intern/mikktspace/CMakeLists.txt +++ b/intern/mikktspace/CMakeLists.txt @@ -35,7 +35,7 @@ set(INC ) set(INC_SYS - + ) set(SRC diff --git a/intern/rigidbody/CMakeLists.txt b/intern/rigidbody/CMakeLists.txt index 5d84c2cf082..91fe1023b5e 100644 --- a/intern/rigidbody/CMakeLists.txt +++ b/intern/rigidbody/CMakeLists.txt @@ -31,7 +31,7 @@ set(INC_SYS set(SRC rb_bullet_api.cpp - + RBI_api.h ) diff --git a/release/windows/blendthumb/CMakeLists.txt b/release/windows/blendthumb/CMakeLists.txt index 1e5f5131a36..f0da43c2614 100644 --- a/release/windows/blendthumb/CMakeLists.txt +++ b/release/windows/blendthumb/CMakeLists.txt @@ -26,17 +26,18 @@ #----------------------------------------------------------------------------- cmake_minimum_required(VERSION 2.8) project(BlendThumb) - + #Bring the headers, such as Student.h into the project include_directories(${ZLIB_INCLUDE}) - + #Can manually add the sources using the set command as follows: -set(SOURCES src/BlenderThumb.cpp - src/BlendThumb.def - src/BlendThumb.rc - src/Dll.cpp +set(SRC + src/BlenderThumb.cpp + src/BlendThumb.def + src/BlendThumb.rc + src/Dll.cpp ) - -add_library(BlendThumb SHARED ${SOURCES}) + +add_library(BlendThumb SHARED ${SRC}) target_link_libraries(BlendThumb ${ZLIB_LIBS}) install (TARGETS BlendThumb DESTINATION bin) From 86e20a2e63ea7c4810782942d5a3505f21718068 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 17 Jun 2018 20:18:09 +0200 Subject: [PATCH 3/3] Cleanup: trailing space cmake, make.bat --- .../patches/cmake/modules/FindIlmBase.cmake | 4 ++-- .../patches/cmake/modules/FindOpenEXR.cmake | 2 +- .../modules/SelectLibraryConfigurations.cmake | 10 +++++----- make.bat | 18 +++++++++--------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/build_files/build_environment/patches/cmake/modules/FindIlmBase.cmake b/build_files/build_environment/patches/cmake/modules/FindIlmBase.cmake index de4c0aba48c..10075d71484 100644 --- a/build_files/build_environment/patches/cmake/modules/FindIlmBase.cmake +++ b/build_files/build_environment/patches/cmake/modules/FindIlmBase.cmake @@ -75,7 +75,7 @@ macro(PREFIX_FIND_LIB prefix libname libpath_var liblist_var cachelist_var) # Handle new library names for OpenEXR 2.1 build via cmake string(REPLACE "." "_" _ILMBASE_VERSION ${ILMBASE_VERSION}) string(SUBSTRING ${_ILMBASE_VERSION} 0 3 _ILMBASE_VERSION ) - + find_library(${tmp_prefix}_LIBRARY_RELEASE NAMES ${libname} ${libname}-${_ILMBASE_VERSION} HINTS ${${libpath_var}} @@ -177,7 +177,7 @@ if(ILMBASE_INCLUDE_DIR) "\\1" XYZ ${ILMBASE_BUILD_SPECIFICATION}) set("ILMBASE_VERSION" ${XYZ} CACHE STRING "Version of ILMBase lib") else() - # Old versions (before 2.0?) do not have any version string, just assuming 2.0 should be fine though. + # Old versions (before 2.0?) do not have any version string, just assuming 2.0 should be fine though. message(WARNING "Could not determine ILMBase library version, assuming 2.0.") set("ILMBASE_VERSION" "2.0" CACHE STRING "Version of ILMBase lib") endif() diff --git a/build_files/build_environment/patches/cmake/modules/FindOpenEXR.cmake b/build_files/build_environment/patches/cmake/modules/FindOpenEXR.cmake index 1eb4ea3f5e7..96a2ca94bab 100644 --- a/build_files/build_environment/patches/cmake/modules/FindOpenEXR.cmake +++ b/build_files/build_environment/patches/cmake/modules/FindOpenEXR.cmake @@ -175,7 +175,7 @@ if(OPENEXR_INCLUDE_DIR) "\\1" XYZ ${OPENEXR_BUILD_SPECIFICATION}) set("OPENEXR_VERSION" ${XYZ} CACHE STRING "Version of OpenEXR lib") else() - # Old versions (before 2.0?) do not have any version string, just assuming 2.0 should be fine though. + # Old versions (before 2.0?) do not have any version string, just assuming 2.0 should be fine though. message(WARNING "Could not determine ILMBase library version, assuming 2.0.") set("OPENEXR_VERSION" "2.0" CACHE STRING "Version of OpenEXR lib") endif() diff --git a/build_files/build_environment/patches/cmake/modules/SelectLibraryConfigurations.cmake b/build_files/build_environment/patches/cmake/modules/SelectLibraryConfigurations.cmake index 47234ced74a..796be8db87d 100644 --- a/build_files/build_environment/patches/cmake/modules/SelectLibraryConfigurations.cmake +++ b/build_files/build_environment/patches/cmake/modules/SelectLibraryConfigurations.cmake @@ -6,7 +6,7 @@ # basename_LIBRARY_RELEASE is defined, basename_LIBRARY, basename_LIBRARY_DEBUG, # and basename_LIBRARY_RELEASE will be set to the release value. If only # basename_LIBRARY_DEBUG is defined, then basename_LIBRARY, -# basename_LIBRARY_DEBUG and basename_LIBRARY_RELEASE will take the debug value. +# basename_LIBRARY_DEBUG and basename_LIBRARY_RELEASE will take the debug value. # # If the generator supports configuration types, then basename_LIBRARY and # basename_LIBRARIES will be set with debug and optimized flags specifying the @@ -53,10 +53,10 @@ macro( select_library_configurations basename ) # if the generator supports configuration types or CMAKE_BUILD_TYPE # is set, then set optimized and debug options. if( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE ) - set( ${basename}_LIBRARY + set( ${basename}_LIBRARY optimized ${${basename}_LIBRARY_RELEASE} debug ${${basename}_LIBRARY_DEBUG} ) - set( ${basename}_LIBRARIES + set( ${basename}_LIBRARIES optimized ${${basename}_LIBRARY_RELEASE} debug ${${basename}_LIBRARY_DEBUG} ) else( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE ) @@ -67,14 +67,14 @@ macro( select_library_configurations basename ) endif( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE ) endif( ${basename}_LIBRARY_DEBUG AND ${basename}_LIBRARY_RELEASE ) - set( ${basename}_LIBRARY ${${basename}_LIBRARY} CACHE FILEPATH + set( ${basename}_LIBRARY ${${basename}_LIBRARY} CACHE FILEPATH "The ${basename} library" ) if( ${basename}_LIBRARY ) set( ${basename}_FOUND TRUE ) endif( ${basename}_LIBRARY ) - mark_as_advanced( ${basename}_LIBRARY + mark_as_advanced( ${basename}_LIBRARY ${basename}_LIBRARY_RELEASE ${basename}_LIBRARY_DEBUG ) diff --git a/make.bat b/make.bat index 18e861f8fdb..5fb428fbed0 100644 --- a/make.bat +++ b/make.bat @@ -31,7 +31,7 @@ if "%BUILD_UPDATE%" == "1" ( goto EOF ) -call "%BLENDER_DIR%\build_files\windows\detect_architecture.cmd" +call "%BLENDER_DIR%\build_files\windows\detect_architecture.cmd" if "%BUILD_VS_YEAR%" == "" ( call "%BLENDER_DIR%\build_files\windows\autodetect_msvc.cmd" @@ -47,28 +47,28 @@ if "%BUILD_VS_YEAR%" == "" ( ) ) -call "%BLENDER_DIR%\build_files\windows\set_build_dir.cmd" +call "%BLENDER_DIR%\build_files\windows\set_build_dir.cmd" echo Building blender with VS%BUILD_VS_YEAR% for %BUILD_ARCH% in %BUILD_DIR% -call "%BLENDER_DIR%\build_files\windows\check_libraries.cmd" +call "%BLENDER_DIR%\build_files\windows\check_libraries.cmd" if errorlevel 1 goto EOF -call "%BLENDER_DIR%\build_files\windows\check_submodules.cmd" +call "%BLENDER_DIR%\build_files\windows\check_submodules.cmd" if errorlevel 1 goto EOF if "%BUILD_WITH_NINJA%" == "" ( - call "%BLENDER_DIR%\build_files\windows\configure_msbuild.cmd" + call "%BLENDER_DIR%\build_files\windows\configure_msbuild.cmd" if errorlevel 1 goto EOF - call "%BLENDER_DIR%\build_files\windows\build_msbuild.cmd" + call "%BLENDER_DIR%\build_files\windows\build_msbuild.cmd" if errorlevel 1 goto EOF ) else ( - call "%BLENDER_DIR%\build_files\windows\configure_ninja.cmd" + call "%BLENDER_DIR%\build_files\windows\configure_ninja.cmd" if errorlevel 1 goto EOF - call "%BLENDER_DIR%\build_files\windows\build_ninja.cmd" + call "%BLENDER_DIR%\build_files\windows\build_ninja.cmd" if errorlevel 1 goto EOF ) -:EOF \ No newline at end of file +:EOF