Переглянути джерело

LibRegex: Correct jump offset to the start of the loop block

Previously we were jumping to the new end of the previous block (created
by the newly inserted ForkStay), correct the offset to jump to the
correct block as shown in the comments.
Fixes #12033.
Ali Mohammad Pur 3 роки тому
батько
коміт
bfe8f312f3

+ 2 - 0
Tests/LibRegex/Regex.cpp

@@ -914,6 +914,8 @@ TEST_CASE(optimizer_atomic_groups)
         Tuple { "(1+)\\1"sv, "11"sv, true },
         Tuple { "(1+)1"sv, "11"sv, true },
         Tuple { "(1+)0"sv, "10"sv, true },
+        // Rewrite should not skip over first required iteration of <x>+.
+        Tuple { "a+"sv, ""sv, false },
     };
 
     for (auto& test : tests) {

+ 3 - 3
Userland/Libraries/LibRegex/RegexOptimizer.cpp

@@ -376,7 +376,7 @@ void Regex<Parser>::attempt_rewrite_loops_as_atomic_groups(BasicBlockList const&
             if (candidate.new_target_block.has_value()) {
                 // Insert a fork-stay targeted at the second block.
                 bytecode.insert(candidate.forking_block.start, (ByteCodeValueType)OpCodeId::ForkStay);
-                bytecode.insert(candidate.forking_block.start + 1, candidate.new_target_block->start - candidate.forking_block.start);
+                bytecode.insert(candidate.forking_block.start + 1, candidate.new_target_block->start - candidate.forking_block.start + 2);
                 needed_patches.insert(candidate.forking_block.start, 2u);
             }
         }
@@ -427,9 +427,9 @@ void Regex<Parser>::attempt_rewrite_loops_as_atomic_groups(BasicBlockList const&
                     if (patch_it.key() == ip)
                         return;
 
-                    if (patch_point.value < 0 && target_offset < patch_it.key() && ip > patch_it.key())
+                    if (patch_point.value < 0 && target_offset <= patch_it.key() && ip > patch_it.key())
                         bytecode[patch_point.offset] += (patch_point.should_negate ? 1 : -1) * (*patch_it);
-                    else if (patch_point.value > 0 && target_offset > patch_it.key() && ip < patch_it.key())
+                    else if (patch_point.value > 0 && target_offset >= patch_it.key() && ip < patch_it.key())
                         bytecode[patch_point.offset] += (patch_point.should_negate ? -1 : 1) * (*patch_it);
                 };