From 44b669ba66ad38267db5da04c1f389c3394c8488 Mon Sep 17 00:00:00 2001 From: zerico <71151164+ZERICO2005@users.noreply.github.com> Date: Mon, 8 Jun 2026 10:51:55 -0600 Subject: [PATCH] Fix va_list reuse with va_copy in boot_sprintf and nanoprintf --- src/ce/boot_printf.c | 35 +++++++++++++++++++++++++---------- src/libc/printf/nanoprintf.c | 11 +++++++++-- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/ce/boot_printf.c b/src/ce/boot_printf.c index ab3be414b..e7641bb8d 100644 --- a/src/ce/boot_printf.c +++ b/src/ce/boot_printf.c @@ -1,20 +1,23 @@ #include #include -#include #include -#include #include #include #define SINK (char *__restrict)0xE40000 int boot_vsnprintf(char *__restrict buffer, size_t count, const char *__restrict format, va_list args) { - int str_len = boot_vsprintf(SINK, format, args); + va_list args_copy; + va_copy(args_copy, args); + int str_len = boot_vsprintf(SINK, format, args_copy); + va_end(args_copy); + if (buffer == NULL || count == 0) { return str_len; } - if ((size_t)str_len >= count || str_len <= 0) { - // won't fit or invalid formatting + // str_len == 0 can take this fast path + if ((size_t)str_len >= count || str_len < 0 || str_len == 0) { + // won't fit, invalid formatting, or empty string *buffer = '\0'; return str_len; } @@ -32,18 +35,30 @@ int boot_snprintf(char *__restrict buffer, size_t count, const char *__restrict __attribute__((weak, alias("boot_snprintf"))) int snprintf(char *__restrict buffer, size_t count, const char *__restrict format, ...); int boot_vasprintf(char **__restrict p_buffer, const char *__restrict format, va_list args) { - int ret = -1; *p_buffer = NULL; - int str_len = boot_vsprintf(SINK, format, args); + va_list args_copy; + va_copy(args_copy, args); + int str_len = boot_vsprintf(SINK, format, args_copy); + va_end(args_copy); + if (str_len < 0) { // formatting error return str_len; } size_t buffer_size = (size_t)str_len + 1; - *p_buffer = malloc(buffer_size); - if (*p_buffer != NULL) { - ret = boot_vsprintf(*p_buffer, format, args); + char* buffer = malloc(buffer_size); + if (buffer == NULL) { + // malloc failure + return -1; + } + va_copy(args_copy, args); + int ret = boot_vsprintf(buffer, format, args_copy); + va_end(args_copy); + if (ret < 0) { + free(buffer); + return ret; } + *p_buffer = buffer; return ret; } __attribute__((weak, alias("boot_vasprintf"))) int vasprintf(char **__restrict p_buffer, const char *__restrict format, va_list args); diff --git a/src/libc/printf/nanoprintf.c b/src/libc/printf/nanoprintf.c index 18759a235..c69607990 100644 --- a/src/libc/printf/nanoprintf.c +++ b/src/libc/printf/nanoprintf.c @@ -93,8 +93,13 @@ int sprintf(char *__restrict buffer, const char *__restrict format, ...) int vasprintf(char **__restrict p_str, const char *__restrict format, va_list vlist) { *p_str = NULL; - int str_len = vsnprintf(NULL, 0, format, vlist); + va_list vlist_copy; + va_copy(vlist_copy, vlist); + int str_len = vsnprintf(NULL, 0, format, vlist_copy); + va_end(vlist_copy); + if (str_len < 0) { + // formatting error return str_len; } size_t buf_len = (size_t)str_len + 1; @@ -103,7 +108,9 @@ int vasprintf(char **__restrict p_str, const char *__restrict format, va_list vl // malloc failure return -1; } - int ret = vsnprintf(buf, buf_len, format, vlist); + va_copy(vlist_copy, vlist); + int ret = vsnprintf(buf, buf_len, format, vlist_copy); + va_end(vlist_copy); if (ret < 0) { free(buf); return ret;