From b0e471228dd0093e6281d59f2b769079da8eeed3 Mon Sep 17 00:00:00 2001 From: Ali Mohammad Pur Date: Tue, 24 Jun 2025 16:41:28 +0200 Subject: [PATCH] LibRegex: Avoid use-after-return of MatchState in 'is_an_eligible_jump' The opcode may have last been accessed by block_satisfies_atomic_rewrite_precondition, which would set it to a state that no longer exists. Set the state to the correct one unconditionally to ensure we're looking at the right value. Fixes #5145. --- Libraries/LibRegex/RegexByteCode.h | 4 ++-- Libraries/LibRegex/RegexOptimizer.cpp | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Libraries/LibRegex/RegexByteCode.h b/Libraries/LibRegex/RegexByteCode.h index 6e3d6fdd9b9..75d54293bd7 100644 --- a/Libraries/LibRegex/RegexByteCode.h +++ b/Libraries/LibRegex/RegexByteCode.h @@ -652,7 +652,7 @@ public: ALWAYS_INLINE StringView name() const; static StringView name(OpCodeId); - ALWAYS_INLINE void set_state(MatchState& state) { m_state = &state; } + ALWAYS_INLINE void set_state(MatchState const& state) { m_state = &state; } ALWAYS_INLINE void set_bytecode(ByteCode& bytecode) { m_bytecode = &bytecode; } @@ -673,7 +673,7 @@ public: protected: ByteCode* m_bytecode { nullptr }; - MatchState* m_state { nullptr }; + MatchState const* m_state { nullptr }; }; class OpCode_Exit final : public OpCode { diff --git a/Libraries/LibRegex/RegexOptimizer.cpp b/Libraries/LibRegex/RegexOptimizer.cpp index 8e8161a997e..e00d6688f58 100644 --- a/Libraries/LibRegex/RegexOptimizer.cpp +++ b/Libraries/LibRegex/RegexOptimizer.cpp @@ -1013,8 +1013,10 @@ void Regex::attempt_rewrite_loops_as_atomic_groups(BasicBlockList const& AlternateForm form; }; Vector candidate_blocks; + auto state = MatchState::only_for_enumeration(); - auto is_an_eligible_jump = [](OpCode const& opcode, size_t ip, size_t block_start, AlternateForm alternate_form) { + auto is_an_eligible_jump = [&state](OpCode& opcode, size_t ip, size_t block_start, AlternateForm alternate_form) { + opcode.set_state(state); switch (opcode.opcode_id()) { case OpCodeId::JumpNonEmpty: { auto const& op = static_cast(opcode); @@ -1049,7 +1051,6 @@ void Regex::attempt_rewrite_loops_as_atomic_groups(BasicBlockList const& Optional fork_fallback_block; if (i + 1 < basic_blocks.size()) fork_fallback_block = basic_blocks[i + 1]; - auto state = MatchState::only_for_enumeration(); // Check if the last instruction in this block is a jump to the block itself: { state.instruction_position = forking_block.end;