From 4d71f4edc46cec682dc835400243290239e09af2 Mon Sep 17 00:00:00 2001 From: Ali Mohammad Pur Date: Thu, 14 Sep 2023 05:43:29 +0330 Subject: [PATCH] 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. --- Tests/LibRegex/Regex.cpp | 2 ++ Userland/Libraries/LibRegex/RegexOptimizer.cpp | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Tests/LibRegex/Regex.cpp b/Tests/LibRegex/Regex.cpp index bdaed954f2..c060874e29 100644 --- a/Tests/LibRegex/Regex.cpp +++ b/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) { diff --git a/Userland/Libraries/LibRegex/RegexOptimizer.cpp b/Userland/Libraries/LibRegex/RegexOptimizer.cpp index 2672ddfc11..5da5375008 100644 --- a/Userland/Libraries/LibRegex/RegexOptimizer.cpp +++ b/Userland/Libraries/LibRegex/RegexOptimizer.cpp @@ -907,7 +907,7 @@ void Optimizer::append_alternation(ByteCode& target, Span alternatives has_any_backwards_jump |= static_cast(opcode).offset() < 0; break; case OpCodeId::Repeat: - incoming_jump_edges.ensure(static_cast(opcode).offset() + state.instruction_position).append({ opcode_bytes }); + incoming_jump_edges.ensure(state.instruction_position - static_cast(opcode).offset()).append({ opcode_bytes }); has_any_backwards_jump = true; break; default: @@ -1139,7 +1139,7 @@ void Optimizer::append_alternation(ByteCode& target, Span alternatives jump_offset = static_cast(opcode).offset(); break; case OpCodeId::Repeat: - jump_offset = static_cast(0) - static_cast(static_cast(opcode).offset()); + jump_offset = static_cast(0) - static_cast(static_cast(opcode).offset()) - static_cast(opcode.size()); break; default: is_jump = false;