sampling : fix use-after-scope in grammar trigger_words path (#2221)

llama_sampler_init_grammar_impl built the trigger_words pattern in a block-scoped std::string, stored a pointer into it (trigger_pattern_c), pointed trigger_patterns at that pointer, then let the block drop both locals before llama_grammar_init_impl dereferenced trigger_patterns -- a read of a dangling pointer into freed std::string storage (UB). Hoist trigger_pattern and trigger_pattern_c to function scope so both outlive the call.
This commit is contained in:
replikeit
2026-08-01 08:55:31 +03:00
committed by GitHub
parent a8ae4fb36f
commit 8802ed2dc5
+4 -2
View File
@@ -1367,11 +1367,13 @@ struct llama_grammar* llama_sampler_init_grammar_impl(
size_t num_trigger_patterns) {
// Huh? this is not used and leaks. auto* ctx = new llama_sampler_grammar;
struct llama_grammar* grammar;
std::string trigger_pattern;
const char * trigger_pattern_c = nullptr;
if (grammar_str != nullptr && grammar_str[0] != '\0') {
// TODO: remove trigger_words support.
if (trigger_words != nullptr && num_trigger_words > 0) {
GGML_ASSERT(trigger_patterns == nullptr && num_trigger_patterns == 0);
std::string trigger_pattern("[\\s\\S]*?(");
trigger_pattern = "[\\s\\S]*?(";
for (size_t i = 0; i < num_trigger_words; ++i) {
static const std::regex special_chars("[.^$|()*+?\\[\\]{}\\\\]");
if (i > 0) {
@@ -1380,7 +1382,7 @@ struct llama_grammar* llama_sampler_init_grammar_impl(
trigger_pattern += std::regex_replace(trigger_words[i], special_chars, "\\$0");
}
trigger_pattern += ")[\\s\\S]*";
auto trigger_pattern_c = trigger_pattern.c_str();
trigger_pattern_c = trigger_pattern.c_str();
trigger_patterns = &trigger_pattern_c;
num_trigger_patterns = 1;
}