diff --git a/CHANGELOG b/CHANGELOG index bf9386b81..953dad85c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,11 @@ o Applied some nsock bugfixes from Diman Todorov. These don't affect the current version of Nmap, but are important for his upcoming Nmap Scripting Engine. +o Fixed a bug which would occasionally cause Nmap to crash with the + message "log_vwrite: write buffer not large enough". I thought I + conquered it in a previous release -- thanks to Doug Hoyte for finding a + corner case which proved me wrong. + o Integrated all 2nd quarter service detection fingerprint submissions. Please keep them coming! We now have 3,671 signatures representing 415 protocols. Thanks to version detection czar Doug diff --git a/output.cc b/output.cc index c7a9ff01e..d2f8d8be5 100644 --- a/output.cc +++ b/output.cc @@ -675,12 +675,14 @@ char* xml_convert (const char* str) { va_start() AND va_end() calls. */ void log_vwrite(int logt, const char *fmt, va_list ap) { static char *writebuf = NULL; - int writebuflen = 65536; + int writebuflen = 8192; bool skid_noxlate = false; int rc = 0; int len; int fileidx = 0; int l; + va_list apcopy; + /* Account for extended output under high debugging/verbosity */ if (o.debugging > 2 || o.verbose > 2) @@ -708,20 +710,29 @@ void log_vwrite(int logt, const char *fmt, va_list ap) { case LOG_MACHINE: case LOG_SKID: case LOG_XML: + va_copy(apcopy, ap); /* Needed in case we need to so a second vnsprintf */ l = logt; fileidx = 0; while ((l&1)==0) { fileidx++; l>>=1; } assert(fileidx < LOG_NUM_FILES); if (o.logfd[fileidx]) { len = vsnprintf(writebuf, writebuflen, fmt, ap); - if (len == 0) { + if (len == 0) { + va_end(apcopy); return; } else if (len < 0) { fprintf(stderr, "vnsprintf returned %d in %s -- bizarre. Quitting.\n", len, __FUNCTION__); exit(1); } else if (len >= writebuflen) { - fprintf(stderr, "%s: write buffer not large enough -- need to increase from %d to at least %d (logt == %d). Please email this message to fyodor@insecure.org. Quitting.\n", __FUNCTION__, writebuflen, len, logt); - exit(1); + /* Didn't have enough space. Expand writebuf and try again */ + free(writebuf); + writebuflen = len + 1024; + writebuf = (char *) safe_malloc(writebuflen); + len = vsnprintf(writebuf, writebuflen, fmt, apcopy); + if (len <= 0 || len >= writebuflen) { + fprintf(stderr, "%s: vnsprintf failed. Even after increasing bufferlen to %d, vsnprintf returned %d (logt == %d). Please email this message to fyodor@insecure.org. Quitting.\n", __FUNCTION__, writebuflen, len, logt); + exit(1); + } } if (logt == LOG_SKID && !skid_noxlate) skid_output(writebuf); @@ -730,6 +741,7 @@ void log_vwrite(int logt, const char *fmt, va_list ap) { fprintf(stderr, "Failed to write %d bytes of data to (logt==%d) stream. fwrite returned %d. Quitting.\n", len, logt, rc); exit(1); } + va_end(apcopy); } break;