diff options
author | Tim Peters <tim.peters@gmail.com> | 2020-05-06 02:28:24 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-06 02:28:24 (GMT) |
commit | b9c46a2c2d7fc68457bff641f78932d66f5e5f59 (patch) | |
tree | 7f7798c3f7ef5c476705bf2fdb349adddf14c354 /Lib/test/test_fnmatch.py | |
parent | 96074de573f82fc66a2bd73c36905141a3f1d5c1 (diff) | |
download | cpython-b9c46a2c2d7fc68457bff641f78932d66f5e5f59.zip cpython-b9c46a2c2d7fc68457bff641f78932d66f5e5f59.tar.gz cpython-b9c46a2c2d7fc68457bff641f78932d66f5e5f59.tar.bz2 |
bpo-40480 "fnmatch" exponential execution time (GH-19908)
bpo-40480: create different regexps in the presence of multiple `*`
patterns to prevent fnmatch() from taking exponential time.
Diffstat (limited to 'Lib/test/test_fnmatch.py')
-rw-r--r-- | Lib/test/test_fnmatch.py | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/Lib/test/test_fnmatch.py b/Lib/test/test_fnmatch.py index 55f9f0d..4c17306 100644 --- a/Lib/test/test_fnmatch.py +++ b/Lib/test/test_fnmatch.py @@ -45,6 +45,13 @@ class FnmatchTestCase(unittest.TestCase): check('\nfoo', 'foo*', False) check('\n', '*') + def test_slow_fnmatch(self): + check = self.check_match + check('a' * 50, '*a*a*a*a*a*a*a*a*a*a') + # The next "takes forever" if the regexp translation is + # straightforward. See bpo-40480. + check('a' * 50 + 'b', '*a*a*a*a*a*a*a*a*a*a', False) + def test_mix_bytes_str(self): self.assertRaises(TypeError, fnmatch, 'test', b'*') self.assertRaises(TypeError, fnmatch, b'test', '*') @@ -107,6 +114,16 @@ class TranslateTestCase(unittest.TestCase): self.assertEqual(translate('[!x]'), r'(?s:[^x])\Z') self.assertEqual(translate('[^x]'), r'(?s:[\^x])\Z') self.assertEqual(translate('[x'), r'(?s:\[x)\Z') + # from the docs + self.assertEqual(translate('*.txt'), r'(?s:.*\.txt)\Z') + # squash consecutive stars + self.assertEqual(translate('*********'), r'(?s:.*)\Z') + self.assertEqual(translate('A*********'), r'(?s:A.*)\Z') + self.assertEqual(translate('*********A'), r'(?s:.*A)\Z') + self.assertEqual(translate('A*********?[?]?'), r'(?s:A.*.[?].)\Z') + # fancy translation to prevent exponential-time match failure + self.assertEqual(translate('**a*a****a'), + r'(?s:(?=(?P<g1>.*?a))(?P=g1)(?=(?P<g2>.*?a))(?P=g2).*a)\Z') class FilterTestCase(unittest.TestCase): |