Making eval() safe
Python eval function comes with the facility of explicitly passing a list of functions or variables that it can access. We need to pass it as an argument in the form of a dictionary.
Python3
from math import * def secret_function(): return "Secret key is 1234" def function_creator(): # expression to be evaluated expr = input ( "Enter the function(in terms of x):" ) # variable used in expression x = int ( input ( "Enter the value of x:" )) # passing variable x in safe dictionary safe_dict[ 'x' ] = x # evaluating expression y = eval (expr, {}, safe_dict) # printing evaluated result print ( "y = {}" . format (y)) if __name__ = = "__main__" : # list of safe methods safe_list = [ 'acos' , 'asin' , 'atan' , 'atan2' , 'ceil' , 'cos' , 'cosh' , 'degrees' , 'e' , 'exp' , 'fabs' , 'floor' , 'fmod' , 'frexp' , 'hypot' , 'ldexp' , 'log' , 'log10' , 'modf' , 'pi' , 'pow' , 'radians' , 'sin' , 'sinh' , 'sqrt' , 'tan' , 'tanh' ] # creating a dictionary of safe methods safe_dict = {} for safe_key in safe_list: safe_dict[safe_key] = locals ().get(safe_key) function_creator() |
Now if we try to run the above programs like:
Enter the function(in terms of x):secret_function()
Enter the value of x:0
We get the output:
NameError: name 'secret_function' is not defined
Let us analyze the above code step by step:
- First, we create a list of methods we want to allow as safe_list.
- Next, we create a dictionary of safe methods. In this dictionary, keys are the method names and values are their local namespaces.
safe_dict = {}
for safe_key in safe_list:
safe_dict[safe_key] = locals().get(safe_key)
- locals() is a built-in method that returns a dictionary that maps all the methods and variables in the local scope with their namespaces.
safe_dict['x'] = x
Here, we add the local variable x to the safe_dict too. No local variable other than x will get identified by the eval function.
- eval accepts dictionaries of local as well as global variables as arguments. So, in order to ensure that none of the built-in methods is available to eval expression, we pass another dictionary along with safe_dict as well, as shown below:
y = eval(expr, {}, safe_dict)
So, in this way, we have made our eval function safe from any possible hacks!
eval in Python
Python eval() function parse the expression argument and evaluate it as a Python expression and runs Python expression (code) within the program.