Skip to content

Commit b175621

Browse files
gh-152026: Track mark-saving contexts with a counter (GH-153160)
Replace the state->repeat checks that guard mark saving and restoring with an explicit save_marks counter maintained where repeat and possessive contexts are entered and left. Each push is now paired with a pop decided by the same condition. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent ad54b91 commit b175621

3 files changed

Lines changed: 41 additions & 38 deletions

File tree

Modules/_sre/sre.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,7 @@ state_init(SRE_STATE* state, PatternObject* pattern, PyObject* string,
738738
state->charsize = charsize;
739739
state->match_all = 0;
740740
state->must_advance = 0;
741+
state->save_marks = 0;
741742
state->debug = ((pattern->flags & SRE_FLAG_DEBUG) != 0);
742743

743744
state->beginning = ptr;

Modules/_sre/sre.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ typedef struct {
9797
int lastmark;
9898
int lastindex;
9999
const void** mark;
100+
int save_marks; /* if nonzero, save and restore mark values on
101+
backtracking instead of only rewinding the lastmark
102+
index; counts enclosing repeat contexts and
103+
possessive bodies */
100104
/* dynamically allocated stuff */
101105
char* data_stack;
102106
size_t data_stack_size;

Modules/_sre/sre_lib.h

Lines changed: 36 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -863,7 +863,7 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel)
863863
/* <BRANCH> <0=skip> code <JUMP> ... <NULL> */
864864
TRACE(("|%p|%p|BRANCH\n", pattern, ptr));
865865
LASTMARK_SAVE();
866-
if (state->repeat)
866+
if (state->save_marks)
867867
MARK_PUSH(ctx->lastmark);
868868
for (; pattern[0]; pattern += pattern[0]) {
869869
if (pattern[1] == SRE_OP_LITERAL &&
@@ -878,16 +878,16 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel)
878878
state->ptr = ptr;
879879
DO_JUMP(JUMP_BRANCH, jump_branch, pattern+1);
880880
if (ret) {
881-
if (state->repeat)
881+
if (state->save_marks)
882882
MARK_POP_DISCARD(ctx->lastmark);
883883
RETURN_ON_ERROR(ret);
884884
RETURN_SUCCESS;
885885
}
886-
if (state->repeat)
886+
if (state->save_marks)
887887
MARK_POP_KEEP(ctx->lastmark);
888888
LASTMARK_RESTORE();
889889
}
890-
if (state->repeat)
890+
if (state->save_marks)
891891
MARK_POP_DISCARD(ctx->lastmark);
892892
RETURN_FAILURE;
893893

@@ -933,7 +933,7 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel)
933933
}
934934

935935
LASTMARK_SAVE();
936-
if (state->repeat)
936+
if (state->save_marks)
937937
MARK_PUSH(ctx->lastmark);
938938

939939
if (pattern[pattern[0]] == SRE_OP_LITERAL) {
@@ -952,19 +952,19 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel)
952952
DO_JUMP(JUMP_REPEAT_ONE_1, jump_repeat_one_1,
953953
pattern+pattern[0]);
954954
if (ret) {
955-
if (state->repeat)
955+
if (state->save_marks)
956956
MARK_POP_DISCARD(ctx->lastmark);
957957
RETURN_ON_ERROR(ret);
958958
RETURN_SUCCESS;
959959
}
960-
if (state->repeat)
960+
if (state->save_marks)
961961
MARK_POP_KEEP(ctx->lastmark);
962962
LASTMARK_RESTORE();
963963

964964
ptr--;
965965
ctx->count--;
966966
}
967-
if (state->repeat)
967+
if (state->save_marks)
968968
MARK_POP_DISCARD(ctx->lastmark);
969969
} else {
970970
/* general case */
@@ -973,19 +973,19 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel)
973973
DO_JUMP(JUMP_REPEAT_ONE_2, jump_repeat_one_2,
974974
pattern+pattern[0]);
975975
if (ret) {
976-
if (state->repeat)
976+
if (state->save_marks)
977977
MARK_POP_DISCARD(ctx->lastmark);
978978
RETURN_ON_ERROR(ret);
979979
RETURN_SUCCESS;
980980
}
981-
if (state->repeat)
981+
if (state->save_marks)
982982
MARK_POP_KEEP(ctx->lastmark);
983983
LASTMARK_RESTORE();
984984

985985
ptr--;
986986
ctx->count--;
987987
}
988-
if (state->repeat)
988+
if (state->save_marks)
989989
MARK_POP_DISCARD(ctx->lastmark);
990990
}
991991
RETURN_FAILURE;
@@ -1035,7 +1035,7 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel)
10351035
} else {
10361036
/* general case */
10371037
LASTMARK_SAVE();
1038-
if (state->repeat)
1038+
if (state->save_marks)
10391039
MARK_PUSH(ctx->lastmark);
10401040

10411041
while ((Py_ssize_t)pattern[2] == SRE_MAXREPEAT
@@ -1044,12 +1044,12 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel)
10441044
DO_JUMP(JUMP_MIN_REPEAT_ONE,jump_min_repeat_one,
10451045
pattern+pattern[0]);
10461046
if (ret) {
1047-
if (state->repeat)
1047+
if (state->save_marks)
10481048
MARK_POP_DISCARD(ctx->lastmark);
10491049
RETURN_ON_ERROR(ret);
10501050
RETURN_SUCCESS;
10511051
}
1052-
if (state->repeat)
1052+
if (state->save_marks)
10531053
MARK_POP_KEEP(ctx->lastmark);
10541054
LASTMARK_RESTORE();
10551055

@@ -1063,7 +1063,7 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel)
10631063
ptr++;
10641064
ctx->count++;
10651065
}
1066-
if (state->repeat)
1066+
if (state->save_marks)
10671067
MARK_POP_DISCARD(ctx->lastmark);
10681068
}
10691069
RETURN_FAILURE;
@@ -1140,10 +1140,12 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel)
11401140
ctx->u.rep->prev = state->repeat;
11411141
ctx->u.rep->last_ptr = NULL;
11421142
state->repeat = ctx->u.rep;
1143+
state->save_marks++;
11431144

