[Python-checkins] CVS: python/dist/src/Lib pickle.py,1.38,1.39
Jeremy Hylton
python-dev@python.org
Fri, 15 Sep 2000 08:14:54 -0700
Update of /cvsroot/python/python/dist/src/Lib
In directory slayer.i.sourceforge.net:/tmp/cvs-serv25891/Lib
Modified Files:
pickle.py
Log Message:
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
Index: pickle.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/pickle.py,v
retrieving revision 1.38
retrieving revision 1.39
diff -C2 -r1.38 -r1.39
*** pickle.py 2000/06/29 16:15:52 1.38
--- pickle.py 2000/09/15 15:14:51 1.39
***************
*** 578,584 ****
def load_string(self):
! self.append(eval(self.readline()[:-1],
{'__builtins__': {}})) # Let's be careful
dispatch[STRING] = load_string
def load_binstring(self):
--- 578,624 ----
def load_string(self):
! 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):