]> diplodocus.org Git - nmh/commitdiff
Use va_copy() to get a copy of va_list, instead of using original.
authorKen Hornstein <kenh@pobox.com>
Sat, 4 Nov 2017 13:59:18 +0000 (09:59 -0400)
committerKen Hornstein <kenh@pobox.com>
Sat, 4 Nov 2017 13:59:18 +0000 (09:59 -0400)
netsec_vprintf() can call vsnprintf() twice if the outgoing buffer is
full (but it happens rarely in practice, given the way the current
code uses it).  But if this DOES happen, vsnprintf() will use the
same va_list argument twice, and the second time around either it will
grab a random bit of memory off of the stack OR it will segfault.
So we always use va_copy() to get our own copy of the passed-in va_list
and work on that.

sbr/netsec.c

index 01c25f5f375419bda95542da29d22f243100b9e3..0fb4126294612ad77757f7aef6395d3343f1a221 100644 (file)
@@ -807,6 +807,7 @@ netsec_vprintf(netsec_context *nsc, char **errstr, const char *format,
               va_list ap)
 {
     int rc;
               va_list ap)
 {
     int rc;
+    va_list apcopy;
 
     /*
      * Cheat a little.  If we can fit the data into our outgoing buffer,
 
     /*
      * Cheat a little.  If we can fit the data into our outgoing buffer,
@@ -814,8 +815,10 @@ netsec_vprintf(netsec_context *nsc, char **errstr, const char *format,
      */
 
 retry:
      */
 
 retry:
+    va_copy(apcopy, ap);
     rc = vsnprintf((char *) nsc->ns_outptr,
     rc = vsnprintf((char *) nsc->ns_outptr,
-                  nsc->ns_outbufsize - nsc->ns_outbuflen, format, ap);
+                  nsc->ns_outbufsize - nsc->ns_outbuflen, format, apcopy);
+    va_end(apcopy);
 
     if (rc >= (int) (nsc->ns_outbufsize - nsc->ns_outbuflen)) {
        /*
 
     if (rc >= (int) (nsc->ns_outbufsize - nsc->ns_outbuflen)) {
        /*