From 75ab455cf60aa431ea4b76d447728d56e0694fe7 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Thu, 11 Dec 2025 10:54:58 +0100 Subject: [PATCH] libutil: Avoid realloc() with zero size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the valgrind man-page, "the behaviour of realloc() with a size of zero is implementation defined in C17 and undefined in C23." The current glibc implementation frees the specified buffer, returns NULL and doesn't set errno. While this behavior is unlikely to change in the near future, code relying on it may not be compatible with other libc implementations. Also this realloc() use is flagged as an error in valgrind runs, making valgrind output less usable. Fix this by explicitly adding code to cover the realloc(buffer, 0) case in util_realloc(). Also change libutil users of realloc() to use util_realloc() instead. Reviewed-by: Steffen Eiden Signed-off-by: Peter Oberparleiter Signed-off-by: Jan Höppner --- libutil/util_file.c | 25 +++---------------------- libutil/util_libc.c | 5 +++++ libutil/util_scandir.c | 2 +- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/libutil/util_file.c b/libutil/util_file.c index 9bba5579..7de159cc 100644 --- a/libutil/util_file.c +++ b/libutil/util_file.c @@ -544,19 +544,6 @@ int util_file_read_va(const char *path, const char *fmt, ...) return ret; } -/** - * Print an error message indicating an out-of-memory situation and exit. - */ -static void oom(void) -{ - fprintf(stderr, "Out of memory\n"); - - /* We can't rely on our clean-up routines to work reliably during an - * OOM situation, so just exit here. - */ - exit(UTIL_EXIT_OUT_OF_MEMORY); -} - /** * Read all data from @fd and return address of resulting buffer in * @buffer_ptr. If @size_ptr is non-zero, use it to store the size of the @@ -576,9 +563,7 @@ util_exit_code_t util_file_read_fd_buf(FILE *fd, void **buffer_ptr, size_t done = 0; while (!feof(fd)) { - buffer = realloc(buffer, done + READ_CHUNK_SIZE); - if (!buffer) - oom(); + buffer = util_realloc(buffer, done + READ_CHUNK_SIZE); done += fread(&buffer[done], 1, READ_CHUNK_SIZE, fd); if (ferror(fd)) { free(buffer); @@ -586,9 +571,7 @@ util_exit_code_t util_file_read_fd_buf(FILE *fd, void **buffer_ptr, } } - buffer = realloc(buffer, done); - if (!buffer && done > 0) - oom(); + buffer = util_realloc(buffer, done); *buffer_ptr = buffer; if (size_ptr) @@ -635,9 +618,7 @@ char *util_file_read_fd(FILE *fd, int chomp) done--; /* NULL-terminate. */ - buffer = realloc(buffer, done + 1); - if (!buffer) - oom(); + buffer = util_realloc(buffer, done + 1); buffer[done] = 0; return buffer; diff --git a/libutil/util_libc.c b/libutil/util_libc.c index 00b33ee3..d038a7dc 100644 --- a/libutil/util_libc.c +++ b/libutil/util_libc.c @@ -89,6 +89,11 @@ void *__util_realloc(const char *func, const char *file, int line, { void *buf; + if (size == 0) { + free(ptr); + return NULL; + } + buf = realloc(ptr, size); if (buf == NULL) diff --git a/libutil/util_scandir.c b/libutil/util_scandir.c index 73308ad2..997ba8a9 100644 --- a/libutil/util_scandir.c +++ b/libutil/util_scandir.c @@ -68,7 +68,7 @@ static int __scandir(struct dirent ***de_vec, const char *path, continue; de_new = util_malloc(sizeof(*de_new)); *de_new = *de; - de_vec_new = realloc(de_vec_new, sizeof(void *) * (count + 1)); + de_vec_new = util_realloc(de_vec_new, sizeof(void *) * (count + 1)); de_vec_new[count++] = de_new; } closedir(dirp);