about summary refs log tree commit diff
path: root/include
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2023-01-25 08:01:00 +0100
committerFlorian Weimer <fweimer@redhat.com>2023-01-25 08:01:00 +0100
commit0d50f477f47ba637b54fb03ac48d769ec4543e8d (patch)
tree598fbe050d8441a6152237d5442d2506ed846bf0 /include
parent0674613e6652a46063756f162bdef88622b3bdbd (diff)
downloadglibc-0d50f477f47ba637b54fb03ac48d769ec4543e8d.tar.gz
glibc-0d50f477f47ba637b54fb03ac48d769ec4543e8d.tar.xz
glibc-0d50f477f47ba637b54fb03ac48d769ec4543e8d.zip
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.h19
1 files changed, 14 insertions, 5 deletions
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;