Python eval(compile(…), sandbox), globals go in sandbox unless in def, why?
考虑下面的:P></
1 2 3 4 5 6 7 8 9 10 11 12 | def test(s): globals()['a'] = s sandbox = {'test': test} py_str = 'test("Setting A") globals()["b"] ="Setting B"' eval(compile(py_str, '<string>', 'exec'), sandbox) 'a' in sandbox # returns False, !What I dont want! 'b' in sandbox # returns True, What I want 'a' in globals() # returns True, !What I dont want! 'b' in globals() # returns False, What I want |
我甚至不确定我想问how to,but the Global to be the scope for a函数的环境中运行它有没有打算在编译eval function to the the。这是可能的吗?P></
thanks for any输入P></
解决方案P></
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | def test(s): globals()['a'] = s sandbox = {} # create a new version of test() that uses the sandbox for its globals newtest = type(test)(test.func_code, sandbox, test.func_name, test.func_defaults, test.func_closure) # add the sandboxed version of test() to the sandbox sandbox["test"] = newtest py_str = 'test("Setting A") globals()["b"] ="Setting B"' eval(compile(py_str, '<string>', 'exec'), sandbox) 'a' in sandbox # returns True 'b' in sandbox # returns True 'a' in globals() # returns False 'b' in globals() # returns False |
在Python中调用函数时,它看到的全局变量始终是在其中定义的模块的全局变量。(如果这不是真的,那么函数可能不起作用——它可能实际上需要一些全局值,而您不一定知道这些值是什么。)指定一个带有
如果您希望函数看到其他全局变量,那么您确实需要在传递给
您可以通过创建一个新的函数来解决这个问题,该函数与您所调用的函数具有相同的代码对象,但具有指向全局dict的不同
1 2 3 4 5 6 7 8 9 | # create a sandbox globals dict sandbox = {} # create a new version of test() that uses the sandbox for its globals newtest = type(test)(test.func_code, sandbox, test.func_name, test.func_defaults, test.func_closure) # add the sandboxed version of test() to the sandbox sandbox["test"] = newtest |
可选的全局/局部变量只适用于沙盒中的代码。它们不会影响它之外的任何事物,也不会影响它之外的任何事物,如果它们能够,就没有意义了。
换句话说,所谓的"沙盒"将对象
test 传递给exec运行的代码。为了改变test 所看到的全局,它还必须修改对象,而不是按原样传递它。这是不可能的,以任何方式来保持它的工作,更不用说在一个对象将继续做一些有意义的事情的方式。通过使用替代全局,
sandbox 中的任何内容都将看到内置的。如果要隐藏沙盒内的代码中的部分或所有内置项,则需要在字典中添加一个指向None (禁用所有内置项)或其版本的"__builtins__" 键。这也限制了对象的某些属性,例如访问函数的func_globals 属性将被禁用。即使移除内置组件,沙箱仍然不安全。沙盒代码是您首先信任的。
这是一个简单的概念证明:
1 2 3 4 5 6 7 | import subprocess code ="""[x for x in ().__class__.__bases__[0].__subclasses__() if x.__name__ == 'Popen'][0](['ls', '-la']).wait()""" # The following runs"ls"... exec code in dict(__builtins__=None) # ...even though the following raises exec"(lambda:None).func_globals" in dict(__builtins__=None) |
外部执行上下文是在python中静态定义的(
1 2 3 4 | def mycheck(s): return True exec priviledged_code in {'check_password':mycheck} |