11441145
state->ptr = ptr;
11451146
DO_JUMP(JUMP_REPEAT, jump_repeat, pattern+pattern[0]);
11461147
state->repeat = ctx->u.rep->prev;
1148+
state->save_marks--;
11471149
repeat_pool_free(state, ctx->u.rep);
11481150

11491151
if (ret) {
@@ -1212,8 +1214,10 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel)
12121214
/* cannot match more repeated items here. make sure the
12131215
tail matches */
12141216
state->repeat = ctx->u.rep->prev;
1217+
state->save_marks--;
12151218
DO_JUMP(JUMP_MAX_UNTIL_3, jump_max_until_3, pattern);
12161219
state->repeat = ctx->u.rep; // restore repeat before return
1220+
state->save_marks++;
12171221

12181222
RETURN_ON_SUCCESS(ret);
12191223
state->ptr = ptr;
@@ -1250,22 +1254,26 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel)
12501254

12511255
/* see if the tail matches */
12521256
state->repeat = ctx->u.rep->prev;
1257+
state->save_marks--;
12531258

12541259
LASTMARK_SAVE();
1255-
if (state->repeat)
1260+
if (state->save_marks)
12561261
MARK_PUSH(ctx->lastmark);
12571262

12581263
DO_JUMP(JUMP_MIN_UNTIL_2, jump_min_until_2, pattern);
1259-
SRE_REPEAT *repeat_of_tail = state->repeat;
1264+
/* save_marks is balanced across the jump, so this equals the
1265+
value tested for MARK_PUSH above */
1266+
int pushed = state->save_marks != 0;
12601267
state->repeat = ctx->u.rep; // restore repeat before return
1268+
state->save_marks++;
12611269

12621270
if (ret) {
1263-
if (repeat_of_tail)
1271+
if (pushed)
12641272
MARK_POP_DISCARD(ctx->lastmark);
12651273
RETURN_ON_ERROR(ret);
12661274
RETURN_SUCCESS;
12671275
}
1268-
if (repeat_of_tail)
1276+
if (pushed)
12691277
MARK_POP(ctx->lastmark);
12701278
LASTMARK_RESTORE();
12711279

@@ -1302,16 +1310,10 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel)
13021310
pointer */
13031311
state->ptr = ptr;
13041312

1305-
/* Set state->repeat to non-NULL */
1306-
ctx->u.rep = repeat_pool_malloc(state);
1307-
if (!ctx->u.rep) {
1308-
RETURN_ERROR(SRE_ERROR_MEMORY);
1309-
}
1310-
ctx->u.rep->count = -1;
1311-
ctx->u.rep->pattern = NULL;
1312-
ctx->u.rep->prev = state->repeat;
1313-
ctx->u.rep->last_ptr = NULL;
1314-
state->repeat = ctx->u.rep;
1313+
/* Capture groups in the body can be revisited on backtracking
1314+
between iterations, so their marks must be saved and restored,
1315+
as is done inside a repeat. */
1316+
state->save_marks++;
13151317

13161318
/* Initialize Count to 0 */
13171319
ctx->count = 0;
@@ -1327,9 +1329,7 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel)
13271329
}
13281330
else {
13291331
state->ptr = ptr;
1330-
/* Restore state->repeat */
1331-
state->repeat = ctx->u.rep->prev;
1332-
repeat_pool_free(state, ctx->u.rep);
1332+
state->save_marks--;
13331333
RETURN_FAILURE;
13341334
}
13351335
}
@@ -1402,9 +1402,7 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel)
14021402
}
14031403
}
14041404

1405-
/* Restore state->repeat */
1406-
state->repeat = ctx->u.rep->prev;
1407-
repeat_pool_free(state, ctx->u.rep);
1405+
state->save_marks--;
14081406

14091407
/* Evaluate Tail */
14101408
/* Jump to end of pattern indicated by skip, and then skip
@@ -1586,17 +1584,17 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel)
15861584
if ((uintptr_t)(ptr - (SRE_CHAR *)state->beginning) >= pattern[1]) {
15871585
state->ptr = ptr - pattern[1];
15881586
LASTMARK_SAVE();
1589-
if (state->repeat)
1587+
if (state->save_marks)
15901588
MARK_PUSH(ctx->lastmark);
15911589

15921590
DO_JUMP0(JUMP_ASSERT_NOT, jump_assert_not, pattern+2);
15931591
if (ret) {
1594-
if (state->repeat)
1592+
if (state->save_marks)
15951593
MARK_POP_DISCARD(ctx->lastmark);
15961594
RETURN_ON_ERROR(ret);
15971595
RETURN_FAILURE;
15981596
}
1599-
if (state->repeat)
1597+
if (state->save_marks)
16001598
MARK_POP(ctx->lastmark);
16011599
LASTMARK_RESTORE();
16021600
}

0 commit comments

Comments
 (0)