libutil: Avoid realloc() with zero size

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 <seiden@linux.ibm.com>
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Peter Oberparleiter
2025-12-11 10:54:58 +01:00
committed by Jan Höppner
parent 25088b340b
commit 75ab455cf6
3 changed files with 9 additions and 23 deletions

View File

@@ -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;

View File

@@ -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)

View File

@@ -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);