From 478f967af46b9808354d8b8b69242bead2fc5f35 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Wed, 27 Feb 2013 14:01:31 -0500 Subject: [PATCH] We would fail if a global was defined with a non-jsonable value inside a jsonable one. Now we don't/ --- common/lib/codejail/codejail/safe_exec.py | 20 ++++++++++++++++++- .../codejail/codejail/tests/test_safe_exec.py | 8 ++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/common/lib/codejail/codejail/safe_exec.py b/common/lib/codejail/codejail/safe_exec.py index 7b4037a2a9..b77081a2a2 100644 --- a/common/lib/codejail/codejail/safe_exec.py +++ b/common/lib/codejail/codejail/safe_exec.py @@ -43,6 +43,10 @@ def safe_exec(code, globals_dict, assumed_imports=None, files=None, python_path= Returns None. Changes made by `code` are visible in `globals_dict`. """ + print "--- Executing: -------" + print code + print + the_code = [] files = list(files or ()) @@ -86,7 +90,15 @@ def safe_exec(code, globals_dict, assumed_imports=None, files=None, python_path= """ ok_types = (type(None), int, long, float, str, unicode, list, tuple, dict) bad_keys = ("__builtins__",) - g_dict = {k:v for k,v in g_dict.iteritems() if isinstance(v, ok_types) and k not in bad_keys} + def jsonable(v): + if not isinstance(v, ok_types): + return False + try: + json.dumps(v) + except Exception: + return False + return True + g_dict = {k:v for k,v in g_dict.iteritems() if jsonable(v) and k not in bad_keys} """ # Write the globals back to the calling process. """ @@ -124,8 +136,14 @@ def not_safe_exec(code, globals_dict, assumed_imports=None, files=None, python_p Used to emulate reading data through a serialization straw. """ + ok_types = (type(None), int, long, float, str, unicode, list, tuple, dict) + bad_keys = ("__builtins__",) jd = {} for k,v in d.iteritems(): + if not isinstance(v, ok_types): + continue + if k in bad_keys: + continue try: json.dumps(v) except TypeError: diff --git a/common/lib/codejail/codejail/tests/test_safe_exec.py b/common/lib/codejail/codejail/tests/test_safe_exec.py index b4f3627ad6..8a565f8cfb 100644 --- a/common/lib/codejail/codejail/tests/test_safe_exec.py +++ b/common/lib/codejail/codejail/tests/test_safe_exec.py @@ -59,6 +59,14 @@ class SafeExecTests(object): self.safe_exec("a = 17; print 'hi!'", g) self.assertEqual(g['a'], 17) + def test_importing_lots_of_crap(self): + g = {} + self.safe_exec(textwrap.dedent("""\ + from numpy import * + a = 1723 + """), g) + self.assertEqual(g['a'], 1723) + class TestSafeExec(SafeExecTests, unittest.TestCase): """Run SafeExecTests, with the real safe_exec."""