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

Skip to content

Commit 3646ab9

Browse files
committed
Fix for part of the problem mentioned in #725149 by Greg Chapman.
This problem is related to a wrong behavior from mark_save/restore(), which don't restore the mark_stack_base before restoring the marks. Greg's suggestion was to change the asserts, which happen to be the only recursive ops that can continue the loop, but the problem would happen to any operation with the same behavior. So, rather than hardcoding this into asserts, I have changed mark_save/restore() to always restore the stackbase before restoring the marks. Both solutions should fix these two cases, presented by Greg: >>> re.match('(a)(?:(?=(b)*)c)*', 'abb').groups() ('b', None) >>> re.match('(a)((?!(b)*))*', 'abb').groups() ('b', None, None) The rest of the bug and patch in #725149 must be discussed further.
1 parent c34f255 commit 3646ab9

2 files changed

Lines changed: 17 additions & 8 deletions

File tree

Lib/test/test_re.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,13 @@ def test_bug_725106(self):
295295
self.assertEqual(re.match('^((a)c|[ab])*?c', 'abc').groups(),
296296
('b', None))
297297

298+
def test_bug_725149(self):
299+
# mark_stack_base restoring before restoring marks
300+
self.assertEqual(re.match('(a)(?:(?=(b)*)c)*', 'abb').groups(),
301+
('a', None))
302+
self.assertEqual(re.match('(a)((?!(b)*))*', 'abb').groups(),
303+
('a', None, None))
304+
298305
def test_finditer(self):
299306
iter = re.finditer(r":+", "a:b::c:::d")
300307
self.assertEqual([item.group(0) for item in iter],

Modules/_sre.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ mark_fini(SRE_STATE* state)
279279
}
280280

281281
static int
282-
mark_save(SRE_STATE* state, int lo, int hi)
282+
mark_save(SRE_STATE* state, int lo, int hi, int *mark_stack_base)
283283
{
284284
void* stack;
285285
int size;
@@ -323,11 +323,13 @@ mark_save(SRE_STATE* state, int lo, int hi)
323323

324324
state->mark_stack_base += size;
325325

326+
*mark_stack_base = state->mark_stack_base;
327+
326328
return 0;
327329
}
328330

329331
static int
330-
mark_restore(SRE_STATE* state, int lo, int hi)
332+
mark_restore(SRE_STATE* state, int lo, int hi, int *mark_stack_base)
331333
{
332334
int size;
333335

@@ -336,7 +338,7 @@ mark_restore(SRE_STATE* state, int lo, int hi)
336338

337339
size = (hi - lo) + 1;
338340

339-
state->mark_stack_base -= size;
341+
state->mark_stack_base = *mark_stack_base - size;
340342

341343
TRACE(("copy %d:%d from %d\n", lo, hi, state->mark_stack_base));
342344

@@ -712,7 +714,7 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
712714
SRE_CHAR* ptr = state->ptr;
713715
int i, count;
714716
SRE_REPEAT* rp;
715-
int lastmark, lastindex;
717+
int lastmark, lastindex, mark_stack_base;
716718
SRE_CODE chr;
717719

718720
SRE_REPEAT rep; /* FIXME: <fl> allocate in STATE instead */
@@ -948,7 +950,7 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
948950
(ptr >= end || !SRE_CHARSET(pattern + 3, (SRE_CODE) *ptr)))
949951
continue;
950952
if (state->repeat) {
951-
i = mark_save(state, 0, lastmark);
953+
i = mark_save(state, 0, lastmark, &mark_stack_base);
952954
if (i < 0)
953955
return i;
954956
}
@@ -957,7 +959,7 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
957959
if (i)
958960
return i;
959961
if (state->repeat) {
960-
i = mark_restore(state, 0, lastmark);
962+
i = mark_restore(state, 0, lastmark, &mark_stack_base);
961963
if (i < 0)
962964
return i;
963965
}
@@ -1157,14 +1159,14 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
11571159
/* we may have enough matches, but if we can
11581160
match another item, do so */
11591161
rp->count = count;
1160-
i = mark_save(state, 0, lastmark);
1162+
i = mark_save(state, 0, lastmark, &mark_stack_base);
11611163
if (i < 0)
11621164
return i;
11631165
/* RECURSIVE */
11641166
i = SRE_MATCH(state, rp->pattern + 3, level + 1);
11651167
if (i)
11661168
return i;
1167-
i = mark_restore(state, 0, lastmark);
1169+
i = mark_restore(state, 0, lastmark, &mark_stack_base);
11681170
LASTMARK_RESTORE();
11691171
if (i < 0)
11701172
return i;

0 commit comments

Comments
 (0)