diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2013-02-16 16:47:47 +0200 |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2013-02-16 16:47:47 +0200 |
commit | c1bc0b91f6d3d93785f62cee4ceb78ef6fc0ab7c (patch) | |
tree | 91b3d5c5de1a4c161c722599984e5d2d9ea349d9 /Lib | |
parent | 6b8e2d5d7b82000f170f6301f25773f12172d456 (diff) | |
download | cpython-c1bc0b91f6d3d93785f62cee4ceb78ef6fc0ab7c.tar.gz |
Issue #13169: The maximal repetition number in a regular expression has been
increased from 65534 to 2147483647 (on 32-bit platform) or 4294967294 (on
64-bit).
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/sre_compile.py | 1 | ||||
-rw-r--r-- | Lib/sre_constants.py | 4 | ||||
-rw-r--r-- | Lib/sre_parse.py | 9 | ||||
-rw-r--r-- | Lib/test/test_re.py | 34 |
4 files changed, 41 insertions, 7 deletions
diff --git a/Lib/sre_compile.py b/Lib/sre_compile.py index f52ea01459..46eac9c070 100644 --- a/Lib/sre_compile.py +++ b/Lib/sre_compile.py @@ -13,6 +13,7 @@ import _sre, sys import sre_parse from sre_constants import * +from _sre import MAXREPEAT assert _sre.MAGIC == MAGIC, "SRE module mismatch" diff --git a/Lib/sre_constants.py b/Lib/sre_constants.py index 417670bf8d..71ccb23f62 100644 --- a/Lib/sre_constants.py +++ b/Lib/sre_constants.py @@ -15,10 +15,6 @@ MAGIC = 20031017 -# max code word in this release - -MAXREPEAT = 65535 - # SRE standard exception (access as sre.error) # should this really be here? diff --git a/Lib/sre_parse.py b/Lib/sre_parse.py index 19dd4fc4bc..045a5ebfef 100644 --- a/Lib/sre_parse.py +++ b/Lib/sre_parse.py @@ -15,6 +15,7 @@ import sys from sre_constants import * +from _sre import MAXREPEAT SPECIAL_CHARS = ".\\[{()*+?^$|" REPEAT_CHARS = "*+?{" @@ -505,10 +506,14 @@ def _parse(source, state): continue if lo: min = int(lo) + if min >= MAXREPEAT: + raise OverflowError("the repetition number is too large") if hi: max = int(hi) - if max < min: - raise error("bad repeat interval") + if max >= MAXREPEAT: + raise OverflowError("the repetition number is too large") + if max < min: + raise error("bad repeat interval") else: raise error("not supported") # figure out which item to repeat diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 6b047e48db..f7e76dcfba 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -1,4 +1,5 @@ -from test.support import verbose, run_unittest, gc_collect, bigmemtest, _2G +from test.support import verbose, run_unittest, gc_collect, bigmemtest, _2G, \ + cpython_only import io import re from re import Scanner @@ -883,6 +884,37 @@ class ReTests(unittest.TestCase): self.assertEqual(n, size + 1) + def test_repeat_minmax_overflow(self): + # Issue #13169 + string = "x" * 100000 + self.assertEqual(re.match(r".{65535}", string).span(), (0, 65535)) + self.assertEqual(re.match(r".{,65535}", string).span(), (0, 65535)) + self.assertEqual(re.match(r".{65535,}?", string).span(), (0, 65535)) + self.assertEqual(re.match(r".{65536}", string).span(), (0, 65536)) + self.assertEqual(re.match(r".{,65536}", string).span(), (0, 65536)) + self.assertEqual(re.match(r".{65536,}?", string).span(), (0, 65536)) + # 2**128 should be big enough to overflow both SRE_CODE and Py_ssize_t. + self.assertRaises(OverflowError, re.compile, r".{%d}" % 2**128) + self.assertRaises(OverflowError, re.compile, r".{,%d}" % 2**128) + self.assertRaises(OverflowError, re.compile, r".{%d,}?" % 2**128) + self.assertRaises(OverflowError, re.compile, r".{%d,%d}" % (2**129, 2**128)) + + @cpython_only + def test_repeat_minmax_overflow_maxrepeat(self): + try: + from _sre import MAXREPEAT + except ImportError: + self.skipTest('requires _sre.MAXREPEAT constant') + string = "x" * 100000 + self.assertIsNone(re.match(r".{%d}" % (MAXREPEAT - 1), string)) + self.assertEqual(re.match(r".{,%d}" % (MAXREPEAT - 1), string).span(), + (0, 100000)) + self.assertIsNone(re.match(r".{%d,}?" % (MAXREPEAT - 1), string)) + self.assertRaises(OverflowError, re.compile, r".{%d}" % MAXREPEAT) + self.assertRaises(OverflowError, re.compile, r".{,%d}" % MAXREPEAT) + self.assertRaises(OverflowError, re.compile, r".{%d,}?" % MAXREPEAT) + + def run_re_tests(): from test.re_tests import tests, SUCCEED, FAIL, SYNTAX_ERROR if verbose: |