diff options
author | Robert E. McGrath <mcgrath@ncsa.uiuc.edu> | 2004-06-18 17:52:24 (GMT) |
---|---|---|
committer | Robert E. McGrath <mcgrath@ncsa.uiuc.edu> | 2004-06-18 17:52:24 (GMT) |
commit | 25a80ea2dc8da3a61cd083b38cf9b43b27249b0e (patch) | |
tree | 7f87e6c748a7f003ea1effaf70e500e3e6c291ac /tools/lib | |
parent | 5d2983abf65f698257b0aaeefbeeaf3c62ebf7d8 (diff) | |
download | hdf5-25a80ea2dc8da3a61cd083b38cf9b43b27249b0e.zip hdf5-25a80ea2dc8da3a61cd083b38cf9b43b27249b0e.tar.gz hdf5-25a80ea2dc8da3a61cd083b38cf9b43b27249b0e.tar.bz2 |
[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:
Diffstat (limited to 'tools/lib')
-rw-r--r-- | tools/lib/h5tools_str.c | 62 |
1 files 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; } /*------------------------------------------------------------------------- |