From 4114ba18b208c2e9c1689a8316d410e649309dbc Mon Sep 17 00:00:00 2001 From: Pascal Date: Mon, 13 Jul 2026 00:47:25 +0200 Subject: [PATCH] mtmd: fix silent prompt truncation on embedded NUL (#25548) * mtmd: fix silent prompt truncation on embedded NUL mtmd_input_text carried the prompt as a bare const char* with no length, so a NUL byte in message content cut the prompt at the tokenizer boundary and dropped every later message plus the assistant marker, with no log. Add an explicit text_len and thread it through, matching llama_tokenize and the text only path. * cleanup --------- Co-authored-by: Xuan Son Nguyen --- tools/mtmd/mtmd-cli.cpp | 3 ++- tools/mtmd/mtmd.cpp | 5 +++-- tools/mtmd/mtmd.h | 1 + tools/server/server-common.cpp | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/mtmd/mtmd-cli.cpp b/tools/mtmd/mtmd-cli.cpp index 8704ea79d..08288c868 100644 --- a/tools/mtmd/mtmd-cli.cpp +++ b/tools/mtmd/mtmd-cli.cpp @@ -250,7 +250,8 @@ static int eval_message(mtmd_cli_context & ctx, common_chat_msg & msg) { LOG_DBG("formatted_chat.prompt: %s\n", formatted_chat.c_str()); mtmd_input_text text; - text.text = formatted_chat.c_str(); + text.text = formatted_chat.data(); + text.text_len = formatted_chat.size(); text.add_special = add_bos; text.parse_special = true; diff --git a/tools/mtmd/mtmd.cpp b/tools/mtmd/mtmd.cpp index 73270ba88..e10ccf186 100644 --- a/tools/mtmd/mtmd.cpp +++ b/tools/mtmd/mtmd.cpp @@ -809,7 +809,7 @@ void mtmd_free(mtmd_context * ctx) { struct mtmd_tokenizer { mtmd_context * ctx; - std::string input_text; + std::string input_text; // note: can contain null bytes; do not use c_str() bool add_special; bool parse_special; const llama_vocab * vocab; @@ -839,9 +839,10 @@ struct mtmd_tokenizer { size_t n_bitmaps) : ctx(ctx) { add_special = text->add_special; parse_special = text->parse_special; - input_text = text->text; vocab = ctx->vocab; + input_text.assign(text->text, text->text_len); + std::vector bitmaps(bmps, bmps + n_bitmaps); auto parts_str = split_text(input_text, ctx->media_marker); size_t i_bm = 0; diff --git a/tools/mtmd/mtmd.h b/tools/mtmd/mtmd.h index 25d51ef58..3b8c1200b 100644 --- a/tools/mtmd/mtmd.h +++ b/tools/mtmd/mtmd.h @@ -67,6 +67,7 @@ struct mtmd_batch; struct mtmd_input_text { const char * text; + size_t text_len; bool add_special; bool parse_special; }; diff --git a/tools/server/server-common.cpp b/tools/server/server-common.cpp index ac291d359..c76ed7cc2 100644 --- a/tools/server/server-common.cpp +++ b/tools/server/server-common.cpp @@ -705,7 +705,8 @@ server_tokens process_mtmd_prompt(mtmd_context * mctx, const std::string & promp std::vector inputs; // multimodal mtmd_input_text inp_txt = { - prompt.c_str(), + prompt.data(), + prompt.size(), /* add_special */ true, /* parse_special */ true, };