summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/lib/h5tools_str.c62
1 files changed, 47 insertions, 15 deletions
diff --git a/tools/lib/h5tools_str.c b/tools/lib/h5tools_str.c
index 6656c81..9faba55 100644
--- a/tools/lib/h5tools_str.c
+++ b/tools/lib/h5tools_str.c
@@ -111,6 +111,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 *
@@ -129,24 +135,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;
}
/*-------------------------------------------------------------------------