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 --- include/printf_buffer.h | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'include/printf_buffer.h') diff --git a/include/printf_buffer.h b/include/printf_buffer.h index 55feebf279..4d787e4b2c 100644 --- a/include/printf_buffer.h +++ b/include/printf_buffer.h @@ -115,19 +115,28 @@ __printf_buffer_has_failed (struct __printf_buffer *buf) return buf->mode == __printf_buffer_mode_failed; } -/* Initialization of a buffer, using the memory region from [BASE, BASE +LEN) - as the initial buffer contents. LEN can be zero. */ +/* Initialization of a buffer, using the memory region from [BASE, + END) as the initial buffer contents. */ static inline void -__printf_buffer_init (struct __printf_buffer *buf, char *base, size_t len, - enum __printf_buffer_mode mode) +__printf_buffer_init_end (struct __printf_buffer *buf, char *base, char *end, + enum __printf_buffer_mode mode) { buf->write_base = base; buf->write_ptr = base; - buf->write_end = base + len; + buf->write_end = end; buf->written = 0; buf->mode = mode; } +/* Initialization of a buffer, using the memory region from [BASE, BASE +LEN) + as the initial buffer contents. LEN can be zero. */ +static inline void +__printf_buffer_init (struct __printf_buffer *buf, char *base, size_t len, + enum __printf_buffer_mode mode) +{ + __printf_buffer_init_end (buf, base, base + len, mode); +} + /* Called by printf_buffer_putc for a full buffer. */ void __printf_buffer_putc_1 (struct __printf_buffer *buf, char ch) attribute_hidden; -- cgit v1.2.3