Fix regex lazy loop handling of backtracking state at max iteration limit#97890
Fix regex lazy loop handling of backtracking state at max iteration limit#97890stephentoub merged 3 commits intodotnet:mainfrom
Conversation
…imit Upon entering a lazy loop, state is pushed onto the backtracking stack if the lazy loop might be backtracked into. That state is then dutifully popped off when unwinding the loop due to failure to match. However, if the loop successfully matches its maximum number of times but still fails because of a failure after the lazy loop, the state still needs to be popped off the stack, but isn't. This fixes that.
|
Tagging subscribers to this area: @dotnet/area-system-text-regularexpressions Issue DetailsUpon entering a lazy loop, state is pushed onto the backtracking stack if the lazy loop might be backtracked into. That state is then dutifully popped off when unwinding the loop due to failure to match. However, if the loop successfully matches its maximum number of times but still fails because of a failure after the lazy loop, the state still needs to be popped off the stack, but isn't (in the compiler and source generator; it's fine in the interpreter). This fixes that.
|
joperezr
left a comment
There was a problem hiding this comment.
Change LGTM. IIRC there has been several edge cases where we have to do fixes like this due to the state not being reset appropriately. I suppose there is no good way for us to ensure that each time you enter a construct we "save" the stack depth and info so that when we exit it we validate that we indeed popped the state to the right place.
Yeah, this is maybe the third I can remember from the last couple of years where we hit something like that. I've had a similar idea, where in a debug build the source generator could emit an additional stack in order to verify that the state being popped is the state that's expected, but I've not had time to implement such a thing. |
|
/backport to release/8.0-staging |
|
Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/7768960657 |
Upon entering a lazy loop, state is pushed onto the backtracking stack if the lazy loop might be backtracked into. That state is then dutifully popped off when unwinding the loop due to failure to match. However, if the loop successfully matches its maximum number of times but still fails because of a failure after the lazy loop, the state still needs to be popped off the stack, but isn't (in the compiler and source generator; it's fine in the interpreter). This fixes that.