Home | History | Annotate | Download | only in pgen2
      1 # Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved.

      2 # Licensed to PSF under a Contributor Agreement.

      3 
      4 """Safely evaluate Python string literals without using eval()."""
      5 
      6 import re
      7 
      8 simple_escapes = {"a": "\a",
      9                   "b": "\b",
     10                   "f": "\f",
     11                   "n": "\n",
     12                   "r": "\r",
     13                   "t": "\t",
     14                   "v": "\v",
     15                   "'": "'",
     16                   '"': '"',
     17                   "\\": "\\"}
     18 
     19 def escape(m):
     20     all, tail = m.group(0, 1)
     21     assert all.startswith("\\")
     22     esc = simple_escapes.get(tail)
     23     if esc is not None:
     24         return esc
     25     if tail.startswith("x"):
     26         hexes = tail[1:]
     27         if len(hexes) < 2:
     28             raise ValueError("invalid hex string escape ('\\%s')" % tail)
     29         try:
     30             i = int(hexes, 16)
     31         except ValueError:
     32             raise ValueError("invalid hex string escape ('\\%s')" % tail)
     33     else:
     34         try:
     35             i = int(tail, 8)
     36         except ValueError:
     37             raise ValueError("invalid octal string escape ('\\%s')" % tail)
     38     return chr(i)
     39 
     40 def evalString(s):
     41     assert s.startswith("'") or s.startswith('"'), repr(s[:1])
     42     q = s[0]
     43     if s[:3] == q*3:
     44         q = q*3
     45     assert s.endswith(q), repr(s[-len(q):])
     46     assert len(s) >= 2*len(q)
     47     s = s[len(q):-len(q)]
     48     return re.sub(r"\\(\'|\"|\\|[abfnrtv]|x.{0,2}|[0-7]{1,3})", escape, s)
     49 
     50 def test():
     51     for i in range(256):
     52         c = chr(i)
     53         s = repr(c)
     54         e = evalString(s)
     55         if e != c:
     56             print i, c, s, e
     57 
     58 
     59 if __name__ == "__main__":
     60     test()
     61