From 7705fc4470b76ec7979dc00e5c97efd720d5e335 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Mon, 20 Feb 2017 20:30:14 +0000 Subject: [PATCH] Fix buffer management in strbuf_catfv. Thanks to Tim Kosse for pointing out that I had _completely_ cocked up all the code that was supposed to enlarge the buffer in the strbuf structure, by failing to pass in 'oldsize' to the innermost dupvprintf_inner function by reference, so that the size was never updated. Fortunately, this whole mechanism was something I dashed off for the purposes of buildinfo(), which means it's only ever used to glue together a fixed number of compile-time string constants, for which there turns out to be plenty to spare in the standard 512 bytes allocated to a new strbuf. So it's at least not dangerous, though it clearly needs to be fixed before I make the mistake of using strbuf_catf[v] for anything else! --- misc.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) 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, ...) -- 2.45.1