Martin v. Löwis | ef04c44 | 2008-03-19 05:04:44 +0000 | [diff] [blame] | 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: |
Martin v. Löwis | 8a5f8ca | 2008-03-19 05:33:36 +0000 | [diff] [blame^] | 56 | print(i, c, s, e) |
Martin v. Löwis | ef04c44 | 2008-03-19 05:04:44 +0000 | [diff] [blame] | 57 | |
| 58 | |
| 59 | if __name__ == "__main__": |
| 60 | test() |