From 0d50f477f47ba637b54fb03ac48d769ec4543e8d Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Wed, 25 Jan 2023 08:01:00 +0100 Subject: stdio-common: Handle -1 buffer size in __sprintf_chk & co (bug 30039) This shows up as an assertion failure when sprintf is called with a specifier like "%.8g" and libquadmath is linked in: Fatal glibc error: printf_buffer_as_file.c:31 (__printf_buffer_as_file_commit): assertion failed: file->stream._IO_write_ptr <= file->next->write_end Fix this by detecting pointer wraparound in __vsprintf_internal and saturate the addition to the end of the address space instead. Reviewed-by: Carlos O'Donell Tested-by: Carlos O'Donell --- libio/iovsprintf.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'libio') diff --git a/libio/iovsprintf.c b/libio/iovsprintf.c index 8d53e401cc..9a4f59a06e 100644 --- a/libio/iovsprintf.c +++ b/libio/iovsprintf.c @@ -45,14 +45,19 @@ __vsprintf_internal (char *string, size_t maxlen, if ((mode_flags & PRINTF_CHK) != 0) { string[0] = '\0'; - __printf_buffer_init (&buf, string, maxlen, + /* In some cases, __sprintf_chk is called with an unknown buffer + size (the special value -1). Prevent pointer wraparound in + this case and saturate to the end of the address space. */ + uintptr_t end; + if (__builtin_add_overflow ((uintptr_t) string, maxlen, &end)) + end = -1; + __printf_buffer_init_end (&buf, string, (char *) end, __printf_buffer_mode_sprintf_chk); } else - { - __printf_buffer_init (&buf, string, 0, __printf_buffer_mode_sprintf); - buf.write_end = (char *) ~(uintptr_t) 0; /* End of address space. */ - } + /* Use end of address space. */ + __printf_buffer_init_end (&buf, string, (char *) ~(uintptr_t) 0, + __printf_buffer_mode_sprintf); __printf_buffer (&buf, format, args, mode_flags); -- cgit 1.4.1