Bläddra i källkod

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.
Ali Mohammad Pur 3 år sedan
förälder
incheckning
3b0943d24c
2 ändrade filer med 22 tillägg och 7 borttagningar
  1. 15 0
      Tests/LibRegex/Regex.cpp
  2. 7 7
      Userland/Libraries/LibRegex/RegexOptimizer.cpp

+ 15 - 0
Tests/LibRegex/Regex.cpp

@@ -958,6 +958,21 @@ TEST_CASE(optimizer_char_class_lut)
         EXPECT_EQ(re.match("1635488940000"sv).success, false);
         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)
 TEST_CASE(posix_basic_dollar_is_end_anchor)
 {
 {
     // Ensure that a dollar sign at the end only matches the end of the line.
     // Ensure that a dollar sign at the end only matches the end of the line.

+ 7 - 7
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)
         if (left_is_empty && right_is_empty)
             return;
             return;
 
 
-        // ForkJump right (+ left.size() + 2 + right.size())
-        // (left)
-        // Jump end (+ right.size())
+        // ForkJump left (+ 2 + right.size())
         // (right)
         // (right)
+        // Jump end (+ left.size())
+        // (left)
         // LABEL end
         // LABEL end
         target.append(static_cast<ByteCodeValueType>(OpCodeId::ForkJump));
         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.extend(move(right));
+        target.append(static_cast<ByteCodeValueType>(OpCodeId::Jump));
+        target.append(left.size());
+        target.extend(move(left));
         return;
         return;
     }
     }