I'm trying to set up a client and server in python so that the client sends some code, the server executes and processes it, and then sends the output back. I can execute the code received on the server with the command exec but whenever I try: var = exec "print 'word'", this doesn't work and fails with a syntax error; whereas when I run the same command not set to a variable, it works flawlessly. I am using python2.7
Don't. Eval and Exec are very dangerous from untrusted inputs and there is no reasonable way to make them safe:
Using eval
or exec
from an untrusted input means you can get queries like this:
eval("os.system('clear')", {})
Use ast.literal_eval
to evaluate safely evaluate a string to a Python object.
>>> import ast
>>> string = '{}'
>>> b = ast.literal_eval(string)
>>> b
{}
>>> type(b)
<class 'dict'>
If you can trust the input, use eval
.
>>> string = '{}'
>>> b = eval(string)
>>> b
{}
>>> type(b)
<class 'dict'>
The Dangers of Eval and Exec
To explain why eval
is dangerous, and why ast.literal_eval is safe, you have to understand how eval works: it merely takes a string and then interprets the input as Python code, allowing essentially anything to occur.
There are many ways to try to make eval
and exec
safe, however, all have various ways of getting around them. You can prevent nearly everything, including imports, builtins, etc., and someone can still find a way to get around it (see the link above).
ast.literal_eval
gets around this by only allowing valid Python datatypes to be evaluated, such as dict, list, tuple, None, int, string, and float. This prevents the malicious execution of any code, but the application is much more limited. However, this extra security is well worth the loss of functionality for code coming from unknown sources.
A good example on how ast.literal_eval
keeps you safe is the following snippet:
>>> import ast
>>> eval('__import__("os")')
<module 'os' from '/usr/lib/python3.4/os.py'>
>>> ast.literal_eval('__import__("os")')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.4/ast.py", line 84, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.4/ast.py", line 83, in _convert
raise ValueError('malformed node or string: ' + repr(node))
ValueError: malformed node or string: <_ast.Call object at 0x7f68e03db2e8>
Eval allows direct code execution, in this case, allowing access to the os module and therefore system tasks that could wipe your drive, while ast.literal_eval raises an error because it is not a recognized data type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With