8196882: VS2017 Hotspot Defined vsnprintf Function Causes C2084 Already Defined Compilation Error

Thu, 02 Aug 2018 03:54:51 -0700

author
kevinw
date
Thu, 02 Aug 2018 03:54:51 -0700
changeset 9478
f3108e56b502
parent 9477
bbd1da3f538f
child 9479
b4ee249eb1c4

8196882: VS2017 Hotspot Defined vsnprintf Function Causes C2084 Already Defined Compilation Error
Summary: Add os::vsnprintf and os::snprintf.
Reviewed-by: kbarrett, lfoltan, stuefe, mlarsson

src/os/posix/vm/os_posix.cpp file | annotate | diff | comparison | revisions
src/os/windows/vm/os_windows.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp file | annotate | diff | comparison | revisions
src/share/vm/oops/generateOopMap.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/jni.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/jvm.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/os.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/os.hpp file | annotate | diff | comparison | revisions
src/share/vm/utilities/exceptions.cpp file | annotate | diff | comparison | revisions
src/share/vm/utilities/globalDefinitions_visCPP.hpp file | annotate | diff | comparison | revisions
src/share/vm/utilities/ostream.cpp file | annotate | diff | comparison | revisions
src/share/vm/utilities/ostream.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/os/posix/vm/os_posix.cpp	Wed Aug 01 04:19:22 2018 -0400
     1.2 +++ b/src/os/posix/vm/os_posix.cpp	Thu Aug 02 03:54:51 2018 -0700
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 -* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
     1.6 +* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -166,6 +166,16 @@
    1.11    return aligned_base;
    1.12  }
    1.13  
    1.14 +int os::vsnprintf(char* buf, size_t len, const char* fmt, va_list args) {
    1.15 +  int result = ::vsnprintf(buf, len, fmt, args);
    1.16 +  // If an encoding error occurred (result < 0) then it's not clear
    1.17 +  // whether the buffer is NUL terminated, so ensure it is.
    1.18 +  if ((result < 0) && (len > 0)) {
    1.19 +    buf[len - 1] = '\0';
    1.20 +  }
    1.21 +  return result;
    1.22 +}
    1.23 +
    1.24  void os::Posix::print_load_average(outputStream* st) {
    1.25    st->print("load average:");
    1.26    double loadavg[3];
     2.1 --- a/src/os/windows/vm/os_windows.cpp	Wed Aug 01 04:19:22 2018 -0400
     2.2 +++ b/src/os/windows/vm/os_windows.cpp	Thu Aug 02 03:54:51 2018 -0700
     2.3 @@ -1837,6 +1837,42 @@
     2.4    st->cr();
     2.5  }
     2.6  
     2.7 +
     2.8 +int os::vsnprintf(char* buf, size_t len, const char* fmt, va_list args) {
     2.9 +#if _MSC_VER >= 1900
    2.10 +  // Starting with Visual Studio 2015, vsnprint is C99 compliant.
    2.11 +  int result = ::vsnprintf(buf, len, fmt, args);
    2.12 +  // If an encoding error occurred (result < 0) then it's not clear
    2.13 +  // whether the buffer is NUL terminated, so ensure it is.
    2.14 +  if ((result < 0) && (len > 0)) {
    2.15 +    buf[len - 1] = '\0';
    2.16 +  }
    2.17 +  return result;
    2.18 +#else
    2.19 +  // Before Visual Studio 2015, vsnprintf is not C99 compliant, so use
    2.20 +  // _vsnprintf, whose behavior seems to be *mostly* consistent across
    2.21 +  // versions.  However, when len == 0, avoid _vsnprintf too, and just
    2.22 +  // go straight to _vscprintf.  The output is going to be truncated in
    2.23 +  // that case, except in the unusual case of empty output.  More
    2.24 +  // importantly, the documentation for various versions of Visual Studio
    2.25 +  // are inconsistent about the behavior of _vsnprintf when len == 0,
    2.26 +  // including it possibly being an error.
    2.27 +  int result = -1;
    2.28 +  if (len > 0) {
    2.29 +    result = _vsnprintf(buf, len, fmt, args);
    2.30 +    // If output (including NUL terminator) is truncated, the buffer
    2.31 +    // won't be NUL terminated.  Add the trailing NUL specified by C99.
    2.32 +    if ((result < 0) || (result >= (int) len)) {
    2.33 +      buf[len - 1] = '\0';
    2.34 +    }
    2.35 +  }
    2.36 +  if (result < 0) {
    2.37 +    result = _vscprintf(fmt, args);
    2.38 +  }
    2.39 +  return result;
    2.40 +#endif // _MSC_VER dispatch
    2.41 +}
    2.42 +
    2.43  void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) {
    2.44    // do nothing
    2.45  }
     3.1 --- a/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp	Wed Aug 01 04:19:22 2018 -0400
     3.2 +++ b/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp	Thu Aug 02 03:54:51 2018 -0700
     3.3 @@ -41,13 +41,13 @@
     3.4    int _cur;
     3.5  
     3.6    void vappend(const char* format, va_list ap)  ATTRIBUTE_PRINTF(2, 0) {
     3.7 -    int res = vsnprintf(&_buffer[_cur], BUFFER_LEN - _cur, format, ap);
     3.8 -    if (res != -1) {
     3.9 -      _cur += res;
    3.10 -    } else {
    3.11 +    int res = os::vsnprintf(&_buffer[_cur], BUFFER_LEN - _cur, format, ap);
    3.12 +    if (res > BUFFER_LEN) {
    3.13        DEBUG_ONLY(warning("buffer too small in LineBuffer");)
    3.14        _buffer[BUFFER_LEN -1] = 0;
    3.15        _cur = BUFFER_LEN; // vsnprintf above should not add to _buffer if we are called again
    3.16 +    } else if (res != -1) {
    3.17 +      _cur += res;
    3.18      }
    3.19    }
    3.20  
     4.1 --- a/src/share/vm/oops/generateOopMap.cpp	Wed Aug 01 04:19:22 2018 -0400
     4.2 +++ b/src/share/vm/oops/generateOopMap.cpp	Thu Aug 02 03:54:51 2018 -0700
     4.3 @@ -1,5 +1,5 @@
     4.4  /*
     4.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     4.6 + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
     4.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.8   *
     4.9   * This code is free software; you can redistribute it and/or modify it
    4.10 @@ -29,6 +29,7 @@
    4.11  #include "oops/symbol.hpp"
    4.12  #include "runtime/handles.inline.hpp"
    4.13  #include "runtime/java.hpp"
    4.14 +#include "runtime/os.hpp"
    4.15  #include "runtime/relocator.hpp"
    4.16  #include "utilities/bitMap.inline.hpp"
    4.17  #include "prims/methodHandles.hpp"
    4.18 @@ -2133,10 +2134,10 @@
    4.19  void GenerateOopMap::error_work(const char *format, va_list ap) {
    4.20    _got_error = true;
    4.21    char msg_buffer[512];
    4.22 -  vsnprintf(msg_buffer, sizeof(msg_buffer), format, ap);
    4.23 +  os::vsnprintf(msg_buffer, sizeof(msg_buffer), format, ap);
    4.24    // Append method name
    4.25    char msg_buffer2[512];
    4.26 -  jio_snprintf(msg_buffer2, sizeof(msg_buffer2), "%s in method %s", msg_buffer, method()->name()->as_C_string());
    4.27 +  os::snprintf(msg_buffer2, sizeof(msg_buffer2), "%s in method %s", msg_buffer, method()->name()->as_C_string());
    4.28    _exception = Exceptions::new_exception(Thread::current(),
    4.29                  vmSymbols::java_lang_LinkageError(), msg_buffer2);
    4.30  }
    4.31 @@ -2154,7 +2155,7 @@
    4.32    _got_error = true;
    4.33    // Append method name
    4.34    char msg_buffer2[512];
    4.35 -  jio_snprintf(msg_buffer2, sizeof(msg_buffer2), "%s in method %s", msg,
    4.36 +  os::snprintf(msg_buffer2, sizeof(msg_buffer2), "%s in method %s", msg,
    4.37                 method()->name()->as_C_string());
    4.38    _exception = Exceptions::new_exception(Thread::current(),
    4.39                  vmSymbols::java_lang_LinkageError(), msg_buffer2);
     5.1 --- a/src/share/vm/prims/jni.cpp	Wed Aug 01 04:19:22 2018 -0400
     5.2 +++ b/src/share/vm/prims/jni.cpp	Thu Aug 02 03:54:51 2018 -0700
     5.3 @@ -33,6 +33,7 @@
     5.4  #include "classfile/vmSymbols.hpp"
     5.5  #include "interpreter/linkResolver.hpp"
     5.6  #include "utilities/macros.hpp"
     5.7 +#include "utilities/ostream.hpp"
     5.8  #if INCLUDE_ALL_GCS
     5.9  #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
    5.10  #endif // INCLUDE_ALL_GCS
    5.11 @@ -5127,6 +5128,7 @@
    5.12      run_unit_test(GuardedMemory::test_guarded_memory());
    5.13      run_unit_test(AltHashing::test_alt_hash());
    5.14      run_unit_test(test_loggc_filename());
    5.15 +    run_unit_test(test_snprintf());
    5.16      run_unit_test(TestNewSize_test());
    5.17      run_unit_test(TestKlass_test());
    5.18      run_unit_test(Test_linked_list());
     6.1 --- a/src/share/vm/prims/jvm.cpp	Wed Aug 01 04:19:22 2018 -0400
     6.2 +++ b/src/share/vm/prims/jvm.cpp	Thu Aug 02 03:54:51 2018 -0700
     6.3 @@ -2915,16 +2915,12 @@
     6.4  
     6.5  ATTRIBUTE_PRINTF(3, 0)
     6.6  int jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args) {
     6.7 -  // see bug 4399518, 4417214
     6.8 +  // Reject count values that are negative signed values converted to
     6.9 +  // unsigned; see bug 4399518, 4417214
    6.10    if ((intptr_t)count <= 0) return -1;
    6.11  
    6.12 -  int result = vsnprintf(str, count, fmt, args);
    6.13 -  // Note: on truncation vsnprintf(3) on Unix returns number of
    6.14 -  // characters which would have been written had the buffer been large
    6.15 -  // enough; on Windows, it returns -1. We handle both cases here and
    6.16 -  // always return -1, and perform null termination.
    6.17 -  if ((result > 0 && (size_t)result >= count) || result == -1) {
    6.18 -    str[count - 1] = '\0';
    6.19 +  int result = os::vsnprintf(str, count, fmt, args);
    6.20 +  if (result > 0 && (size_t)result >= count) {
    6.21      result = -1;
    6.22    }
    6.23  
     7.1 --- a/src/share/vm/runtime/os.cpp	Wed Aug 01 04:19:22 2018 -0400
     7.2 +++ b/src/share/vm/runtime/os.cpp	Thu Aug 02 03:54:51 2018 -0700
     7.3 @@ -108,6 +108,14 @@
     7.4  #endif
     7.5  }
     7.6  
     7.7 +int os::snprintf(char* buf, size_t len, const char* fmt, ...) {
     7.8 +  va_list args;
     7.9 +  va_start(args, fmt);
    7.10 +  int result = os::vsnprintf(buf, len, fmt, args);
    7.11 +  va_end(args);
    7.12 +  return result;
    7.13 +}
    7.14 +
    7.15  // Fill in buffer with current local time as an ISO-8601 string.
    7.16  // E.g., yyyy-mm-ddThh:mm:ss-zzzz.
    7.17  // Returns buffer, or NULL if it failed.
     8.1 --- a/src/share/vm/runtime/os.hpp	Wed Aug 01 04:19:22 2018 -0400
     8.2 +++ b/src/share/vm/runtime/os.hpp	Thu Aug 02 03:54:51 2018 -0700
     8.3 @@ -616,6 +616,9 @@
     8.4    static void *find_agent_function(AgentLibrary *agent_lib, bool check_lib,
     8.5                                     const char *syms[], size_t syms_len);
     8.6  
     8.7 +  static int vsnprintf(char* buf, size_t len, const char* fmt, va_list args) ATTRIBUTE_PRINTF(3, 0);
     8.8 +  static int snprintf(char* buf, size_t len, const char* fmt, ...) ATTRIBUTE_PRINTF(3, 4);
     8.9 +
    8.10    // Print out system information; they are called by fatal error handler.
    8.11    // Output format may be different on different platforms.
    8.12    static void print_os_info(outputStream* st);
     9.1 --- a/src/share/vm/utilities/exceptions.cpp	Wed Aug 01 04:19:22 2018 -0400
     9.2 +++ b/src/share/vm/utilities/exceptions.cpp	Thu Aug 02 03:54:51 2018 -0700
     9.3 @@ -30,6 +30,7 @@
     9.4  #include "runtime/init.hpp"
     9.5  #include "runtime/java.hpp"
     9.6  #include "runtime/javaCalls.hpp"
     9.7 +#include "runtime/os.hpp"
     9.8  #include "runtime/thread.inline.hpp"
     9.9  #include "runtime/threadCritical.hpp"
    9.10  #include "utilities/events.hpp"
    9.11 @@ -246,8 +247,7 @@
    9.12    va_list ap;
    9.13    va_start(ap, format);
    9.14    char msg[max_msg_size];
    9.15 -  vsnprintf(msg, max_msg_size, format, ap);
    9.16 -  msg[max_msg_size-1] = '\0';
    9.17 +  os::vsnprintf(msg, max_msg_size, format, ap);
    9.18    va_end(ap);
    9.19    _throw_msg(thread, file, line, h_name, msg);
    9.20  }
    10.1 --- a/src/share/vm/utilities/globalDefinitions_visCPP.hpp	Wed Aug 01 04:19:22 2018 -0400
    10.2 +++ b/src/share/vm/utilities/globalDefinitions_visCPP.hpp	Thu Aug 02 03:54:51 2018 -0700
    10.3 @@ -1,5 +1,5 @@
    10.4  /*
    10.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
    10.6 + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
    10.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.8   *
    10.9   * This code is free software; you can redistribute it and/or modify it
   10.10 @@ -187,14 +187,6 @@
   10.11  #pragma warning( disable : 4996 ) // unsafe string functions. Same as define _CRT_SECURE_NO_WARNINGS/_CRT_SECURE_NO_DEPRICATE
   10.12  #endif
   10.13  
   10.14 -inline int vsnprintf(char* buf, size_t count, const char* fmt, va_list argptr) {
   10.15 -  // If number of characters written == count, Windows doesn't write a
   10.16 -  // terminating NULL, so we do it ourselves.
   10.17 -  int ret = _vsnprintf(buf, count, fmt, argptr);
   10.18 -  if (count > 0) buf[count-1] = '\0';
   10.19 -  return ret;
   10.20 -}
   10.21 -
   10.22  // Portability macros
   10.23  #define PRAGMA_INTERFACE
   10.24  #define PRAGMA_IMPLEMENTATION
    11.1 --- a/src/share/vm/utilities/ostream.cpp	Wed Aug 01 04:19:22 2018 -0400
    11.2 +++ b/src/share/vm/utilities/ostream.cpp	Thu Aug 02 03:54:51 2018 -0700
    11.3 @@ -1,5 +1,5 @@
    11.4  /*
    11.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
    11.6 + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
    11.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.8   *
    11.9   * This code is free software; you can redistribute it and/or modify it
   11.10 @@ -27,6 +27,7 @@
   11.11  #include "gc_implementation/shared/gcId.hpp"
   11.12  #include "oops/oop.inline.hpp"
   11.13  #include "runtime/arguments.hpp"
   11.14 +#include "runtime/os.hpp"
   11.15  #include "utilities/defaultStream.hpp"
   11.16  #include "utilities/ostream.hpp"
   11.17  #include "utilities/top.hpp"
   11.18 @@ -89,6 +90,8 @@
   11.19                                         const char* format, va_list ap,
   11.20                                         bool add_cr,
   11.21                                         size_t& result_len) {
   11.22 +  assert(buflen >= 2, "buffer too small");
   11.23 +
   11.24    const char* result;
   11.25    if (add_cr)  buflen--;
   11.26    if (!strchr(format, '%')) {
   11.27 @@ -101,18 +104,20 @@
   11.28      result = va_arg(ap, const char*);
   11.29      result_len = strlen(result);
   11.30      if (add_cr && result_len >= buflen)  result_len = buflen-1;  // truncate
   11.31 -  } else if (vsnprintf(buffer, buflen, format, ap) >= 0) {
   11.32 +  } else {
   11.33 +    int written = os::vsnprintf(buffer, buflen, format, ap);
   11.34 +    assert(written >= 0, "vsnprintf encoding error");
   11.35      result = buffer;
   11.36 -    result_len = strlen(result);
   11.37 -  } else {
   11.38 -    DEBUG_ONLY(warning("increase O_BUFLEN in ostream.hpp -- output truncated");)
   11.39 -    result = buffer;
   11.40 -    result_len = buflen - 1;
   11.41 -    buffer[result_len] = 0;
   11.42 +    if ((size_t)written < buflen) {
   11.43 +      result_len = written;
   11.44 +    } else {
   11.45 +      DEBUG_ONLY(warning("increase O_BUFLEN in ostream.hpp -- output truncated");)
   11.46 +      result_len = buflen - 1;
   11.47 +    }
   11.48    }
   11.49    if (add_cr) {
   11.50      if (result != buffer) {
   11.51 -      strncpy(buffer, result, buflen);
   11.52 +      memcpy(buffer, result, result_len);
   11.53        result = buffer;
   11.54      }
   11.55      buffer[result_len++] = '\n';
   11.56 @@ -578,6 +583,117 @@
   11.57      assert(o_result == NULL, err_msg("Too long file name after pid expansion should return NULL, but got '%s'", o_result));
   11.58    }
   11.59  }
   11.60 +
   11.61 +//////////////////////////////////////////////////////////////////////////////
   11.62 +// Test os::vsnprintf and friends.
   11.63 +
   11.64 +void check_snprintf_result(int expected, size_t limit, int actual, bool expect_count) {
   11.65 +  if (expect_count || ((size_t)expected < limit)) {
   11.66 +    assert(expected == actual, "snprintf result not expected value");
   11.67 +  } else {
   11.68 +    // Make this check more permissive for jdk8u, don't assert that actual == 0.
   11.69 +    // e.g. jio_vsnprintf_wrapper and jio_snprintf return -1 when expected >= limit
   11.70 +    if (expected >= (int) limit) {
   11.71 +      assert(actual == -1, "snprintf result should be -1 for expected >= limit");
   11.72 +    } else {
   11.73 +      assert(actual > 0, "snprintf result should be >0 for expected < limit");
   11.74 +    }
   11.75 +  }
   11.76 +}
   11.77 +
   11.78 +// PrintFn is expected to be int (*)(char*, size_t, const char*, ...).
   11.79 +// But jio_snprintf is a C-linkage function with that signature, which
   11.80 +// has a different type on some platforms (like Solaris).
   11.81 +template<typename PrintFn>
   11.82 +void test_snprintf(PrintFn pf, bool expect_count) {
   11.83 +  const char expected[] = "abcdefghijklmnopqrstuvwxyz";
   11.84 +  const int expected_len = sizeof(expected) - 1;
   11.85 +  const size_t padding_size = 10;
   11.86 +  char buffer[2 * (sizeof(expected) + padding_size)];
   11.87 +  char check_buffer[sizeof(buffer)];
   11.88 +  const char check_char = '1';  // Something not in expected.
   11.89 +  memset(check_buffer, check_char, sizeof(check_buffer));
   11.90 +  const size_t sizes_to_test[] = {
   11.91 +    sizeof(buffer) - padding_size,       // Fits, with plenty of space to spare.
   11.92 +    sizeof(buffer)/2,                    // Fits, with space to spare.
   11.93 +    sizeof(buffer)/4,                    // Doesn't fit.
   11.94 +    sizeof(expected) + padding_size + 1, // Fits, with a little room to spare
   11.95 +    sizeof(expected) + padding_size,     // Fits exactly.
   11.96 +    sizeof(expected) + padding_size - 1, // Doesn't quite fit.
   11.97 +    2,                                   // One char + terminating NUL.
   11.98 +    1,                                   // Only space for terminating NUL.
   11.99 +    0 };                                 // No space at all.
  11.100 +  for (unsigned i = 0; i < ARRAY_SIZE(sizes_to_test); ++i) {
  11.101 +    memset(buffer, check_char, sizeof(buffer)); // To catch stray writes.
  11.102 +    size_t test_size = sizes_to_test[i];
  11.103 +    ResourceMark rm;
  11.104 +    stringStream s;
  11.105 +    s.print("test_size: " SIZE_FORMAT, test_size);
  11.106 +    size_t prefix_size = padding_size;
  11.107 +    guarantee(test_size <= (sizeof(buffer) - prefix_size), "invariant");
  11.108 +    size_t write_size = MIN2(sizeof(expected), test_size);
  11.109 +    size_t suffix_size = sizeof(buffer) - prefix_size - write_size;
  11.110 +    char* write_start = buffer + prefix_size;
  11.111 +    char* write_end = write_start + write_size;
  11.112 +
  11.113 +    int result = pf(write_start, test_size, "%s", expected);
  11.114 +
  11.115 +    check_snprintf_result(expected_len, test_size, result, expect_count);
  11.116 +
  11.117 +    // Verify expected output.
  11.118 +    if (test_size > 0) {
  11.119 +      assert(0 == strncmp(write_start, expected, write_size - 1), "strncmp failure");
  11.120 +      // Verify terminating NUL of output.
  11.121 +      assert('\0' == write_start[write_size - 1], "null terminator failure");
  11.122 +    } else {
  11.123 +      guarantee(test_size == 0, "invariant");
  11.124 +      guarantee(write_size == 0, "invariant");
  11.125 +      guarantee(prefix_size + suffix_size == sizeof(buffer), "invariant");
  11.126 +      guarantee(write_start == write_end, "invariant");
  11.127 +    }
  11.128 +
  11.129 +    // Verify no scribbling on prefix or suffix.
  11.130 +    assert(0 == strncmp(buffer, check_buffer, prefix_size), "prefix scribble");
  11.131 +    assert(0 == strncmp(write_end, check_buffer, suffix_size), "suffix scribble");
  11.132 +  }
  11.133 +
  11.134 +  // Special case of 0-length buffer with empty (except for terminator) output.
  11.135 +  check_snprintf_result(0, 0, pf(NULL, 0, "%s", ""), expect_count);
  11.136 +  check_snprintf_result(0, 0, pf(NULL, 0, ""), expect_count);
  11.137 +}
  11.138 +
  11.139 +// This is probably equivalent to os::snprintf, but we're being
  11.140 +// explicit about what we're testing here.
  11.141 +static int vsnprintf_wrapper(char* buf, size_t len, const char* fmt, ...) {
  11.142 +  va_list args;
  11.143 +  va_start(args, fmt);
  11.144 +  int result = os::vsnprintf(buf, len, fmt, args);
  11.145 +  va_end(args);
  11.146 +  return result;
  11.147 +}
  11.148 +
  11.149 +// These are declared in jvm.h; test here, with related functions.
  11.150 +extern "C" {
  11.151 +int jio_vsnprintf(char*, size_t, const char*, va_list);
  11.152 +int jio_snprintf(char*, size_t, const char*, ...);
  11.153 +}
  11.154 +
  11.155 +// This is probably equivalent to jio_snprintf, but we're being
  11.156 +// explicit about what we're testing here.
  11.157 +static int jio_vsnprintf_wrapper(char* buf, size_t len, const char* fmt, ...) {
  11.158 +  va_list args;
  11.159 +  va_start(args, fmt);
  11.160 +  int result = jio_vsnprintf(buf, len, fmt, args);
  11.161 +  va_end(args);
  11.162 +  return result;
  11.163 +}
  11.164 +
  11.165 +void test_snprintf() {
  11.166 +  test_snprintf(vsnprintf_wrapper, true);
  11.167 +  test_snprintf(os::snprintf, true);
  11.168 +  test_snprintf(jio_vsnprintf_wrapper, false); // jio_vsnprintf returns -1 on error including exceeding buffer size
  11.169 +  test_snprintf(jio_snprintf, false);          // jio_snprintf calls jio_vsnprintf
  11.170 +}
  11.171  #endif // PRODUCT
  11.172  
  11.173  fileStream::fileStream(const char* file_name) {
    12.1 --- a/src/share/vm/utilities/ostream.hpp	Wed Aug 01 04:19:22 2018 -0400
    12.2 +++ b/src/share/vm/utilities/ostream.hpp	Thu Aug 02 03:54:51 2018 -0700
    12.3 @@ -258,6 +258,7 @@
    12.4  #ifndef PRODUCT
    12.5  // unit test for checking -Xloggc:<filename> parsing result
    12.6  void test_loggc_filename();
    12.7 +void test_snprintf();
    12.8  #endif
    12.9  
   12.10  void ostream_init();

mercurial