[Top][All Lists]
[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- fix sprintf-posix, vsprintf-posix modules,
Bruno Haible <=