]> asedeno.scripts.mit.edu Git - PuTTY.git/commitdiff
Fix buffer management in strbuf_catfv.
authorSimon Tatham <anakin@pobox.com>
Mon, 20 Feb 2017 20:30:14 +0000 (20:30 +0000)
committerSimon Tatham <anakin@pobox.com>
Mon, 20 Feb 2017 20:46:04 +0000 (20:46 +0000)
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

diff --git a/misc.c b/misc.c
index 6cc817103b5a105d625bd76f6846b6a8326a47d1..9aff234b9fdde6c04527c2b79db32ef02e1122e4 100644 (file)
--- 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, ...)