diff options
author | Jeremy Hylton <jeremy@alum.mit.edu> | 2000-09-15 15:14:51 (GMT) |
---|---|---|
committer | Jeremy Hylton <jeremy@alum.mit.edu> | 2000-09-15 15:14:51 (GMT) |
commit | be467e5c69515c355982e41d90762a31f2d3f75b (patch) | |
tree | 82e62b2aa1d370258dd72c41fcce76835e5180f4 /Lib/pickle.py | |
parent | a647f577f00647063f1e29be75b2b3b8207fc3d0 (diff) | |
download | cpython-be467e5c69515c355982e41d90762a31f2d3f75b.zip cpython-be467e5c69515c355982e41d90762a31f2d3f75b.tar.gz cpython-be467e5c69515c355982e41d90762a31f2d3f75b.tar.bz2 |
Fix Bug #114293:
Strings are unpickled by calling eval on the string's repr. This
change makes pickle work like cPickle; it checks if the pickled
string is safe to eval and raises ValueError if it is not.
test suite modifications:
Verify that pickle catches a variety of insecure string pickles
Make test_pickle and test_cpickle use exactly the same test suite
Add test for pickling recursive object
Diffstat (limited to 'Lib/pickle.py')
-rw-r--r-- | Lib/pickle.py | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/Lib/pickle.py b/Lib/pickle.py index 6c1bcbe..128a627 100644 --- a/Lib/pickle.py +++ b/Lib/pickle.py @@ -577,10 +577,50 @@ class Unpickler: dispatch[BINFLOAT] = load_binfloat def load_string(self): - self.append(eval(self.readline()[:-1], + rep = self.readline()[:-1] + if not self._is_string_secure(rep): + raise ValueError, "insecure string pickle" + self.append(eval(rep, {'__builtins__': {}})) # Let's be careful dispatch[STRING] = load_string + def _is_string_secure(self, s): + """Return true if s contains a string that is safe to eval + + The definition of secure string is based on the implementation + in cPickle. s is secure as long as it only contains a quoted + string and optional trailing whitespace. + """ + q = s[0] + if q not in ("'", '"'): + return 0 + # find the closing quote + offset = 1 + i = None + while 1: + try: + i = s.index(q, offset) + except ValueError: + # if there is an error the first time, there is no + # close quote + if offset == 1: + return 0 + if s[i-1] != '\\': + break + # check to see if this one is escaped + nslash = 0 + j = i - 1 + while j >= offset and s[j] == '\\': + j = j - 1 + nslash = nslash + 1 + if nslash % 2 == 0: + break + offset = i + 1 + for c in s[i+1:]: + if ord(c) > 32: + return 0 + return 1 + def load_binstring(self): len = mloads('i' + self.read(4)) self.append(self.read(len)) |