Yet another attempt at a safe eval() call

matt.newville at gmail.com matt.newville at gmail.com
Sat Jan 5 11:40:34 EST 2013


On Saturday, January 5, 2013 8:17:16 AM UTC-8, Oscar Benjamin wrote:
> On 5 January 2013 16:01, Chris Angelico <rosuav at gmail.com> wrote:
> 
> > On Sun, Jan 6, 2013 at 2:56 AM, Oscar Benjamin
> 
> > <oscar.j.benjamin at gmail.com> wrote:
> 
> >> On 4 January 2013 15:53, Grant Edwards <invalid at invalid.invalid> wrote:
> 
> >>> On 2013-01-04, Steven D'Aprano <steve+comp.lang.python at pearwood.info> wrote:
> 
> >>>> On Thu, 03 Jan 2013 23:25:51 +0000, Grant Edwards wrote:
> 
> >>>>
> 
> >>>> * But frankly, you should avoid eval, and write your own mini-integer
> 
> >>>>   arithmetic evaluator which avoids even the most remote possibility
> 
> >>>>   of exploit.
> 
> >>>
> 
> >>> That's obviously the "right" thing to do.  I suppose I should figure
> 
> >>> out how to use the ast module.
> 
> >>
> 
> >> Someone has already created a module that does this called numexpr. Is
> 
> >> there some reason why you don't want to use that?
> 
> >>
> 
> >>>>> import numexpr
> 
> >>>>> numexpr.evaluate('2+4*5')
> 
> >> array(22, dtype=int32)
> 
> >>>>> numexpr.evaluate('2+a*5', {'a':4})
> 
> >> array(22L)
> 
> >
> 
> > Is that from PyPI? It's not in my Python 3.3 installation. Obvious
> 
> > reason not to use it: Unaware of it. :)
> 
> 
> 
> My apologies. I should have at least provided a link:
> 
> http://code.google.com/p/numexpr/
> 
> 
> 
> I installed it from the ubuntu repo under the name python-numexpr. It
> 
> is also on PyPI:
> 
> http://pypi.python.org/pypi/numexpr
> 
> 
> 
> numexpr is a well established project intended primarily for memory
> 
> and cache efficient computations over large arrays of data. Possibly
> 
> as a side effect, it can also be used to evaluate simple algebraic
> 
> expressions involving ordinary scalar variables.
> 
> 
> 
> 
> 
> Oscar

The asteval module http://pypi.python.org/pypi/asteval/0.9 and
http://newville.github.com/asteval/  might be another alternative.  It's not as fast as numexpr, but a bit more general. It uses the ast module to "compile" an expression into the AST, then walks through that, intercepting Name nodes and using a flat namespace of variables.  It disallows imports and does not support all python constructs, but it is a fairly complete in supporting python syntax.

It makes no claim at actually being safe from malicious attack, but should be safer than a straight eval(), and prevent accidental problems when evaluating user-input as code.  If anyone can find exploits within it, I'd be happy to try to fix them.

--Matt



More information about the Python-list mailing list