From 564e431717fd4dcb903b3b9ac68de7c65ef96078 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Mon, 8 Jun 2026 16:29:39 +0000 Subject: [PATCH] fix(llama-cpp): patch mtmd video stdin double-close (heap crash) Upstream mtmd video input (ggml-org/llama.cpp#24269) double-fcloses the ffmpeg/ffprobe stdin FILE: feed_stdin() fclose()s the FILE returned by subprocess_stdin() (which is sp->stdin_file), then subprocess_destroy() fclose()s the same pointer again -> heap corruption that aborts the backend on any base64 input_video request (the CLI --video file path is unaffected). Vendor a one-line fix (null sp->stdin_file after fclose) via prepare.sh's patches/ until upstream merges it. Verified e2e with gemma-4-e2b-it-qat-q4_0: video frames decode via ffmpeg and the model answers correctly (red clip -> 'Red', blue -> 'Blue'). Signed-off-by: Ettore Di Giacinto --- ...01-mtmd-fix-video-stdin-double-close.patch | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 backend/cpp/llama-cpp/patches/0001-mtmd-fix-video-stdin-double-close.patch diff --git a/backend/cpp/llama-cpp/patches/0001-mtmd-fix-video-stdin-double-close.patch b/backend/cpp/llama-cpp/patches/0001-mtmd-fix-video-stdin-double-close.patch new file mode 100644 index 000000000..a4c3261a4 --- /dev/null +++ b/backend/cpp/llama-cpp/patches/0001-mtmd-fix-video-stdin-double-close.patch @@ -0,0 +1,30 @@ +From: Ettore Di Giacinto +Subject: [PATCH] mtmd: fix double-close of ffmpeg/ffprobe stdin in video helper + +mtmd_helper_video::feed_stdin() obtains the subprocess stdin via +subprocess_stdin(sp), which returns sp->stdin_file directly, then +fclose()s that FILE. Closing the local copy leaves sp->stdin_file +dangling (still non-NULL), so the subsequent subprocess_destroy() +fclose()s the same FILE a second time. The resulting heap corruption +aborts the process ("corrupted double-linked list" / "corrupted size +vs. prev_size") - notably on the server's base64 input_video path, +where every probe()/start_ffmpeg() feeds the buffer via stdin. The CLI +--video file path is unaffected (it never spawns the stdin feeder). + +Clear sp->stdin_file after fclose so subprocess_destroy() skips it. + +--- a/tools/mtmd/mtmd-helper.cpp ++++ b/tools/mtmd/mtmd-helper.cpp +@@ -642,7 +642,12 @@ + LOG_DBG("%s: feeding %zu bytes to stdin\n", __func__, input_buf.size()); + size_t written = fwrite(input_buf.data(), 1, input_buf.size(), f); + LOG_DBG("%s: wrote %zu bytes, closing stdin\n", __func__, written); + fclose(f); ++ // subprocess_stdin() returns sp->stdin_file directly; fclosing our local ++ // copy leaves the struct pointer dangling, so subprocess_destroy() would ++ // fclose() the same FILE again -> heap corruption. Null it so the later ++ // destroy skips stdin. ++ sp->stdin_file = nullptr; + } + + bool probe(float fps_target_arg) {