diff --git a/misc.c b/misc.c index 6cc81710..9aff234b 100644 --- a/misc.c +++ b/misc.c @@ -394,15 +394,19 @@ int toint(unsigned u) * directive we don't know about, we should panic and die rather * than run any risk. */ -static char *dupvprintf_inner(char *buf, int oldlen, int oldsize, +static char *dupvprintf_inner(char *buf, int oldlen, int *oldsize, const char *fmt, va_list ap) { - int len, size; + int len, size, newsize; - size = oldsize - oldlen; + assert(*oldsize >= oldlen); + size = *oldsize - oldlen; if (size == 0) { size = 512; - buf = sresize(buf, oldlen + size, char); + newsize = oldlen + size; + buf = sresize(buf, newsize, char); + } else { + newsize = *oldsize; } while (1) { @@ -430,6 +434,7 @@ static char *dupvprintf_inner(char *buf, int oldlen, int oldsize, if (len >= 0 && len < size) { /* This is the C99-specified criterion for snprintf to have * been completely successful. */ + *oldsize = newsize; return buf; } else if (len > 0) { /* This is the C99 error condition: the returned length is @@ -440,13 +445,15 @@ static char *dupvprintf_inner(char *buf, int oldlen, int oldsize, * buffer wasn't big enough, so we enlarge it a bit and hope. */ size += 512; } - buf = sresize(buf, oldlen + size, char); + newsize = oldlen + size; + buf = sresize(buf, newsize, char); } } char *dupvprintf(const char *fmt, va_list ap) { - return dupvprintf_inner(NULL, 0, 0, fmt, ap); + int size = 0; + return dupvprintf_inner(NULL, 0, &size, fmt, ap); } char *dupprintf(const char *fmt, ...) { @@ -488,7 +495,7 @@ char *strbuf_to_str(strbuf *buf) } void strbuf_catfv(strbuf *buf, const char *fmt, va_list ap) { - buf->s = dupvprintf_inner(buf->s, buf->len, buf->size, fmt, ap); + buf->s = dupvprintf_inner(buf->s, buf->len, &buf->size, fmt, ap); buf->len += strlen(buf->s + buf->len); } void strbuf_catf(strbuf *buf, const char *fmt, ...)