From 24ea62df446cf698c5b4c5fa494b462ad7adf490 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Thu, 27 Aug 2026 01:18:11 +0000 Subject: [PATCH] llama: fix the qwen4exp PLE history seq_rm(-1) iterator invalidation and the fatal-warning build ple_hist_rm recursed over ple_hist with a range-based for and the recursive call erases the entry it is iterating when the whole sequence is removed (p0 <= 0, p1 < 0), so the loop then increments an invalidated iterator. It is unreachable today only because llama_memory_recurrent::seq_rm rejects seq_id < 0 before llama_memory_hybrid_idx::seq_rm reaches the history, which is a guard in another class. Advance past the entry before recursing. Two smaller things in the same area: - the n_toks sanity bound in ple_hist_state_read was the literal 64, which is the value of LLAMA_MAX_PLE_HEADS, not of the quantity being checked. The window is at most ple_ngram_size - 1 tokens, so the bound is LLAMA_MAX_PLE_NGRAM - 1, eight times tighter. - build_conv_state_at left mem_size unused, so -DLLAMA_FATAL_WARNINGS=ON does not compile. Predates this series; drop the line. (cherry picked from commit 6eba44a89d5f328eb4859b844e1d28fb564cbe3e) --- src/llama-memory-hybrid-idx.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/llama-memory-hybrid-idx.cpp b/src/llama-memory-hybrid-idx.cpp index 6316ab7cf3..35059baf6b 100644 --- a/src/llama-memory-hybrid-idx.cpp +++ b/src/llama-memory-hybrid-idx.cpp @@ -249,8 +249,12 @@ static void ple_hist_truncate(llama_memory_hybrid_idx::ple_history & h, llama_po void llama_memory_hybrid_idx::ple_hist_rm(llama_seq_id seq_id, llama_pos p0, llama_pos p1) { if (seq_id < 0) { - for (auto & it : ple_hist) { - ple_hist_rm(it.first, p0, p1); + // the recursive call erases seq_id's entry when the whole sequence is removed, so + // advance past it first: erase invalidates only the iterator to the erased element + for (auto it = ple_hist.begin(); it != ple_hist.end(); ) { + const llama_seq_id id = it->first; + ++it; + ple_hist_rm(id, p0, p1); } return; } @@ -433,9 +437,9 @@ void llama_memory_hybrid_idx::ple_hist_state_read(llama_io_read_i & io, llama_se io.read(&next_pos, sizeof(next_pos)); io.read(&n_toks, sizeof(n_toks)); - // the window is never longer than ple_ngram_size - 1, so a larger count is a corrupt - // blob and would size an allocation from the file - if (n_toks > 64) { + // the window is never longer than ple_ngram_size - 1; anything else is a corrupt or + // mismatched blob, and reading it would size an allocation from the file + if (n_toks > LLAMA_MAX_PLE_NGRAM - 1) { throw std::runtime_error("qwen4exp PLE history: implausible token count in state blob"); }