src/blib2to3/pgen2/literals.py
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | # 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()