diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c index 7d03b909226f24..e742a25e4891fc 100644 --- a/Modules/_sre/sre.c +++ b/Modules/_sre/sre.c @@ -738,6 +738,7 @@ state_init(SRE_STATE* state, PatternObject* pattern, PyObject* string, state->charsize = charsize; state->match_all = 0; state->must_advance = 0; + state->save_marks = 0; state->debug = ((pattern->flags & SRE_FLAG_DEBUG) != 0); state->beginning = ptr; diff --git a/Modules/_sre/sre.h b/Modules/_sre/sre.h index 42681c2addf3c2..bec4ae21d1e10f 100644 --- a/Modules/_sre/sre.h +++ b/Modules/_sre/sre.h @@ -97,6 +97,10 @@ typedef struct { int lastmark; int lastindex; const void** mark; + int save_marks; /* if nonzero, save and restore mark values on + backtracking instead of only rewinding the lastmark + index; counts enclosing repeat contexts and + possessive bodies */ /* dynamically allocated stuff */ char* data_stack; size_t data_stack_size; diff --git a/Modules/_sre/sre_lib.h b/Modules/_sre/sre_lib.h index 6e6ae46f05a50f..444cd39d2fed28 100644 --- a/Modules/_sre/sre_lib.h +++ b/Modules/_sre/sre_lib.h @@ -863,7 +863,7 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) /* <0=skip> code ... */ TRACE(("|%p|%p|BRANCH\n", pattern, ptr)); LASTMARK_SAVE(); - if (state->repeat) + if (state->save_marks) MARK_PUSH(ctx->lastmark); for (; pattern[0]; pattern += pattern[0]) { if (pattern[1] == SRE_OP_LITERAL && @@ -878,16 +878,16 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) state->ptr = ptr; DO_JUMP(JUMP_BRANCH, jump_branch, pattern+1); if (ret) { - if (state->repeat) + if (state->save_marks) MARK_POP_DISCARD(ctx->lastmark); RETURN_ON_ERROR(ret); RETURN_SUCCESS; } - if (state->repeat) + if (state->save_marks) MARK_POP_KEEP(ctx->lastmark); LASTMARK_RESTORE(); } - if (state->repeat) + if (state->save_marks) MARK_POP_DISCARD(ctx->lastmark); RETURN_FAILURE; @@ -933,7 +933,7 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) } LASTMARK_SAVE(); - if (state->repeat) + if (state->save_marks) MARK_PUSH(ctx->lastmark); if (pattern[pattern[0]] == SRE_OP_LITERAL) { @@ -952,19 +952,19 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) DO_JUMP(JUMP_REPEAT_ONE_1, jump_repeat_one_1, pattern+pattern[0]); if (ret) { - if (state->repeat) + if (state->save_marks) MARK_POP_DISCARD(ctx->lastmark); RETURN_ON_ERROR(ret); RETURN_SUCCESS; } - if (state->repeat) + if (state->save_marks) MARK_POP_KEEP(ctx->lastmark); LASTMARK_RESTORE(); ptr--; ctx->count--; } - if (state->repeat) + if (state->save_marks) MARK_POP_DISCARD(ctx->lastmark); } else { /* general case */ @@ -973,19 +973,19 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) DO_JUMP(JUMP_REPEAT_ONE_2, jump_repeat_one_2, pattern+pattern[0]); if (ret) { - if (state->repeat) + if (state->save_marks) MARK_POP_DISCARD(ctx->lastmark); RETURN_ON_ERROR(ret); RETURN_SUCCESS; } - if (state->repeat) + if (state->save_marks) MARK_POP_KEEP(ctx->lastmark); LASTMARK_RESTORE(); ptr--; ctx->count--; } - if (state->repeat) + if (state->save_marks) MARK_POP_DISCARD(ctx->lastmark); } RETURN_FAILURE; @@ -1035,7 +1035,7 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) } else { /* general case */ LASTMARK_SAVE(); - if (state->repeat) + if (state->save_marks) MARK_PUSH(ctx->lastmark); while ((Py_ssize_t)pattern[2] == SRE_MAXREPEAT @@ -1044,12 +1044,12 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) DO_JUMP(JUMP_MIN_REPEAT_ONE,jump_min_repeat_one, pattern+pattern[0]); if (ret) { - if (state->repeat) + if (state->save_marks) MARK_POP_DISCARD(ctx->lastmark); RETURN_ON_ERROR(ret); RETURN_SUCCESS; } - if (state->repeat) + if (state->save_marks) MARK_POP_KEEP(ctx->lastmark); LASTMARK_RESTORE(); @@ -1063,7 +1063,7 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) ptr++; ctx->count++; } - if (state->repeat) + if (state->save_marks) MARK_POP_DISCARD(ctx->lastmark); } RETURN_FAILURE; @@ -1140,10 +1140,12 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) ctx->u.rep->prev = state->repeat; ctx->u.rep->last_ptr = NULL; state->repeat = ctx->u.rep; + state->save_marks++; state->ptr = ptr; DO_JUMP(JUMP_REPEAT, jump_repeat, pattern+pattern[0]); state->repeat = ctx->u.rep->prev; + state->save_marks--; repeat_pool_free(state, ctx->u.rep); if (ret) { @@ -1212,8 +1214,10 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) /* cannot match more repeated items here. make sure the tail matches */ state->repeat = ctx->u.rep->prev; + state->save_marks--; DO_JUMP(JUMP_MAX_UNTIL_3, jump_max_until_3, pattern); state->repeat = ctx->u.rep; // restore repeat before return + state->save_marks++; RETURN_ON_SUCCESS(ret); state->ptr = ptr; @@ -1250,22 +1254,26 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) /* see if the tail matches */ state->repeat = ctx->u.rep->prev; + state->save_marks--; LASTMARK_SAVE(); - if (state->repeat) + if (state->save_marks) MARK_PUSH(ctx->lastmark); DO_JUMP(JUMP_MIN_UNTIL_2, jump_min_until_2, pattern); - SRE_REPEAT *repeat_of_tail = state->repeat; + /* save_marks is balanced across the jump, so this equals the + value tested for MARK_PUSH above */ + int pushed = state->save_marks != 0; state->repeat = ctx->u.rep; // restore repeat before return + state->save_marks++; if (ret) { - if (repeat_of_tail) + if (pushed) MARK_POP_DISCARD(ctx->lastmark); RETURN_ON_ERROR(ret); RETURN_SUCCESS; } - if (repeat_of_tail) + if (pushed) MARK_POP(ctx->lastmark); LASTMARK_RESTORE(); @@ -1302,16 +1310,10 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) pointer */ state->ptr = ptr; - /* Set state->repeat to non-NULL */ - ctx->u.rep = repeat_pool_malloc(state); - if (!ctx->u.rep) { - RETURN_ERROR(SRE_ERROR_MEMORY); - } - ctx->u.rep->count = -1; - ctx->u.rep->pattern = NULL; - ctx->u.rep->prev = state->repeat; - ctx->u.rep->last_ptr = NULL; - state->repeat = ctx->u.rep; + /* Capture groups in the body can be revisited on backtracking + between iterations, so their marks must be saved and restored, + as is done inside a repeat. */ + state->save_marks++; /* Initialize Count to 0 */ ctx->count = 0; @@ -1327,9 +1329,7 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) } else { state->ptr = ptr; - /* Restore state->repeat */ - state->repeat = ctx->u.rep->prev; - repeat_pool_free(state, ctx->u.rep); + state->save_marks--; RETURN_FAILURE; } } @@ -1402,9 +1402,7 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) } } - /* Restore state->repeat */ - state->repeat = ctx->u.rep->prev; - repeat_pool_free(state, ctx->u.rep); + state->save_marks--; /* Evaluate Tail */ /* 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) if ((uintptr_t)(ptr - (SRE_CHAR *)state->beginning) >= pattern[1]) { state->ptr = ptr - pattern[1]; LASTMARK_SAVE(); - if (state->repeat) + if (state->save_marks) MARK_PUSH(ctx->lastmark); DO_JUMP0(JUMP_ASSERT_NOT, jump_assert_not, pattern+2); if (ret) { - if (state->repeat) + if (state->save_marks) MARK_POP_DISCARD(ctx->lastmark); RETURN_ON_ERROR(ret); RETURN_FAILURE; } - if (state->repeat) + if (state->save_marks) MARK_POP(ctx->lastmark); LASTMARK_RESTORE(); }