From a4ea1f3dcc967a09a98af156de5c999de075effd Mon Sep 17 00:00:00 2001 From: Ihor Aleksandrychiev Date: Thu, 9 Jul 2026 17:11:57 +0300 Subject: [PATCH] Made GetExecOutput() return an empty string on empty command output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The read loop never touched the output buffer when the command produced no output: it hit EOF on the first iteration and returned success, leaving the buffer exactly as the caller allocated it. A caller using malloc() then saw stale heap data as command output — this made cf-agent's container inventory intermittently treat a freed 'docker image inspect' JSON buffer as the 'docker volume ls --quiet' result on Windows. NUL-terminate the buffer up front so callers always get a valid, possibly empty, string. Co-Authored-By: Claude Fable 5 Signed-off-by: Ihor Aleksandrychiev --- libpromises/exec_tools.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libpromises/exec_tools.c b/libpromises/exec_tools.c index e64eecbd7a..895602506d 100644 --- a/libpromises/exec_tools.c +++ b/libpromises/exec_tools.c @@ -37,6 +37,14 @@ bool GetExecOutput(const char *command, char **buffer, size_t *buffer_size, ShellType shell, OutputSelect output_select, int *ret_out) /* Buffer initially contains whole exec string */ { + assert(buffer != NULL && *buffer != NULL); + assert(buffer_size != NULL && *buffer_size > 0); + + /* Terminate up front: if the command produces no output the read loop + * below never writes to the buffer, and a caller that allocated it with + * malloc() would otherwise see stale heap data as command output. */ + (*buffer)[0] = '\0'; + FILE *pp; if (shell == SHELL_TYPE_USE)