• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved.
2# Licensed to PSF under a Contributor Agreement.
3"""Safely evaluate Python string literals without using eval()."""
4
5import re
6
7simple_escapes = {
8    '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
20
21def escape(m):
22  all, tail = m.group(0, 1)
23  assert all.startswith('\\')
24  esc = simple_escapes.get(tail)
25  if esc is not None:
26    return esc
27  if tail.startswith('x'):
28    hexes = tail[1:]
29    if len(hexes) < 2:
30      raise ValueError("invalid hex string escape ('\\%s')" % tail)
31    try:
32      i = int(hexes, 16)
33    except ValueError:
34      raise ValueError("invalid hex string escape ('\\%s')" % tail) from None
35  else:
36    try:
37      i = int(tail, 8)
38    except ValueError:
39      raise ValueError("invalid octal string escape ('\\%s')" % tail) from None
40  return chr(i)
41
42
43def evalString(s):
44  assert s.startswith("'") or s.startswith('"'), repr(s[:1])
45  q = s[0]
46  if s[:3] == q * 3:
47    q = q * 3
48  assert s.endswith(q), repr(s[-len(q):])
49  assert len(s) >= 2 * len(q)
50  s = s[len(q):-len(q)]
51  return re.sub(r"\\(\'|\"|\\|[abfnrtv]|x.{0,2}|[0-7]{1,3})", escape, s)
52
53
54def test():
55  for i in range(256):
56    c = chr(i)
57    s = repr(c)
58    e = evalString(s)
59    if e != c:
60      print(i, c, s, e)
61
62
63if __name__ == '__main__':
64  test()
65