summaryrefslogtreecommitdiffstats
path: root/Lib/pickle.py
diff options
context:
space:
mode:
authorJeremy Hylton <jeremy@alum.mit.edu>2000-09-15 15:14:51 (GMT)
committerJeremy Hylton <jeremy@alum.mit.edu>2000-09-15 15:14:51 (GMT)
commitbe467e5c69515c355982e41d90762a31f2d3f75b (patch)
tree82e62b2aa1d370258dd72c41fcce76835e5180f4 /Lib/pickle.py
parenta647f577f00647063f1e29be75b2b3b8207fc3d0 (diff)
downloadcpython-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.py42
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))