The cache key for safe_exec has to be hashed to keep it a reasonable size.

This commit is contained in:
Ned Batchelder
2013-04-30 11:23:11 -04:00
parent 09fbbe7bfa
commit baa6b4e3e4
2 changed files with 20 additions and 1 deletions

View File

@@ -4,6 +4,8 @@ from codejail.safe_exec import safe_exec as codejail_safe_exec
from codejail.safe_exec import json_safe
from . import lazymod
import hashlib
# Establish the Python environment for Capa.
# Capa assumes float-friendly division always.
# The name "random" is a properly-seeded stand-in for the random module.
@@ -53,7 +55,10 @@ def safe_exec(code, globals_dict, random_seed=None, python_path=None, cache=None
# Check the cache for a previous result.
if cache:
canonical_globals = sorted(json_safe(globals_dict).iteritems())
key = "safe_exec %r %s %r" % (random_seed, code, canonical_globals)
md5er = hashlib.md5()
md5er.update(code)
md5er.update(repr(canonical_globals))
key = "safe_exec %r %s" % (random_seed, md5er.hexdigest())
cached = cache.get(key)
if cached is not None:
globals_dict.update(cached)

View File

@@ -65,9 +65,13 @@ class DictCache(object):
self.cache = d
def get(self, key):
# Actual cache implementations have limits on key length
assert len(key) <= 250
return self.cache.get(key)
def set(self, key, value):
# Actual cache implementations have limits on key length
assert len(key) <= 250
self.cache[key] = value
@@ -90,3 +94,13 @@ class TestSafeExecCaching(unittest.TestCase):
g = {}
safe_exec("a = int(math.pi)", g, cache=DictCache(cache))
self.assertEqual(g['a'], 17)
def test_cache_large_code_chunk(self):
# Caching used to die on memcache with more than 250 bytes of code.
# Check that it doesn't any more.
code = "a = 0\n" + ("a += 1\n" * 12345)
g = {}
cache = {}
safe_exec(code, g, cache=DictCache(cache))
self.assertEqual(g['a'], 12345)