Преглед на файлове

LibRegex: Don't add the Repeat instruction size to its jump target

This was causing the calculated jump target to become invalid, leading
to possibly invalid optimisations and (more likely) crashes.
Fixes #21047.
Ali Mohammad Pur преди 1 година
родител
ревизия
4d71f4edc4
променени са 2 файла, в които са добавени 4 реда и са изтрити 2 реда
  1. 2 0
      Tests/LibRegex/Regex.cpp
  2. 2 2
      Userland/Libraries/LibRegex/RegexOptimizer.cpp

+ 2 - 0
Tests/LibRegex/Regex.cpp

@@ -1053,6 +1053,8 @@ TEST_CASE(optimizer_alternation)
         Tuple { "\\bDroid\\b.*Build|XT912|XT928|XT926|XT915|XT919|XT925|XT1021|\\bMoto E\\b|XT1068|XT1092|XT1052"sv, "XT1068"sv, 6u },
         // Backwards jumps to IP 0 are normal jumps too.
         Tuple { "^(\\d+|x)"sv, "42"sv, 2u },
+        // `Repeat' does not add its insn size to the jump target.
+        Tuple { "[0-9]{2}|[0-9]"sv, "92"sv, 2u },
     };
 
     for (auto& test : tests) {

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

@@ -907,7 +907,7 @@ void Optimizer::append_alternation(ByteCode& target, Span<ByteCode> alternatives
                 has_any_backwards_jump |= static_cast<OpCode_ForkReplaceStay const&>(opcode).offset() < 0;
                 break;
             case OpCodeId::Repeat:
-                incoming_jump_edges.ensure(static_cast<OpCode_Repeat const&>(opcode).offset() + state.instruction_position).append({ opcode_bytes });
+                incoming_jump_edges.ensure(state.instruction_position - static_cast<OpCode_Repeat const&>(opcode).offset()).append({ opcode_bytes });
                 has_any_backwards_jump = true;
                 break;
             default:
@@ -1139,7 +1139,7 @@ void Optimizer::append_alternation(ByteCode& target, Span<ByteCode> alternatives
                     jump_offset = static_cast<OpCode_ForkReplaceStay const&>(opcode).offset();
                     break;
                 case OpCodeId::Repeat:
-                    jump_offset = static_cast<ssize_t>(0) - static_cast<ssize_t>(static_cast<OpCode_Repeat const&>(opcode).offset());
+                    jump_offset = static_cast<ssize_t>(0) - static_cast<ssize_t>(static_cast<OpCode_Repeat const&>(opcode).offset()) - static_cast<ssize_t>(opcode.size());
                     break;
                 default:
                     is_jump = false;