Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Sun, 17 Jun 2018 18:37:10 +0000 (20:37 +0200)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 17 Jun 2018 18:37:10 +0000 (20:37 +0200)
13 files changed:
CMakeLists.txt
build_files/build_environment/patches/cmake/modules/FindIlmBase.cmake
build_files/build_environment/patches/cmake/modules/FindOpenEXR.cmake
build_files/build_environment/patches/cmake/modules/SelectLibraryConfigurations.cmake
intern/cycles/blender/CMakeLists.txt
intern/cycles/kernel/shaders/CMakeLists.txt
intern/dualcon/CMakeLists.txt
intern/mikktspace/CMakeLists.txt
intern/rigidbody/CMakeLists.txt
make.bat
release/windows/blendthumb/CMakeLists.txt
source/blender/editors/space_graph/graph_buttons.c
source/blender/python/intern/bpy_driver.c

index 4da0f70884ab23e7f3125f172b5bb5b7b2c3a65e..06d31e0e143778b54743800218d8d7454ac7f3c1 100644 (file)
@@ -826,11 +826,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()
 
index de4c0aba48c8ed7126b6217bb268a6d9fd677183..10075d71484452a6fc0c0f699b42e98ab950112a 100644 (file)
@@ -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()
index 1eb4ea3f5e7be2a1df8d6cdb5c32e41caad0ed57..96a2ca94babcd234c08dec734a6dd3ee34df3d7a 100644 (file)
@@ -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()
index 47234ced74a43ce0710bc6ae631b1d06d978b8c4..796be8db87d7d277ac3f027816f7cf97ccdcc022 100644 (file)
@@ -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
     )
index ae4977aaed0369960671784c27792fe854dfd8d8..77c72777aa681624ee02838e5f48e27b74c3665e 100644 (file)
@@ -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
index b28d017c1c25a2c3aa615f832bb68e600ae66736..40720bc36829a29a72d6ee7a3df84d13611e1e04 100644 (file)
@@ -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
index 40c8ef8ff9c57bccf5e5566860e1a31d5d719b8c..213379e852e76241a5fa86d00edb62c48939a8c6 100644 (file)
@@ -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
index 8abd9559358c0b294cab8cc33b3fffe2697db9d7..299ec7fe5013131433f421ffb546384c25782058 100644 (file)
@@ -35,7 +35,7 @@ set(INC
 )
 
 set(INC_SYS
-       
+
 )
 
 set(SRC
index 5d84c2cf082046123c3ee94d1294f9fe5decbe3a..91fe1023b5e5be2352d1bbac247f4d19170656e2 100644 (file)
@@ -31,7 +31,7 @@ set(INC_SYS
 
 set(SRC
        rb_bullet_api.cpp
-       
+
        RBI_api.h
 )
 
index 227b8f8205b386e87288dbfba916809bf510f831..5fb428fbed034709df994aada23e7abd61855c3a 100644 (file)
--- 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,27 +47,27 @@ 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
 )
 
index 1e5f5131a36ca091fede64fba84b180f429028c1..f0da43c26141f367fa823a1ffa5a35b6b190e6bc 100644 (file)
 #-----------------------------------------------------------------------------
 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)
index 263b68a212464d8053cee3934820309d52bac4a9..2a0d5baa5c32c6c6a4d773c611e2a27e1a3dc54f 100644 (file)
@@ -801,7 +801,7 @@ static void graph_draw_driver_settings_panel(uiLayout *layout, ID *id, FCurve *f
 
                if ((G.f & G_SCRIPT_AUTOEXEC) == 0) {
                        /* TODO: Add button to enable? */
-                       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);
index 96bfa9f26d35c2c70e73de07f3c7a26f45922850..fd405e9f14bff350c3c992f528b8d9aadf5dba88 100644 (file)
@@ -54,9 +54,19 @@ extern void BPY_update_rna_module(void);
 
 #define USE_RNA_AS_PYOBJECT
 
+#define USE_BYTECODE_WHITELIST
+
+#ifdef USE_BYTECODE_WHITELIST
+#  include <opcode.h>
+#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.
  */
@@ -81,6 +91,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);
@@ -97,6 +110,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;
 }
 
@@ -165,6 +220,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 */
@@ -187,6 +250,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.
  *
@@ -223,6 +410,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;
@@ -232,6 +420,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(); */
 
@@ -275,6 +466,9 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, C
 
                driver_orig->flag &= ~DRIVER_FLAG_RECOMPILE;
                driver_orig->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_orig->expr_comp), 0);
@@ -356,6 +550,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 */