limited python virtual machine (WAS: Another scripting language implemented into Python itself?)

Michael Spencer mahs at telcopartners.com
Tue Jan 25 15:51:25 EST 2005


Steven Bethard wrote:
> Michael Spencer wrote:
> 
>> Safe eval recipe posted to cookbook:
>> http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/364469
> 
> 
> This recipe only evaluates constant expressions:
> 
> "Description:
> Evaluate constant expressions, including list, dict and tuple using the 
> abstract syntax tree created by compiler.parse"
> 
> It means you can't eval arbitrary Python code -- it's basically just a 
> data parser.  Handy in some situations, but not the equivalent of a 
> limited Python virtual machine.

Indeed.  But it's easy to extend this to arbitrary constructs.  You just need to 
decide what code to emit for the other 50 or so ast node types.  Many of those 
are boiler-plate binops.
> 
>> Likewise, function calls are easily intercepted
> 
> I'm not sure I follow this...  How do you intend to intercept all 
> function calls?
Sorry, should have been more precise.  In the AST, Function calls have their own 
  node type, so it is easy to 'intercept' them and execute them conditionally
> 
[snip]
> 
> It sounds like you're suggesting overriding the global attribute access 
> mechanism.  Is that right?  So that every time Python encountered an 
> attribute access, you would verify that the attribute being accessed is 
> not on the 'dangerous' list?
Just in the context of the AST-walker, yes
   I don't know how to do that without
> basically rewriting some of Python's C code, though certainly I'm no 
> expert in the area...

Not messing with the CPython interpreter
> 
> Also, I'm not sure identity is sufficient:
> 
> py> import sys
> py> import new
> py> new.module('newsys')
> py> newsys = new.module('newsys')
> py> newsys.__dict__.update(sys.__dict__)
> py> newsys is sys
> False
> py> newsys == sys
> False

Right - the crux of the problem is how to identify dangerous objects.  My point 
is that if such as test is possible, then safe exec is very easily implemented 
within current Python. If it is not, then it is essentially impossible.

Let's assume that it is indeed not possible to know in general whether an object 
is safe, either by inspecting its attributes, or by matching its identity 
against a black list.

It might still be possible to have a reliable test within a problem-specific 
domain i.e., white-listing.  This, I think, is what you meant when you said:

> I wish there was a way to, say, exec something with no builtins and with import disabled, so you would have to specify all the available bindings, e.g.:
> 
>     exec user_code in dict(ClassA=ClassA, ClassB=ClassB) 

I believe that if you can come up with a white-list, then the rest of the 
problem is easy.

Michael




More information about the Python-list mailing list