From 16030b5e4c7f68048208599645b6948cf0b70df5 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Mon, 28 Aug 2006 16:04:14 +0000 Subject: [PATCH] Do the INT_MAX check only where size_t is converted to 'int'. --- lib/ChangeLog | 12 ++++++++++++ lib/vasnprintf.c | 22 +++++----------------- lib/vasprintf.c | 20 ++++++++++++++++---- lib/vsnprintf.c | 35 +++++++++++++++++++++++++++-------- 4 files changed, 60 insertions(+), 29 deletions(-) diff --git a/lib/ChangeLog b/lib/ChangeLog index 437c58672..9ed357b2a 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,4 +1,16 @@ 2006-08-26 Bruno Haible + + * vasnprintf.c (EOVERFLOW): Remove definition. + (VASNPRINTF): Return a string of length > INT_MAX without failing. + * vasprintf.c: Include errno.h, limits.h. + (EOVERFLOW): New fallback definition. + (vasprintf): Test here whether the string length is > INT_MAX. + * vsnprintf.c: Include errno.h, limits.h. + (EOVERFLOW): New fallback definition. + (vsnprintf): Fix bug when generated string was too long for the buffer. + Test here whether the string length is > INT_MAX. + +2006-08-26 Bruno Haible Simon Josefsson BeOS portability. diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index 3b496d253..b68c1bbb0 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -40,7 +40,7 @@ #include /* abort(), malloc(), realloc(), free() */ #include /* memcpy(), strlen() */ #include /* errno */ -#include /* CHAR_BIT, INT_MAX */ +#include /* CHAR_BIT */ #include /* DBL_MAX_EXP, LDBL_MAX_EXP */ #if WIDE_CHAR_VERSION # include "wprintf-parse.h" @@ -51,11 +51,6 @@ /* Checked size_t computations. */ #include "xsize.h" -/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */ -#ifndef EOVERFLOW -# define EOVERFLOW E2BIG -#endif - #ifdef HAVE_WCHAR_T # ifdef HAVE_WCSLEN # define local_wcslen wcslen @@ -869,19 +864,12 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar free (buf_malloced); CLEANUP (); *lengthp = length; - if (length > INT_MAX) - goto length_overflow; + /* Note that we can produce a big string of a length > INT_MAX. POSIX + says that snprintf() fails with errno = EOVERFLOW in this case, but + that's only because snprintf() returns an 'int'. This function does + not have this limitation. */ return result; - length_overflow: - /* We could produce such a big string, but its length doesn't fit into - an 'int'. POSIX says that snprintf() fails with errno = EOVERFLOW in - this case. */ - if (result != resultbuf) - free (result); - errno = EOVERFLOW; - return NULL; - out_of_memory: if (!(result == resultbuf || result == NULL)) free (result); diff --git a/lib/vasprintf.c b/lib/vasprintf.c index 149c29242..91da8812b 100644 --- a/lib/vasprintf.c +++ b/lib/vasprintf.c @@ -1,5 +1,5 @@ /* Formatted output to strings. - Copyright (C) 1999, 2002 Free Software Foundation, Inc. + Copyright (C) 1999, 2002, 2006 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,10 +22,17 @@ /* Specification. */ #include "vasprintf.h" +#include +#include #include #include "vasnprintf.h" +/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */ +#ifndef EOVERFLOW +# define EOVERFLOW E2BIG +#endif + int vasprintf (char **resultp, const char *format, va_list args) { @@ -34,9 +41,14 @@ vasprintf (char **resultp, const char *format, va_list args) if (result == NULL) return -1; + if (length > INT_MAX) + { + free (result); + errno = EOVERFLOW; + return -1; + } + *resultp = result; - /* Return the number of resulting bytes, excluding the trailing NUL. - If it wouldn't fit in an 'int', vasnprintf() would have returned NULL - and set errno to EOVERFLOW. */ + /* Return the number of resulting bytes, excluding the trailing NUL. */ return length; } diff --git a/lib/vsnprintf.c b/lib/vsnprintf.c index 827397bff..af567d2cc 100644 --- a/lib/vsnprintf.c +++ b/lib/vsnprintf.c @@ -1,5 +1,5 @@ /* Formatted output to strings. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. Written by Simon Josefsson and Yoann Vandoorselaere . This program is free software; you can redistribute it and/or modify @@ -23,6 +23,8 @@ /* Specification. */ #include "vsnprintf.h" +#include +#include #include #include #include @@ -30,6 +32,11 @@ #include "vasnprintf.h" +/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */ +#ifndef EOVERFLOW +# define EOVERFLOW E2BIG +#endif + /* Print formatted output to string STR. Similar to vsprintf, but additional length SIZE limit how much is written into STR. Returns string length of formatted string (which may be larger than SIZE). @@ -40,19 +47,31 @@ vsnprintf (char *str, size_t size, const char *format, va_list args) { char *output; size_t len; + size_t lenbuf = size; - len = size; - output = vasnprintf (str, &len, format, args); + output = vasnprintf (str, &lenbuf, format, args); + len = lenbuf; if (!output) return -1; - if (str != NULL) - if (len > size - 1) /* equivalent to: (size > 0 && len >= size) */ - str[size - 1] = '\0'; - if (output != str) - free (output); + { + if (size) + { + size_t pruned_len = (len < size ? len : size - 1); + memcpy (str, output, pruned_len); + str[pruned_len] = '\0'; + } + + free (output); + } + + if (len > INT_MAX) + { + errno = EOVERFLOW; + return -1; + } return len; } -- 2.11.0