[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [4720] trunk/py/scripts/addons/ io_import_scene_mhx.py: Replaced eval with a custom eval for improved security.

Thomas Larsson thomas_larsson_01 at hotmail.com
Sun Sep 1 05:32:22 CEST 2013


Revision: 4720
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=4720
Author:   thomasl
Date:     2013-09-01 03:32:21 +0000 (Sun, 01 Sep 2013)
Log Message:
-----------
Replaced eval with a custom eval for improved security.

Modified Paths:
--------------
    trunk/py/scripts/addons/io_import_scene_mhx.py

Modified: trunk/py/scripts/addons/io_import_scene_mhx.py
===================================================================
--- trunk/py/scripts/addons/io_import_scene_mhx.py	2013-08-31 20:20:54 UTC (rev 4719)
+++ trunk/py/scripts/addons/io_import_scene_mhx.py	2013-09-01 03:32:21 UTC (rev 4720)
@@ -38,7 +38,7 @@
 bl_info = {
     'name': 'Import: MakeHuman (.mhx)',
     'author': 'Thomas Larsson',
-    'version': (1, 16, 4),
+    'version': (1, 16, 5),
     "blender": (2, 68, 0),
     'location': "File > Import > MakeHuman (.mhx)",
     'description': 'Import files in the MakeHuman eXchange format (.mhx)',
@@ -51,7 +51,7 @@
 MAJOR_VERSION = 1
 MINOR_VERSION = 16
 FROM_VERSION = 13
-SUB_VERSION = 3
+SUB_VERSION = 5
 
 majorVersion = MAJOR_VERSION
 minorVersion = MINOR_VERSION
@@ -123,8 +123,40 @@
 
 toggle = DefaultToggle
 toggleSettings = toggle
+loadedData = None
 
 #
+#   mhxEval(expr) - an attempt at a reasonably safe mhxEval.
+#   Note that expr never contains any whitespace due to the behavior
+#   of the mhx tokenizer.
+#
+
+def mhxEval(expr, locls={}):
+    globls = {
+        '__builtins__' : {},
+        'toggle' : toggle,
+        'theScale' : theScale,
+        'T_EnforceVersion' : T_EnforceVersion,
+        'T_Clothes' : T_Clothes,
+        'T_HardParents' : T_HardParents,
+        'T_CrashSafe' : T_CrashSafe,
+        'T_Diamond' : T_Diamond,
+        'T_Replace' : T_Replace,
+        'T_Shapekeys' : T_Shapekeys,
+        'T_ShapeDrivers' : T_ShapeDrivers,
+        'T_Face' : T_Face,
+        'T_Shape' : T_Shape,
+        'T_Mesh' : T_Mesh,
+        'T_Armature' : T_Armature,
+        'T_Proxy' : T_Proxy,
+        'T_Cage' : T_Cage,
+        'T_Rigify' : T_Rigify,
+        'T_Opcns' : T_Opcns,
+        'T_Symm' : T_Symm,
+    }
+    return eval(expr, globls, locls)
+
+#
 #    Dictionaries
 #
 
@@ -244,7 +276,7 @@
             if lineSplit[0] == '#if':
                 if comment == nesting:
                     try:
-                        res = eval(lineSplit[1])
+                        res = mhxEval(lineSplit[1])
                     except:
                         res = False
                     if res:
@@ -297,6 +329,7 @@
     bpy.ops.object.mode_set(mode='OBJECT')
     bpy.ops.object.select_all(action='DESELECT')
     theArmature.select = True
+    bpy.ops.object.mode_set(mode='POSE')
     theArmature.MhAlpha8 = not alpha7
     #bpy.ops.wm.properties_edit(data_path="object", property="MhxRig", value=theArmature["MhxRig"])
 
@@ -313,12 +346,9 @@
 
 def getObject(name, var):
     try:
-        ob = loadedData['Object'][name]
+        return loadedData['Object'][name]
     except:
-        if name != "None":
-            pushOnTodoList(None, "ob = loadedData['Object'][name]" % globals(), locals())
-        ob = None
-    return ob
+        raise MhxError("Bug: object %s not found" % ob)
 
 #
 #    checkMhxVersion(major, minor):
@@ -372,7 +402,7 @@
             minorVersion = int(val[1])
             checkMhxVersion(majorVersion, minorVersion)
         elif key == 'MHX249':
-            MHX249 = eval(val[0])
+            MHX249 = mhxEval(val[0])
             print("Blender 2.49 compatibility mode is %s\n" % MHX249)
         elif MHX249:
             pass
@@ -386,7 +416,7 @@
             msg = concatList(val)
             MyError(msg)
         elif key == 'NoScale':
-            if eval(val[0]):
+            if mhxEval(val[0]):
                 theScale = 1.0
             else:
                 theScale = defaultScale
@@ -470,7 +500,7 @@
     name = args[0]
     data = None
     expr = "bpy.data.%s.new('%s')" % (Plural[typ], name)
-    data = eval(expr)
+    data = mhxEval(expr)
 
     bpyType = typ.capitalize()
     loadedData[bpyType][name] = data
@@ -546,7 +576,7 @@
             times.append(int(val[0]))
 
     try:
-        data = eval(expr)
+        data = mhxEval(expr)
     except:
         print("Ignoring illegal expression: %s" % expr)
         return
@@ -628,7 +658,7 @@
 #
 
 def parseAnimationData(rna, args, tokens):
-    if not eval(args[1]):
+    if not mhxEval(args[1]):
         return
     if rna.animation_data is None:
         rna.animation_data_create()
@@ -673,7 +703,7 @@
         expr = "rna." + words[0] + ']'
         pwords = words[1].split('"')
         prop = pwords[1]
-        bone = eval(expr)
+        bone = mhxEval(expr)
         return None
     else:
         words = dataPath.split('.')
@@ -683,7 +713,7 @@
             expr += "." + words[n]
         expr += ".driver_add('%s', index)" % channel
 
-    fcu = eval(expr)
+    fcu = mhxEval(expr, locals())
     drv = fcu.driver
     drv.type = args[0]
     for (key, val, sub) in tokens:
@@ -822,8 +852,8 @@
     n = 0
     for (key, val, sub) in tokens:
         if key == 'Element':
-            elts[n].color = eval(val[0])
-            elts[n].position = eval(val[1])
+            elts[n].color = mhxEval(val[0], locals())
+            elts[n].position = mhxEval(val[1], locals())
             n += 1
         else:
             defaultKey(key, val, sub, tex, ['use_nodes', 'use_textures', 'contrast'])
@@ -1107,12 +1137,12 @@
     for (key, val, sub) in tokens:
         if key == 'h':
             h = par.hair[n]
-            h.location = eval(val[0])
+            h.location = mhxEval(val[0], locals())
             h.time = int(val[1])
             h.weight = float(val[2])
             n += 1
         elif key == 'location':
-            par.location = eval(val[0])
+            par.location = mhxEval(val[0], locals())
     return
 
 #
@@ -1374,10 +1404,10 @@
     n = 0
     for (key, val, sub) in tokens:
         if key == 'cv':
-            data[n].color1 = eval(val[0])
-            data[n].color2 = eval(val[1])
-            data[n].color3 = eval(val[2])
-            data[n].color4 = eval(val[3])
+            data[n].color1 = mhxEval(val[0])
+            data[n].color2 = mhxEval(val[1])
+            data[n].color3 = mhxEval(val[2])
+            data[n].color4 = mhxEval(val[3])
             n += 1
     return
 
@@ -1392,7 +1422,7 @@
         print( "Parsing vertgroup %s" % args )
     grpName = args[0]
     try:
-        res = eval(args[1])
+        res = mhxEval(args[1])
     except:
         res = True
     if not res:
@@ -1527,7 +1557,7 @@
             rolls = {}
             for bone in amt.edit_bones:
                 bone.select = False
-            blist = eval(val[0])
+            blist = mhxEval(val[0])
             for name in blist:
                 bone = amt.edit_bones[name]
                 bone.select = True
@@ -1582,7 +1612,7 @@
         elif key == 'SetProp':
             bone = val[0]
             prop = val[1]
-            value = eval(val[2])
+            value = mhxEval(val[2])
             pb = pbones[bone]
             pb[prop] = value
         else:
@@ -1635,7 +1665,7 @@
             parseArray(pb, ["ik_stiffness_x", "ik_stiffness_y", "ik_stiffness_z"], val)
         elif key == 'hide':
             #bpy.ops.object.mode_set(mode='OBJECT')
-            amt.bones[name].hide = eval(val[0])
+            amt.bones[name].hide = mhxEval(val[0])
             #bpy.ops.object.mode_set(mode='POSE')
 
         else:
@@ -1645,7 +1675,7 @@
 def parseArray(data, exts, args):
     n = 1
     for ext in exts:
-        setattr(data, ext, eval(args[n]))
+        setattr(data, ext, mhxEval(args[n]))
         n += 1
     return
 
@@ -1758,16 +1788,16 @@
     return
 
 def parseBezier(bez, args, tokens):
-    bez.co = eval(args[0])
+    bez.co = mhxEval(args[0])
     bez.co = theScale*bez.co
-    bez.handle1 = eval(args[1])
+    bez.handle1 = mhxEval(args[1])
     bez.handle1_type = args[2]
-    bez.handle2 = eval(args[3])
+    bez.handle2 = mhxEval(args[3])
     bez.handle2_type = args[4]
     return
 
 def parsePoint(pt, args, tokens):
-    pt.co = eval(args[0])
+    pt.co = mhxEval(args[0])
     pt.co = theScale*pt.co
     print(" pt", pt.co)
     return
@@ -2079,15 +2109,14 @@
 
 def defNewProp(name, proptype, rest):
     prop = "%sProperty(%s)" % (proptype, rest)
-    setattr(bpy.types.Object, name, eval(prop))
+    setattr(bpy.types.Object, name, mhxEval(prop))
 
 
 def setProperty(args, var):
     global theProperty
     tip = ""
     name = propNames(args[0])[0]
-    value = eval(args[1])
-    print("setProp", var, name, value)
+    value = mhxEval(args[1])
     if name:
         var[name] = value
         if len(args) > 2:
@@ -2114,7 +2143,6 @@
         prop = FloatProperty(tip)
     elif isinstance(value, string):
         prop = StringProperty(tip)
-    print("SetPK", theProperty, name, prop)
     setattr(bpy.types.Object, name, prop)
     theProperty = None
 
@@ -2134,27 +2162,23 @@
 
     if ext in exclude:
         return
-    #nvar = "%s.%s" % (var, ext)
     nvar = getattr(var, ext)
 
     if len(args) == 0:
         MyError("Key length 0: %s" % ext)
 
     rnaType = args[0]
-    if rnaType == 'Add':
-        print("*** Cannot Add yet ***")
-        return
-
-    elif rnaType == 'Refer':
+    if rnaType == 'Refer':
         typ = args[1]
         name = args[2]
-        data = "loadedData['%s']['%s']" % (typ, name)
+        setattr(var, ext, loadedData[typ][name])
+        return
 
     elif rnaType == 'Struct' or rnaType == 'Define':
+        raise MhxError("Struct/Define!")
         typ = args[1]
         name = args[2]
         try:
-            #data = eval(nvar)
             data = getattr(var, ext)
         except:
             data = None
@@ -2165,11 +2189,10 @@
                 creator = args[3]
             except:
                 creator = None
-            # print("Creator", creator, eval(var,glbals,lcals))
 
             try:
-                rna = eval(var,glbals,lcals)
-                data = eval(creator)
+                rna = mhxEval(var, locals())
+                data = mhxEval(creator)
             except:
                 data = None
             # print("New struct", nvar, typ, data)
@@ -2183,7 +2206,7 @@
         return
 
     elif rnaType == 'PropertyRNA':
-        MyError("PropertyRNA!")
+        raise MhxError("PropertyRNA!")
         #print("PropertyRNA ", ext, var)
         for (key, val, sub) in tokens:
             defaultKey(ext, val, sub, nvar, [])
@@ -2191,19 +2214,22 @@
 
     elif rnaType == 'Array':
         for n in range(1, len(args)):
-            nvar[n-1] = eval(args[n])
+            nvar[n-1] = mhxEval(args[n], locals())
         if len(args) > 0:
-            nvar[0] = eval(args[1])
+            nvar[0] = mhxEval(args[1], locals())
         return
 
     elif rnaType == 'List':
+        raise MhxError("List!")
         data = []

@@ Diff output truncated at 10240 characters. @@


More information about the Bf-extensions-cvs mailing list