From 25a80ea2dc8da3a61cd083b38cf9b43b27249b0e Mon Sep 17 00:00:00 2001 From: "Robert E. McGrath" Date: Fri, 18 Jun 2004 12:52:24 -0500 Subject: [svn-r8708] Purpose: This fixes bug mozilla_145 Description: Output from h5dump is truncated on SGI Solution: Revise h5tools_str_append. Changed the check for the return value from vsnprintf to handle overflows correctly. Added a special check for the case where HAVE_VSNPRINTF is not defined. (Windows doesn't have this function.) Will abort() if memory is overwritten. This overflow appears to be rare, but if we get reports of hitting this abort() we can try a more robust solution for platforms lacking vsnprintf. Platforms tested: arabica verbena hirdls (IRIX64 serial) windows 2000 Misc. update: --- tools/lib/h5tools_str.c | 62 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/tools/lib/h5tools_str.c b/tools/lib/h5tools_str.c index faf801e..3198f65 100644 --- a/tools/lib/h5tools_str.c +++ b/tools/lib/h5tools_str.c @@ -109,6 +109,12 @@ h5tools_str_len(h5tools_str_t *str) * * Modifications: * + * Major change: need to check results of vsnprintf to + * handle errors, empty format, and overflows. + * + * Programmer: REMcG Matzke + * June 16, 2004 + * *------------------------------------------------------------------------- */ char * @@ -127,24 +133,50 @@ h5tools_str_append(h5tools_str_t *str/*in,out*/, const char *fmt, ...) str->len = 0; } - while (1) { + if (strlen(fmt) == 0) { + /* nothing to print */ + va_end(ap); + return str->s; + } + + /* Format the arguments and append to the value already in `str' */ + while (1) { + /* How many bytes available for new value, counting the new NUL */ size_t avail = str->nalloc - str->len; - size_t nchars = (size_t)HDvsnprintf(str->s + str->len, avail, fmt, ap); - if (nchars < avail) { - /* success */ - str->len += nchars; - break; - } - - /* Try again with twice as much space */ - str->nalloc *= 2; - str->s = realloc(str->s, str->nalloc); - assert(str->s); - } + int nchars = HDvsnprintf(str->s + str->len, avail, fmt, ap); - va_end(ap); - return str->s; + if (nchars<0) { + /* failure, such as bad format */ + va_end(ap); + return NULL; + } + + if ((size_t)nchars>=avail || + (0==nchars && (strcmp(fmt,"%s") ))) { + /* Truncation return value as documented by C99, or zero return value with either of the + * following conditions, each of which indicates that the proper C99 return value probably + * should have been positive when the format string is + * something other than "%s" + * Alocate at least twice as much space and try again. + */ + size_t newsize = MAX(str->len+nchars+1, 2*str->nalloc); + assert(newsize > str->nalloc); /*overflow*/ +#ifndef H5_HAVE_VSNPRINTF + /* If we even made it this far... the HDvsnprintf() clobbered memory: SIGSEGV probable*/ + abort(); +#endif + str->s = realloc(str->s, newsize); + assert(str->s); + str->nalloc = newsize; + } else { + /* Success */ + str->len += nchars; + break; + } + } + va_end(ap); + return str->s; } /*------------------------------------------------------------------------- -- cgit v0.12