diff options
author | Bruno Haible <bruno@clisp.org> | 2007-07-02 00:56:18 +0000 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2007-07-02 00:56:18 +0000 |
commit | 7c8322243bf4fe57a7f5d042182c1b5c541bdaeb (patch) | |
tree | 59db416b8cab927056efeee4868ec0e85d3defb7 /lib/vsprintf.c | |
parent | ca3910da774f8ae6c4a2b6b8a8729b10ccc97ad4 (diff) | |
download | gnulib-7c8322243bf4fe57a7f5d042182c1b5c541bdaeb.tar.gz |
Avoid address wraparound inside system functions.
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r-- | lib/vsprintf.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index a9d840d9c8..88e528db37 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -25,6 +25,7 @@ #include <errno.h> #include <limits.h> #include <stdarg.h> +#include <stdint.h> #include <stdlib.h> #include "vasnprintf.h" @@ -46,9 +47,17 @@ vsprintf (char *str, const char *format, va_list args) { 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). */ - size_t lenbuf = (SIZE_MAX < INT_MAX ? SIZE_MAX : INT_MAX); + 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; |