[Python-Dev] Re: [Python-checkins] CVS: python/dist/src/Lib pickle.py,1.38,1.39

Guido van Rossum guido@beopen.com
Fri, 15 Sep 2000 11:24:47 -0500


> --- 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):

Hm...  This seems to add a lot of work to a very common item in
pickles.

I had a different idea on how to make this safe from abuse: pass eval
a globals dict with an empty __builtins__ dict, as follows:
{'__builtins__': {}}.

Have you timed it?

--Guido van Rossum (home page: http://www.pythonlabs.com/~guido/)