bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

fix sprintf-posix, vsprintf-posix modules


From: Bruno Haible
Subject: fix sprintf-posix, vsprintf-posix modules
Date: Mon, 2 Jul 2007 02:56:18 +0200
User-agent: KMail/1.5.4

The sprintf-posix, vsprintf-posix modules need to "estimate" the size
of a given buffer, into which sprintf is allowed to write any amount
of result. The current code uses
    min (SIZE_MAX, INT_MAX)
but this is wrong: Some system functions, such as glibc's iconv(), fail
if you pass them a buffer and a length such that
    buffer + length < buffer    (wrap around in unsigned arithmetic).

The case where it happened to me was a buffer allocated on the stack
(buffer = 0xbff....) and length = 0x7fffffff.

This fixes it.


2007-07-01  Bruno Haible  <address@hidden>

        * lib/sprintf.c (sprintf): Limit the available length estimation,
        to avoid address wraparound.
        * lib/vsprintf.c (vsprintf): Likewise.
        * modules/sprintf-posix (Dependencies): Add stdint.
        * modules/vsprintf-posix (Dependencies): Likewise.

*** lib/sprintf.c       18 Mar 2007 00:31:50 -0000      1.3
--- lib/sprintf.c       2 Jul 2007 00:48:09 -0000
***************
*** 25,30 ****
--- 25,31 ----
  #include <errno.h>
  #include <limits.h>
  #include <stdarg.h>
+ #include <stdint.h>
  #include <stdlib.h>
  
  #include "vasnprintf.h"
***************
*** 46,56 ****
  {
    char *output;
    size_t len;
!   /* vasnprintf fails with EOVERFLOW when the buffer size argument is larger
!      than INT_MAX (if that fits into a 'size_t' at all).  */
!   size_t lenbuf = (SIZE_MAX < INT_MAX ? SIZE_MAX : INT_MAX);
    va_list args;
  
    va_start (args, format);
    output = vasnprintf (str, &lenbuf, format, args);
    len = lenbuf;
--- 47,65 ----
  {
    char *output;
    size_t len;
!   size_t lenbuf;
    va_list args;
  
+   /* vasnprintf fails with EOVERFLOW when the buffer size argument is larger
+      than INT_MAX (if that fits into a 'size_t' at all).
+      Also note that glibc's iconv fails with E2BIG when we pass a length that
+      is so large that str + lenbuf wraps around, i.e.
+      (uintptr_t) (str + lenbuf) < (uintptr_t) str.
+      Therefore set lenbuf = min (SIZE_MAX, INT_MAX, - (uintptr_t) str - 1).  
*/
+   lenbuf = (SIZE_MAX < INT_MAX ? SIZE_MAX : INT_MAX);
+   if (lenbuf > ~ (uintptr_t) str)
+     lenbuf = ~ (uintptr_t) str;
+ 
    va_start (args, format);
    output = vasnprintf (str, &lenbuf, format, args);
    len = lenbuf;
*** lib/vsprintf.c      18 Mar 2007 00:31:50 -0000      1.3
--- lib/vsprintf.c      2 Jul 2007 00:48:09 -0000
***************
*** 25,30 ****
--- 25,31 ----
  #include <errno.h>
  #include <limits.h>
  #include <stdarg.h>
+ #include <stdint.h>
  #include <stdlib.h>
  
  #include "vasnprintf.h"
***************
*** 46,54 ****
  {
    char *output;
    size_t len;
    /* vasnprintf fails with EOVERFLOW when the buffer size argument is larger
!      than INT_MAX (if that fits into a 'size_t' at all).  */
!   size_t lenbuf = (SIZE_MAX < INT_MAX ? SIZE_MAX : INT_MAX);
  
    output = vasnprintf (str, &lenbuf, format, args);
    len = lenbuf;
--- 47,63 ----
  {
    char *output;
    size_t len;
+   size_t lenbuf;
+ 
    /* vasnprintf fails with EOVERFLOW when the buffer size argument is larger
!      than INT_MAX (if that fits into a 'size_t' at all).
!      Also note that glibc's iconv fails with E2BIG when we pass a length that
!      is so large that str + lenbuf wraps around, i.e.
!      (uintptr_t) (str + lenbuf) < (uintptr_t) str.
!      Therefore set lenbuf = min (SIZE_MAX, INT_MAX, - (uintptr_t) str - 1).  
*/
!   lenbuf = (SIZE_MAX < INT_MAX ? SIZE_MAX : INT_MAX);
!   if (lenbuf > ~ (uintptr_t) str)
!     lenbuf = ~ (uintptr_t) str;
  
    output = vasnprintf (str, &lenbuf, format, args);
    len = lenbuf;
*** modules/sprintf-posix       6 Jun 2007 02:20:57 -0000       1.5
--- modules/sprintf-posix       2 Jul 2007 00:48:09 -0000
***************
*** 17,22 ****
--- 17,23 ----
  signbit
  fpucw
  printf-safe
+ stdint
  
  configure.ac:
  gl_FUNC_SPRINTF_POSIX
*** modules/vsprintf-posix      6 Jun 2007 02:20:57 -0000       1.5
--- modules/vsprintf-posix      2 Jul 2007 00:48:09 -0000
***************
*** 17,22 ****
--- 17,23 ----
  signbit
  fpucw
  printf-safe
+ stdint
  
  configure.ac:
  gl_FUNC_VSPRINTF_POSIX





reply via email to

[Prev in Thread] Current Thread [Next in Thread]