summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Mohammad Pur <ali.mpfard@gmail.com>2022-02-14 12:03:33 +0330
committerAndreas Kling <kling@serenityos.org>2022-02-14 11:30:50 +0100
commit3b0943d24cf03f27a69debb3472d1f5e8a6e029b (patch)
tree48c33d985650399ca1b88119d876a3f4a68f82c3
parent76e99fa6c8213ef8788ecb05dd45fbd80c6a9483 (diff)
downloadserenity-3b0943d24cf03f27a69debb3472d1f5e8a6e029b.zip
LibRegex: Correct the alternative matching order when one is empty
Previously we were compiling `/a|/` into what effectively would be `/|a`, which is clearly incorrect.
-rw-r--r--Tests/LibRegex/Regex.cpp15
-rw-r--r--Userland/Libraries/LibRegex/RegexOptimizer.cpp14
2 files changed, 22 insertions, 7 deletions
diff --git a/Tests/LibRegex/Regex.cpp b/Tests/LibRegex/Regex.cpp
index 7dbf8c6d3d..6b8f5f559c 100644
--- a/Tests/LibRegex/Regex.cpp
+++ b/Tests/LibRegex/Regex.cpp
@@ -958,6 +958,21 @@ TEST_CASE(optimizer_char_class_lut)
EXPECT_EQ(re.match("1635488940000"sv).success, false);
}
+TEST_CASE(optimizer_alternation)
+{
+ Array tests {
+ // Pattern, Subject, Expected length
+ Tuple { "a|"sv, "a"sv, 1u },
+ };
+
+ for (auto& test : tests) {
+ Regex<ECMA262> re(test.get<0>());
+ auto result = re.match(test.get<1>());
+ EXPECT(result.success);
+ EXPECT_EQ(result.matches.first().view.length(), test.get<2>());
+ }
+}
+
TEST_CASE(posix_basic_dollar_is_end_anchor)
{
// Ensure that a dollar sign at the end only matches the end of the line.
diff --git a/Userland/Libraries/LibRegex/RegexOptimizer.cpp b/Userland/Libraries/LibRegex/RegexOptimizer.cpp
index 969f37143c..f0d2912965 100644
--- a/Userland/Libraries/LibRegex/RegexOptimizer.cpp
+++ b/Userland/Libraries/LibRegex/RegexOptimizer.cpp
@@ -450,17 +450,17 @@ void Optimizer::append_alternation(ByteCode& target, ByteCode&& left, ByteCode&&
if (left_is_empty && right_is_empty)
return;
- // ForkJump right (+ left.size() + 2 + right.size())
- // (left)
- // Jump end (+ right.size())
+ // ForkJump left (+ 2 + right.size())
// (right)
+ // Jump end (+ left.size())
+ // (left)
// LABEL end
target.append(static_cast<ByteCodeValueType>(OpCodeId::ForkJump));
- target.append(left.size() + 2 + right.size());
- target.extend(move(left));
- target.append(static_cast<ByteCodeValueType>(OpCodeId::Jump));
- target.append(right.size());
+ target.append(2 + right.size());
target.extend(move(right));
+ target.append(static_cast<ByteCodeValueType>(OpCodeId::Jump));
+ target.append(left.size());
+ target.extend(move(left));
return;
}