17db96d56Sopenharmony_ci# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved.
27db96d56Sopenharmony_ci# Licensed to PSF under a Contributor Agreement.
37db96d56Sopenharmony_ci
47db96d56Sopenharmony_ci"""Safely evaluate Python string literals without using eval()."""
57db96d56Sopenharmony_ci
67db96d56Sopenharmony_ciimport re
77db96d56Sopenharmony_ci
87db96d56Sopenharmony_cisimple_escapes = {"a": "\a",
97db96d56Sopenharmony_ci                  "b": "\b",
107db96d56Sopenharmony_ci                  "f": "\f",
117db96d56Sopenharmony_ci                  "n": "\n",
127db96d56Sopenharmony_ci                  "r": "\r",
137db96d56Sopenharmony_ci                  "t": "\t",
147db96d56Sopenharmony_ci                  "v": "\v",
157db96d56Sopenharmony_ci                  "'": "'",
167db96d56Sopenharmony_ci                  '"': '"',
177db96d56Sopenharmony_ci                  "\\": "\\"}
187db96d56Sopenharmony_ci
197db96d56Sopenharmony_cidef escape(m):
207db96d56Sopenharmony_ci    all, tail = m.group(0, 1)
217db96d56Sopenharmony_ci    assert all.startswith("\\")
227db96d56Sopenharmony_ci    esc = simple_escapes.get(tail)
237db96d56Sopenharmony_ci    if esc is not None:
247db96d56Sopenharmony_ci        return esc
257db96d56Sopenharmony_ci    if tail.startswith("x"):
267db96d56Sopenharmony_ci        hexes = tail[1:]
277db96d56Sopenharmony_ci        if len(hexes) < 2:
287db96d56Sopenharmony_ci            raise ValueError("invalid hex string escape ('\\%s')" % tail)
297db96d56Sopenharmony_ci        try:
307db96d56Sopenharmony_ci            i = int(hexes, 16)
317db96d56Sopenharmony_ci        except ValueError:
327db96d56Sopenharmony_ci            raise ValueError("invalid hex string escape ('\\%s')" % tail) from None
337db96d56Sopenharmony_ci    else:
347db96d56Sopenharmony_ci        try:
357db96d56Sopenharmony_ci            i = int(tail, 8)
367db96d56Sopenharmony_ci        except ValueError:
377db96d56Sopenharmony_ci            raise ValueError("invalid octal string escape ('\\%s')" % tail) from None
387db96d56Sopenharmony_ci    return chr(i)
397db96d56Sopenharmony_ci
407db96d56Sopenharmony_cidef evalString(s):
417db96d56Sopenharmony_ci    assert s.startswith("'") or s.startswith('"'), repr(s[:1])
427db96d56Sopenharmony_ci    q = s[0]
437db96d56Sopenharmony_ci    if s[:3] == q*3:
447db96d56Sopenharmony_ci        q = q*3
457db96d56Sopenharmony_ci    assert s.endswith(q), repr(s[-len(q):])
467db96d56Sopenharmony_ci    assert len(s) >= 2*len(q)
477db96d56Sopenharmony_ci    s = s[len(q):-len(q)]
487db96d56Sopenharmony_ci    return re.sub(r"\\(\'|\"|\\|[abfnrtv]|x.{0,2}|[0-7]{1,3})", escape, s)
497db96d56Sopenharmony_ci
507db96d56Sopenharmony_cidef test():
517db96d56Sopenharmony_ci    for i in range(256):
527db96d56Sopenharmony_ci        c = chr(i)
537db96d56Sopenharmony_ci        s = repr(c)
547db96d56Sopenharmony_ci        e = evalString(s)
557db96d56Sopenharmony_ci        if e != c:
567db96d56Sopenharmony_ci            print(i, c, s, e)
577db96d56Sopenharmony_ci
587db96d56Sopenharmony_ci
597db96d56Sopenharmony_ciif __name__ == "__main__":
607db96d56Sopenharmony_ci    test()
61