Mercurial > hg > octave-kai > gnulib-hg
changeset 9029:3b5cd6b6e134
Avoid address wraparound inside system functions.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Mon, 02 Jul 2007 00:56:18 +0000 |
parents | 41c4b53b7797 |
children | 870029929d86 |
files | ChangeLog lib/sprintf.c lib/vsprintf.c modules/sprintf-posix modules/vsprintf-posix |
diffstat | 5 files changed, 33 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2007-07-01 Bruno Haible <bruno@clisp.org> + + * 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. + 2007-07-01 Bruno Haible <bruno@clisp.org> * gnulib-tool (self_abspathname): Determine PATH_SEPARATOR and handle
--- a/lib/sprintf.c +++ b/lib/sprintf.c @@ -25,6 +25,7 @@ #include <errno.h> #include <limits.h> #include <stdarg.h> +#include <stdint.h> #include <stdlib.h> #include "vasnprintf.h" @@ -46,10 +47,18 @@ { 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). */ - size_t lenbuf = (SIZE_MAX < INT_MAX ? SIZE_MAX : INT_MAX); - va_list args; + 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);
--- 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 @@ { 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;