summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Mohammad Pur <ali.mpfard@gmail.com>2022-11-09 21:34:36 +0330
committerAndreas Kling <kling@serenityos.org>2022-11-09 21:28:54 +0100
commit00326a63ed6b07acfe437ccae1253b593463c75b (patch)
tree4d7ad16dc335155a29b599a10a65a676332bdad6
parent0ea399d8d691d4446f632f54a22942277edcb5e1 (diff)
downloadserenity-00326a63ed6b07acfe437ccae1253b593463c75b.zip
LibRegex: Don't treat ForkReplace* as new forks
-rw-r--r--Tests/LibRegex/Regex.cpp6
-rw-r--r--Userland/Libraries/LibRegex/RegexByteCode.cpp13
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<ECMA262> 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;