diff -r bbd1da3f538f -r f3108e56b502 src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Wed Aug 01 04:19:22 2018 -0400 +++ b/src/os/windows/vm/os_windows.cpp Thu Aug 02 03:54:51 2018 -0700 @@ -1837,6 +1837,42 @@ st->cr(); } + +int os::vsnprintf(char* buf, size_t len, const char* fmt, va_list args) { +#if _MSC_VER >= 1900 + // Starting with Visual Studio 2015, vsnprint is C99 compliant. + int result = ::vsnprintf(buf, len, fmt, args); + // If an encoding error occurred (result < 0) then it's not clear + // whether the buffer is NUL terminated, so ensure it is. + if ((result < 0) && (len > 0)) { + buf[len - 1] = '\0'; + } + return result; +#else + // Before Visual Studio 2015, vsnprintf is not C99 compliant, so use + // _vsnprintf, whose behavior seems to be *mostly* consistent across + // versions. However, when len == 0, avoid _vsnprintf too, and just + // go straight to _vscprintf. The output is going to be truncated in + // that case, except in the unusual case of empty output. More + // importantly, the documentation for various versions of Visual Studio + // are inconsistent about the behavior of _vsnprintf when len == 0, + // including it possibly being an error. + int result = -1; + if (len > 0) { + result = _vsnprintf(buf, len, fmt, args); + // If output (including NUL terminator) is truncated, the buffer + // won't be NUL terminated. Add the trailing NUL specified by C99. + if ((result < 0) || (result >= (int) len)) { + buf[len - 1] = '\0'; + } + } + if (result < 0) { + result = _vscprintf(fmt, args); + } + return result; +#endif // _MSC_VER dispatch +} + void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) { // do nothing }