From eee90f4aa23afd66ce6007faf4943d4ab56d4f22 Mon Sep 17 00:00:00 2001 From: Ali Mohammad Pur Date: Tue, 10 Dec 2024 23:34:29 +0100 Subject: [PATCH] LibRegex: Treat checks against nonexistent checkpoints as empty Due to optimiser shenanigans in the tree alternative form, some JumpNonEmpty ops might be moved before their Checkpoint instruction. It is safe to assume the distance between the nonexistent checkpoint and the current op is zero, so just do that. --- Libraries/LibRegex/RegexByteCode.cpp | 2 +- Tests/LibRegex/Regex.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Libraries/LibRegex/RegexByteCode.cpp b/Libraries/LibRegex/RegexByteCode.cpp index 5afe9d8ca1b..7ff0b4a6dfb 100644 --- a/Libraries/LibRegex/RegexByteCode.cpp +++ b/Libraries/LibRegex/RegexByteCode.cpp @@ -1085,7 +1085,7 @@ ALWAYS_INLINE ExecutionResult OpCode_Checkpoint::execute(MatchInput const&, Matc ALWAYS_INLINE ExecutionResult OpCode_JumpNonEmpty::execute(MatchInput const& input, MatchState& state) const { u64 current_position = state.string_position; - auto checkpoint_position = state.checkpoints[checkpoint()]; + auto checkpoint_position = state.checkpoints.get(checkpoint()).value_or(0); if (checkpoint_position != 0 && checkpoint_position != current_position + 1) { auto form = this->form(); diff --git a/Tests/LibRegex/Regex.cpp b/Tests/LibRegex/Regex.cpp index 0f11865fc64..d32b5e820f1 100644 --- a/Tests/LibRegex/Regex.cpp +++ b/Tests/LibRegex/Regex.cpp @@ -1087,6 +1087,8 @@ TEST_CASE(optimizer_alternation) Tuple { "[0-9]{2}|[0-9]"sv, "92"sv, 2u }, // Don't ForkJump to the next instruction, rerunning it would produce the same result. see ladybird#2398. Tuple { "(xxxxxxxxxxxxxxxxxxxxxxx|xxxxxxxxxxxxxxxxxxxxxxx)?b"sv, "xxxxxxxxxxxxxxxxxxxxxxx"sv, 0u }, + // Don't take the jump in JumpNonEmpty with nonexistent checkpoints (also don't crash). + Tuple { "(?!\\d*|[g-ta-r]+|[h-l]|\\S|\\S|\\S){,9}|\\S{7,8}|\\d|(?)|[c-mj-tb-o]*|\\s"sv, "rjvogg7pm|li4nmct mjb2|pk7s8e0"sv, 0u }, }; for (auto& test : tests) {