Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b0c75a7

Browse files
Issue #9669: Protect re against infinite loops on zero-width matching in
non-greedy repeat. Patch by Matthew Barnett.
2 parents f8def28 + fa46816 commit b0c75a7

3 files changed

Lines changed: 19 additions & 2 deletions

File tree

Lib/test/test_re.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,15 @@ def test_stack_overflow(self):
681681
self.assertEqual(re.match('(x)*y', 50000*'x'+'y').group(1), 'x')
682682
self.assertEqual(re.match('(x)*?y', 50000*'x'+'y').group(1), 'x')
683683

684+
def test_unlimited_zero_width_repeat(self):
685+
# Issue #9669
686+
self.assertIsNone(re.match(r'(?:a?)*y', 'z'))
687+
self.assertIsNone(re.match(r'(?:a?)+y', 'z'))
688+
self.assertIsNone(re.match(r'(?:a?){2,}y', 'z'))
689+
self.assertIsNone(re.match(r'(?:a?)*?y', 'z'))
690+
self.assertIsNone(re.match(r'(?:a?)+?y', 'z'))
691+
self.assertIsNone(re.match(r'(?:a?){2,}?y', 'z'))
692+
684693
def test_scanner(self):
685694
def s_ident(scanner, token): return token
686695
def s_operator(scanner, token): return "op%s" % token

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,9 @@ Core and Builtins
178178
Library
179179
-------
180180

181+
- Issue #9669: Protect re against infinite loops on zero-width matching in
182+
non-greedy repeat. Patch by Matthew Barnett.
183+
181184
- Issue #13169: The maximal repetition number in a regular expression has been
182185
increased from 65534 to 2147483647 (on 32-bit platform) or 4294967294 (on
183186
64-bit).

Modules/_sre.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,13 +1272,18 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern)
12721272

12731273
LASTMARK_RESTORE();
12741274

1275-
if (ctx->count >= ctx->u.rep->pattern[2]
1276-
&& ctx->u.rep->pattern[2] != SRE_MAXREPEAT)
1275+
if ((ctx->count >= ctx->u.rep->pattern[2]
1276+
&& ctx->u.rep->pattern[2] != SRE_MAXREPEAT) ||
1277+
state->ptr == ctx->u.rep->last_ptr)
12771278
RETURN_FAILURE;
12781279

12791280
ctx->u.rep->count = ctx->count;
1281+
/* zero-width match protection */
1282+
DATA_PUSH(&ctx->u.rep->last_ptr);
1283+
ctx->u.rep->last_ptr = state->ptr;
12801284
DO_JUMP(JUMP_MIN_UNTIL_3,jump_min_until_3,
12811285
ctx->u.rep->pattern+3);
1286+
DATA_POP(&ctx->u.rep->last_ptr);
12821287
if (ret) {
12831288
RETURN_ON_ERROR(ret);
12841289
RETURN_SUCCESS;

0 commit comments

Comments
 (0)