about summary refs log tree commit diff
path: root/libio/iovsprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'libio/iovsprintf.c')
-rw-r--r--libio/iovsprintf.c15
1 files changed, 10 insertions, 5 deletions
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);