bug-ncurses
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Fix reuse of va_list object in while loop in _nc_printf_string_s


From: Ian Abbott
Subject: [PATCH] Fix reuse of va_list object in while loop in _nc_printf_string_sp()
Date: Wed, 27 Sep 2023 17:41:12 +0100

When `#if USE_SAFE_SPRINTF` is false and `#if HAVE_VSNPRINTF` is true,
`vsnprintf()` is called in a `while` loop that reallocates the
`my_buffer` if the buffer is too small to hold the output.

The `va_list ap` parameter value becomes indeterminate after the first
call to `vnsprintf()` leading to undefined behavior on the next
iteration of the loop.  Make a fresh copy of the `va_list ap` parameter
into new variable `va_list ap2` and pass the copy to `vnsprintf()`,
resulting in undefined behavior.

Terminate the loop and return a null pointer if reallocation of the
`my_buffer` buffer is unsuccessful, otherwise the next iteration would
call `vnsprintf()` with a null buffer pointer and a non-zero buffer
size, leading to undefined behavior.
---
 ncurses/base/safe_sprintf.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/ncurses/base/safe_sprintf.c b/ncurses/base/safe_sprintf.c
index 3fff2e83..4ddde6ab 100644
--- a/ncurses/base/safe_sprintf.c
+++ b/ncurses/base/safe_sprintf.c
@@ -264,11 +264,18 @@ NCURSES_SP_NAME(_nc_printf_string) (NCURSES_SP_DCLx
 # if HAVE_VSNPRINTF
            /* SUSv2, 1997 */
            int used;
-           while ((used = vsnprintf(my_buffer, my_length, fmt, ap))
-                  >= (int) my_length) {
+
+           do {
+               va_list ap2;
+
+               begin_va_copy(ap2, ap);
+               used = vsnprintf(my_buffer, my_length, fmt, ap2);
+               end_va_copy(ap2);
+               if (used < (int) my_length)
+                   break;
                my_length = (size_t) ((3 * used) / 2);
                my_buffer = typeRealloc(char, my_length, my_buffer);
-           }
+           } while (my_buffer != NULL);
 # else
            /* ISO/ANSI C, 1989 */
            vsprintf(my_buffer, fmt, ap);
-- 
2.40.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]