Changeset 619 for branches


Ignore:
Timestamp:
12/20/12 11:54:42 (3 years ago)
Author:
mmckerns
Message:

enable use of locals in build_constraint; make use of exec more secure

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/decorate/_symbolic.py

    r618 r619  
    240240        >>> print simplify_symbolic(equation, target='x2') 
    241241        x2 = 3.0 + x1*x3 
    242 """ 
     242""" #XXX: an expanded version of this code is found in build_constraints XXX# 
    243243    # for now, we abort on multi-line equations or inequalities 
    244244    if len(constraint.replace('==','=').split('=')) != 2: 
     
    262262 
    263263    warn = True  # if True, don't supress warnings 
     264    verbose = False  # if True, print debug info 
    264265    if kwds.has_key('warn'): warn = kwds['warn'] 
    265     locals = kwds.get('locals', None) 
     266    if kwds.has_key('verbose'): verbose = kwds['verbose'] 
    266267 
    267268    # default is _locals with sympy imported 
    268269    _locals = {} 
     270    locals = kwds.get('locals', None) 
     271    if locals is None: locals = {} 
    269272    try: 
    270273        code = """from sympy import Eq, Symbol;""" 
     
    284287    code = compile(code, '<string>', 'exec') 
    285288    exec code in _locals 
    286     if locals is None: locals = {} 
    287289    _locals.update(locals) #XXX: allow this? 
    288290 
    289291    code,left,right,xlist,neqns = _prepare_sympy(constraints, varname, ndim) 
    290292 
    291     code += 'eq = Eq(' + left[0] + ',' + right[0] + ')\n'  
     293    eqlist = "" 
     294    for i in range(1, neqns+1): 
     295        eqn = 'eq' + str(i) 
     296        eqlist += eqn + "," 
     297        code += eqn + '= Eq(' + left[i-1] + ',' + right[i-1] + ')\n' 
     298    eqlist = eqlist.rstrip(',') 
    292299 
    293300    if not target: #XXX: the goal is solving *only one* equation 
    294        #code += 'soln = symsol(eq, [' + xlist + '])\n' 
     301       #code += 'soln = symsol([' + eqlist + '], [' + xlist + '])\n' 
    295302        code += '_xlist = %s\n' % xlist 
    296303        code += 'soln = {}\n' 
    297         code += '[soln.update({i:symsol(eq, i)}) for i in _xlist]\n' 
    298     else: 
    299         code += 'soln = symsol(eq, [' + target + '])\n' 
     304        code += '[soln.update({i:symsol('+eqlist+', i)}) for i in _xlist]\n' 
     305    else: 
     306        code += 'soln = symsol(' + eqlist + ', [' + target + '])\n' 
     307    if verbose: print code 
    300308    code = compile(code, '<string>', 'exec') 
    301309    try:  
     
    308316        if warn: print "Warning:", error 
    309317        return None 
     318    if verbose: print soln 
    310319 
    311320    #XXX Not the best way to handle multiple solutions? 
     
    437446    # >>> soln = symsol([eq2, eq1], [x1, x2, x3]) 
    438447 
    439     # If no Sympy installed, just call generate_constraint 
     448    # default is _locals with sympy imported 
     449    _locals = {} 
     450    locals = kwds.get('locals', None) 
     451    if locals is None: locals = {} 
     452    # if sympy not installed, call generate_constraint 
    440453    try: 
    441         from sympy import Eq, Symbol 
    442         from sympy import solve as symsol 
     454        code = """from sympy import Eq, Symbol;""" 
     455        code += """from sympy import solve as symsol;""" 
     456        code = compile(code, '<string>', 'exec') 
     457        exec code in _locals 
    443458    except ImportError: # Equation will not be simplified." 
    444459        if warn: print "Warning: sympy not installed." 
    445         solv = generate_solvers(constraints, variables=varname) 
     460        solv = generate_solvers(constraints, variables=varname, locals=locals) 
    446461        return generate_constraint(solv) 
    447462 
    448     code, left, right, xlist, neqns = _prepare_sympy(constraints, varname, ndim) 
     463    # default is _locals with numpy and math imported 
     464    # numpy throws an 'AttributeError', but math passes error to sympy 
     465    code = """from numpy import *; from math import *;""" # prefer math 
     466    code += """from numpy import mean as average;""" # use np.mean not average 
     467    code += """from numpy import var as variance;""" # look like mystic.math 
     468    code += """from numpy import ptp as spread;"""   # look like mystic.math 
     469    code = compile(code, '<string>', 'exec') 
     470    exec code in _locals 
     471    _locals.update(locals) #XXX: allow this? 
     472 
     473    code,left,right,xlist,neqns = _prepare_sympy(constraints, varname, ndim) 
    449474 
    450475    eqlist = "" 
    451     for i in range(1, neqns + 1): 
     476    for i in range(1, neqns+1): 
    452477        eqn = 'eq' + str(i) 
    453478        eqlist += eqn + "," 
    454479        code += eqn + '= Eq(' + left[i-1] + ',' + right[i-1] + ')\n' 
     480    eqlist = eqlist.rstrip(',') 
    455481 
    456482    # Figure out if trying various permutations is necessary 
     
    480506            for item in perm: 
    481507                xstring += item + "," 
    482             tempcode += 'soln = symsol([' + eqlist.rstrip(',') + '], [' + \ 
    483                         xstring.rstrip(',') + '])' 
     508            xstring = xstring.rstrip(',') 
     509            tempcode += 'soln = symsol([' + eqlist + '], [' + xstring + '])' 
    484510            if verbose: print tempcode 
    485             exec tempcode in globals(), locals() #FIXME: insecure 
    486  
    487             if soln == None and warn: 
    488                 print "Warning: sympy could not simplify equation." 
     511 
     512            tempcode = compile(tempcode, '<string>', 'exec') 
     513            try:  
     514                exec tempcode in globals(), _locals 
     515                soln = _locals['soln'] 
     516                if soln == None and warn: 
     517                    print "Warning: sympy could not simplify equation." 
     518            except NotImplementedError: # catch 'multivariate' error 
     519                if warn: print "Warning: sympy could not simplify equation." 
     520                soln = None 
     521            except NameError, error: # catch when variable is not defined 
     522                if warn: print "Warning:", error 
     523                soln = None 
     524            if verbose: print soln 
    489525 
    490526            solvedstring = "" 
     
    509545        # constraints functions. Check if constraints(guess) is in the bounds. 
    510546        for string in stringperms: 
    511             solv = generate_solvers(string, variables=varname) 
     547            solv = generate_solvers(string, variables=varname, locals=locals) 
    512548            cf = generate_constraint(solv) 
    513549#           if guess: compatible = isbounded(cf, guess, min=lower_bounds, \ 
     
    534570        # Just form code and get whatever solution sympy comes up with. 
    535571        if targets: 
    536             xlist = ','.join(targets) 
    537         code += 'soln = symsol([' + eqlist.rstrip(',') + '], [' + xlist.rstrip(',') + '])' 
    538         exec code in globals(), locals() #FIXME: insecure 
    539         if soln == None and warn: 
    540             print "Warning: sympy could not simplify equation." 
     572            xlist = ','.join(targets).rstrip(',') 
     573        code += 'soln = symsol([' + eqlist + '], [' + xlist + '])' 
     574        if verbose: print code 
     575        code = compile(code, '<string>', 'exec') 
     576        try:  
     577            exec code in globals(), _locals 
     578            soln = _locals['soln'] 
     579            if soln == None and warn: 
     580                print "Warning: sympy could not simplify equation." 
     581        except NotImplementedError: # catch 'multivariate' error 
     582            if warn: print "Warning: sympy could not simplify equation." 
     583            soln = None 
     584        except NameError, error: # catch when variable is not defined 
     585            if warn: print "Warning:", error 
     586            soln = None 
     587        if verbose: print soln 
    541588 
    542589        solvedstring = "" 
     
    544591            solvedstring += str(key) + ' = ' + str(value) + '\n' 
    545592 
    546         solv = generate_solvers(solvedstring, variables=varname) 
     593        solv = generate_solvers(solvedstring, variables=varname, locals=locals) 
    547594        cf = generate_constraint(solv) 
    548595        if verbose: 
     
    700747#   elif lower_bounds: ndim = len(lower_bounds) 
    701748#   elif upper_bounds: ndim = len(upper_bounds) 
     749 
     750    locals = kwds.get('locals', None) 
     751    if locals is None: locals = {} 
    702752 
    703753    # Figure out if trying various permutations is necessary 
     
    783833            simplified.append(simplify_symbolic(eqn, variables=varname, target=target, warn=warn)) 
    784834 
    785         solv = generate_solvers('\n'.join(simplified), variables=varname) 
     835        solv = generate_solvers('\n'.join(simplified), variables=varname, locals=locals) 
    786836        cf = generate_constraint(solv) 
    787837 
Note: See TracChangeset for help on using the changeset viewer.