From 00326a63ed6b07acfe437ccae1253b593463c75b Mon Sep 17 00:00:00 2001 From: Ali Mohammad Pur Date: Wed, 9 Nov 2022 21:34:36 +0330 Subject: [PATCH] LibRegex: Don't treat ForkReplace* as new forks --- Tests/LibRegex/Regex.cpp | 6 ++++++ Userland/Libraries/LibRegex/RegexByteCode.cpp | 13 +++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Tests/LibRegex/Regex.cpp b/Tests/LibRegex/Regex.cpp index abcfa93513..15e972a24d 100644 --- a/Tests/LibRegex/Regex.cpp +++ b/Tests/LibRegex/Regex.cpp @@ -1067,6 +1067,12 @@ TEST_CASE(negative_lookahead) EXPECT_EQ(re.match(":1"sv).success, false); EXPECT_EQ(re.match(":foobar"sv).success, true); } + { + // Correctly count forks with nested groups and optimised loops + Regex re("^((?:[^\\n]|\\n(?! *\\n))+)(?:\\n *)+\\n"); + EXPECT_EQ(re.match("foo\n\n"sv).success, true); + EXPECT_EQ(re.match("foo\n"sv).success, false); + } } TEST_CASE(single_match_flag) diff --git a/Userland/Libraries/LibRegex/RegexByteCode.cpp b/Userland/Libraries/LibRegex/RegexByteCode.cpp index e0c0ca4a27..e94ec356da 100644 --- a/Userland/Libraries/LibRegex/RegexByteCode.cpp +++ b/Userland/Libraries/LibRegex/RegexByteCode.cpp @@ -267,7 +267,6 @@ ALWAYS_INLINE ExecutionResult OpCode_ForkReplaceStay::execute(MatchInput const& { state.fork_at_position = state.instruction_position + size() + offset(); input.fork_to_replace = state.instruction_position; - state.forks_since_last_save++; return ExecutionResult::Fork_PrioLow; } @@ -384,8 +383,10 @@ ALWAYS_INLINE ExecutionResult OpCode_SaveRightCaptureGroup::execute(MatchInput c { auto& match = state.capture_group_matches.at(input.match_index).at(id()); auto start_position = match.left_column; - if (state.string_position < start_position) + if (state.string_position < start_position) { + dbgln("Right capture group {} is before left capture group {}!", state.string_position, start_position); return ExecutionResult::Failed_ExecuteLowPrioForks; + } auto length = state.string_position - start_position; @@ -1071,11 +1072,15 @@ ALWAYS_INLINE ExecutionResult OpCode_JumpNonEmpty::execute(MatchInput const& inp state.fork_at_position = state.instruction_position + size() + offset(); - if (form == OpCodeId::ForkJump) + if (form == OpCodeId::ForkJump) { + state.forks_since_last_save++; return ExecutionResult::Fork_PrioHigh; + } - if (form == OpCodeId::ForkStay) + if (form == OpCodeId::ForkStay) { + state.forks_since_last_save++; return ExecutionResult::Fork_PrioLow; + } if (form == OpCodeId::ForkReplaceStay) { input.fork_to_replace = state.instruction_position;