From e85e0b68ab28ccd8728a87e5791dc30732192ef3 Mon Sep 17 00:00:00 2001 From: afg Date: Wed, 6 Jan 2016 00:43:20 +0800 Subject: [PATCH] re_unescape with a much simpler method; raise TypeError on invalid input --- tornado/test/util_test.py | 9 ++++++++- tornado/util.py | 20 +++++++++++--------- tornado/web.py | 4 ++++ 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/tornado/test/util_test.py b/tornado/test/util_test.py index 6a0fa5c4a..70b6e7a1e 100644 --- a/tornado/test/util_test.py +++ b/tornado/test/util_test.py @@ -207,9 +207,16 @@ class ReUnescapeTest(unittest.TestCase): test_strings = ( '/favicon.ico', 'index.html', - '\x00\x01\\000', 'Hello, World!', '!$@#%;', ) for string in test_strings: self.assertEqual(string, re_unescape(re.escape(string))) + + def test_re_unescape_raises_error_on_invalid_input(self): + with self.assertRaises(ValueError): + re_unescape('\\d') + with self.assertRaises(ValueError): + re_unescape('\\b') + with self.assertRaises(ValueError): + re_unescape('\\Z') diff --git a/tornado/util.py b/tornado/util.py index e74be97c7..a0401c143 100644 --- a/tornado/util.py +++ b/tornado/util.py @@ -173,20 +173,22 @@ def errno_from_exception(e): return None -_re_unescape_split_pattern = re.compile(r'(\\[^0])') -# re.escape('\x00') is a special case +_alphanum = frozenset( + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") + +def _re_unescape_replacement(match): + group = match.group(1) + if group[0] in _alphanum: + raise ValueError("cannot unescape '\\\\%s'" % group[0]) + return group + +_re_unescape_pattern = re.compile(r'\\(.)', re.DOTALL) def re_unescape(s): ''' unescape a string escaped by ``re.escape()`` ''' - parts = [] - for i, splited in enumerate(_re_unescape_split_pattern.split(s)): - if i % 2: - parts.append(splited[1]) - else: - parts.append(splited.replace(r'\000', '\000')) - return ''.join(parts) + return _re_unescape_pattern.sub(_re_unescape_replacement, s) class Configurable(object): diff --git a/tornado/web.py b/tornado/web.py index a5301db16..b45363cca 100644 --- a/tornado/web.py +++ b/tornado/web.py @@ -3024,6 +3024,10 @@ class URLSpec(object): if paren_loc >= 0: pieces.append('%s' + fragment[paren_loc + 1:]) else: + try: + unescaped_fragment = re_unescape(fragment) + except ValueError as exc: + raise ValueError(exc.args[0] + '; invalid url: %r' % pattern) pieces.append(re_unescape(fragment)) return (''.join(pieces), self.regex.groups) -- 2.47.2