1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | # Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved. ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | # Licensed to PSF under a Contributor Agreement. ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | """Safely evaluate Python string literals without using eval().""" ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | import re ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from typing import Dict, Match ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | simple_escapes: Dict[str, str] = { ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | "a": "\a", ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | "b": "\b", ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | "f": "\f", ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | "n": "\n", ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | "r": "\r", ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | "t": "\t", ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | "v": "\v", ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | "'": "'", ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | '"': '"', ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | "\\": "\\", ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | } ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | def escape(m: Match[str]) -> str: 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | all, tail = m.group(0, 1) 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | assert all.startswith("\\") 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | esc = simple_escapes.get(tail) 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | if esc is not None: 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | return esc 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | if tail.startswith("x"): 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | hexes = tail[1:] 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | if len(hexes) < 2: 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | raise ValueError("invalid hex string escape ('\\%s')" % tail) 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | try: 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | i = int(hexes, 16) 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | except ValueError: 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | raise ValueError("invalid hex string escape ('\\%s')" % tail) from None 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | else: 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | try: 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | i = int(tail, 8) 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | except ValueError: 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | raise ValueError("invalid octal string escape ('\\%s')" % tail) from None 0020 0021 0020 0000 0000 0000 0000 -- 06 003 007 005 010 010 015 0049.83 0106.78 0002.14 | return chr(i) ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | 0009 0012 0009 0000 0000 0000 0000 -- 02 005 012 008 014 017 022 0089.92 0262.28 0002.92 | def evalString(s: str) -> str: 0009 0012 0009 0000 0000 0000 0000 -- 02 005 012 008 014 017 022 0089.92 0262.28 0002.92 | assert s.startswith("'") or s.startswith('"'), repr(s[:1]) 0009 0012 0009 0000 0000 0000 0000 -- 02 005 012 008 014 017 022 0089.92 0262.28 0002.92 | q = s[0] 0009 0012 0009 0000 0000 0000 0000 -- 02 005 012 008 014 017 022 0089.92 0262.28 0002.92 | if s[:3] == q * 3: 0009 0012 0009 0000 0000 0000 0000 -- 02 005 012 008 014 017 022 0089.92 0262.28 0002.92 | q = q * 3 0009 0012 0009 0000 0000 0000 0000 -- 02 005 012 008 014 017 022 0089.92 0262.28 0002.92 | assert s.endswith(q), repr(s[-len(q) :]) 0009 0012 0009 0000 0000 0000 0000 -- 02 005 012 008 014 017 022 0089.92 0262.28 0002.92 | assert len(s) >= 2 * len(q) 0009 0012 0009 0000 0000 0000 0000 -- 02 005 012 008 014 017 022 0089.92 0262.28 0002.92 | s = s[len(q) : -len(q)] 0009 0012 0009 0000 0000 0000 0000 -- 02 005 012 008 014 017 022 0089.92 0262.28 0002.92 | return re.sub(r"\\(\'|\"|\\|[abfnrtv]|x.{0,2}|[0-7]{1,3})", escape, s) ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | 0007 0007 0007 0000 0000 0000 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def test() -> None: 0007 0007 0007 0000 0000 0000 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | for i in range(256): 0007 0007 0007 0000 0000 0000 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | c = chr(i) 0007 0007 0007 0000 0000 0000 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | s = repr(c) 0007 0007 0007 0000 0000 0000 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | e = evalString(s) 0007 0007 0007 0000 0000 0000 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | if e != c: 0007 0007 0007 0000 0000 0000 0000 -- 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | print(i, c, s, e) ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | if __name__ == "__main__": ---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | test()