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

Skip to content

Commit 4e7be06

Browse files
committed
Fixed bug #470582, using a modified version of patch #527371,
from Greg Chapman. * Modules/_sre.c (lastmark_restore): New function, implementing algorithm to restore a state to a given lastmark. In addition to the similar algorithm used in a few places of SRE_MATCH, restore lastindex when restoring lastmark. (SRE_MATCH): Replace lastmark inline restoring by lastmark_restore(), function. Also include it where missing. In SRE_OP_MARK, set lastindex only if i > lastmark. * Lib/test/re_tests.py * Lib/test/test_sre.py Included regression tests for the fixed bugs. * Misc/NEWS Mention fixes.
1 parent 3c2c433 commit 4e7be06

4 files changed

Lines changed: 33 additions & 18 deletions

File tree

Lib/test/re_tests.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,8 @@
646646
(r'a[^>]*?b', 'a>b', FAIL),
647647
# bug 490573: minimizing repeat problem
648648
(r'^a*?$', 'foo', FAIL),
649+
# bug 470582: nested groups problem
650+
(r'^((a)c)?(ab)$', 'ab', SUCCEED, 'g1+"-"+g2+"-"+g3', 'None-None-ab'),
649651
]
650652

651653
try:

Lib/test/test_sre.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ def test(expression, result, exception=None):
7878
test(r"""sre.match(r'(a)|(b)', 'b').end(1)""", -1)
7979
test(r"""sre.match(r'(a)|(b)', 'b').span(1)""", (-1, -1))
8080

81+
# bug described in patch 527371
82+
test(r"""sre.match(r'(a)?a','a').lastindex""", None)
83+
test(r"""sre.match(r'(a)(b)?b','ab').lastindex""", 1)
84+
test(r"""sre.match(r'(?P<a>a)(?P<b>b)?b','ab').lastgroup""", 'a')
85+
8186
if verbose:
8287
print 'Running tests on sre.sub'
8388

Misc/NEWS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,13 @@ Extension modules
352352
to the value of the PYTHON_API_VERSION macro with which the
353353
interpreter was compiled.
354354

355+
- Fixed bug #470582: sre module would return a tuple (None, 'a', 'ab')
356+
when applying the regular expression '^((a)c)?(ab)$' on 'ab'. It now
357+
returns (None, None, 'ab'), as expected. Also fixed handling of
358+
lastindex/lastgroup match attributes in a similar cases. For example,
359+
when running the expression r'(a)(b)?b' over 'ab', lastindex must be
360+
1, not 2.
361+
355362
Library
356363
-------
357364

Modules/_sre.c

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,18 @@ mark_restore(SRE_STATE* state, int lo, int hi)
353353
return 0;
354354
}
355355

356+
void lastmark_restore(SRE_STATE *state, int lastmark)
357+
{
358+
if (state->lastmark > lastmark) {
359+
memset(
360+
state->mark + lastmark + 1, 0,
361+
(state->lastmark - lastmark) * sizeof(void*)
362+
);
363+
state->lastmark = lastmark;
364+
state->lastindex = (lastmark == 0) ? -1 : (lastmark-1)/2+1;
365+
}
366+
}
367+
356368
/* generate 8-bit version */
357369

358370
#define SRE_CHAR unsigned char
@@ -860,10 +872,11 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
860872
/* <MARK> <gid> */
861873
TRACE(("|%p|%p|MARK %d\n", pattern, ptr, pattern[0]));
862874
i = pattern[0];
863-
if (i & 1)
864-
state->lastindex = i/2 + 1;
865-
if (i > state->lastmark)
875+
if (i > state->lastmark) {
866876
state->lastmark = i;
877+
if (i & 1)
878+
state->lastindex = i/2 + 1;
879+
}
867880
state->mark[i] = ptr;
868881
pattern++;
869882
break;
@@ -920,13 +933,7 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
920933
i = SRE_MATCH(state, pattern + 1, level + 1);
921934
if (i)
922935
return i;
923-
if (state->lastmark > lastmark) {
924-
memset(
925-
state->mark + lastmark + 1, 0,
926-
(state->lastmark - lastmark) * sizeof(void*)
927-
);
928-
state->lastmark = lastmark;
929-
}
936+
lastmark_restore(state, lastmark);
930937
}
931938
return 0;
932939

@@ -997,13 +1004,7 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
9971004
return i;
9981005
ptr--;
9991006
count--;
1000-
if (state->lastmark > lastmark) {
1001-
memset(
1002-
state->mark + lastmark + 1, 0,
1003-
(state->lastmark - lastmark) * sizeof(void*)
1004-
);
1005-
state->lastmark = lastmark;
1006-
}
1007+
lastmark_restore(state, lastmark);
10071008
}
10081009
}
10091010
return 0;
@@ -1071,9 +1072,9 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
10711072
if (i)
10721073
return i;
10731074
i = mark_restore(state, 0, lastmark);
1074-
state->lastmark = lastmark;
10751075
if (i < 0)
10761076
return i;
1077+
lastmark_restore(state, lastmark);
10771078
rp->count = count - 1;
10781079
state->ptr = ptr;
10791080
}

0 commit comments

Comments
 (0)