diff options
author | Florian Weimer <fweimer@redhat.com> | 2023-01-25 08:01:00 +0100 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2023-01-25 08:01:00 +0100 |
commit | 0d50f477f47ba637b54fb03ac48d769ec4543e8d (patch) | |
tree | 598fbe050d8441a6152237d5442d2506ed846bf0 /include | |
parent | 0674613e6652a46063756f162bdef88622b3bdbd (diff) | |
download | glibc-0d50f477f47ba637b54fb03ac48d769ec4543e8d.zip glibc-0d50f477f47ba637b54fb03ac48d769ec4543e8d.tar.gz glibc-0d50f477f47ba637b54fb03ac48d769ec4543e8d.tar.bz2 |
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 <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/printf_buffer.h | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/include/printf_buffer.h b/include/printf_buffer.h index 55feebf..4d787e4 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; |