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

Skip to content

Commit fa46816

Browse files
Issue #9669: Protect re against infinite loops on zero-width matching in
non-greedy repeat. Patch by Matthew Barnett.
1 parent 70ca021 commit fa46816

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
@@ -616,6 +616,15 @@ def test_stack_overflow(self):
616616
self.assertEqual(re.match('(x)*y', 50000*'x'+'y').group(1), 'x')
617617
self.assertEqual(re.match('(x)*?y', 50000*'x'+'y').group(1), 'x')
618618

619+
def test_unlimited_zero_width_repeat(self):
620+
# Issue #9669
621+
self.assertIsNone(re.match(r'(?:a?)*y', 'z'))
622+
self.assertIsNone(re.match(r'(?:a?)+y', 'z'))
623+
self.assertIsNone(re.match(r'(?:a?){2,}y', 'z'))
624+
self.assertIsNone(re.match(r'(?:a?)*?y', 'z'))
625+
self.assertIsNone(re.match(r'(?:a?)+?y', 'z'))
626+
self.assertIsNone(re.match(r'(?:a?){2,}?y', 'z'))
627+
619628
def test_scanner(self):
620629
def s_ident(scanner, token): return token
621630
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
@@ -224,6 +224,9 @@ Core and Builtins
224224
Library
225225
-------
226226

227+
- Issue #9669: Protect re against infinite loops on zero-width matching in
228+
non-greedy repeat. Patch by Matthew Barnett.
229+
227230
- Issue #13169: The maximal repetition number in a regular expression has been
228231
increased from 65534 to 2147483647 (on 32-bit platform) or 4294967294 (on
229232
64-bit).

Modules/_sre.c

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

12961296
LASTMARK_RESTORE();
12971297

1298-
if (ctx->count >= ctx->u.rep->pattern[2]
1299-
&& ctx->u.rep->pattern[2] != SRE_MAXREPEAT)
1298+
if ((ctx->count >= ctx->u.rep->pattern[2]
1299+
&& ctx->u.rep->pattern[2] != SRE_MAXREPEAT) ||
1300+
state->ptr == ctx->u.rep->last_ptr)
13001301
RETURN_FAILURE;
13011302

13021303
ctx->u.rep->count = ctx->count;
1304+
/* zero-width match protection */
1305+
DATA_PUSH(&ctx->u.rep->last_ptr);
1306+
ctx->u.rep->last_ptr = state->ptr;
13031307
DO_JUMP(JUMP_MIN_UNTIL_3,jump_min_until_3,
13041308
ctx->u.rep->pattern+3);
1309+
DATA_POP(&ctx->u.rep->last_ptr);
13051310
if (ret) {
13061311
RETURN_ON_ERROR(ret);
13071312
RETURN_SUCCESS;

0 commit comments

Comments
 (0)