# HG changeset patch
# User zgu
# Date 1549941040 0
#      Tue Feb 12 03:10:40 2019 +0000
# Node ID cfb34db6589e222d34e5b736b99ed4f69c261c4f
# Parent  f8beb13aec9f8c291282ee8ec4473c8627aa7e07
6424123, PR3696: JVM crashes on failed 'strdup' call
Summary: Calling os::malloc()/os::strdup() and new os::strdup_check_oom() instead of ::malloc()/::strdup() for native memory tracking purpose
Reviewed-by: coleenp, ctornqvi, kvn

diff -Nru openjdk.orig/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp openjdk/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp
--- openjdk.orig/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp	2021-07-27 18:01:11.869025324 +0100
+++ openjdk/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp	2021-07-27 18:05:29.412943160 +0100
@@ -29,6 +29,7 @@
 #include "compiler/disassembler.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/java.hpp"
+#include "runtime/os.hpp"
 #include "runtime/stubCodeGenerator.hpp"
 #include "utilities/defaultStream.hpp"
 #include "vm_version_ppc.hpp"
@@ -128,7 +129,7 @@
                (has_vshasig() ? " sha"     : "")
                // Make sure number of %s matches num_features!
               );
-  _features_str = strdup(buf);
+  _features_str = os::strdup(buf);
   if (Verbose) {
     print_features();
   }
diff -Nru openjdk.orig/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp openjdk/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp
--- openjdk.orig/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp	2021-07-27 18:01:11.869025324 +0100
+++ openjdk/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp	2021-07-27 18:05:29.413943171 +0100
@@ -26,6 +26,7 @@
 #include "asm/macroAssembler.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/java.hpp"
+#include "runtime/os.hpp"
 #include "runtime/stubCodeGenerator.hpp"
 #include "vm_version_sparc.hpp"
 #ifdef TARGET_OS_FAMILY_linux
@@ -270,7 +271,7 @@
                (!has_hardware_fsmuld() ? ", no-fsmuld" : ""));
 
   // buf is started with ", " or is empty
-  _features_str = strdup(strlen(buf) > 2 ? buf + 2 : buf);
+  _features_str = os::strdup(strlen(buf) > 2 ? buf + 2 : buf);
 
   // UseVIS is set to the smallest of what hardware supports and what
   // the command line requires.  I.e., you cannot set UseVIS to 3 on
@@ -496,7 +497,7 @@
 int VM_Version::parse_features(const char* implementation) {
   int features = unknown_m;
   // Convert to UPPER case before compare.
-  char* impl = os::strdup(implementation);
+  char* impl = os::strdup_check_oom(implementation);
 
   for (int i = 0; impl[i] != 0; i++)
     impl[i] = (char)toupper((uint)impl[i]);
diff -Nru openjdk.orig/hotspot/src/cpu/x86/vm/vm_version_x86.cpp openjdk/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
--- openjdk.orig/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	2021-07-27 18:01:11.869025324 +0100
+++ openjdk/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	2021-07-27 18:05:29.413943171 +0100
@@ -27,6 +27,7 @@
 #include "asm/macroAssembler.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/java.hpp"
+#include "runtime/os.hpp"
 #include "runtime/stubCodeGenerator.hpp"
 #include "vm_version_x86.hpp"
 #ifdef TARGET_OS_FAMILY_linux
@@ -527,7 +528,7 @@
                (supports_bmi1() ? ", bmi1" : ""),
                (supports_bmi2() ? ", bmi2" : ""),
                (supports_adx() ? ", adx" : ""));
-  _features_str = strdup(buf);
+  _features_str = os::strdup(buf);
 
   // UseSSE is set to the smaller of what hardware supports and what
   // the command line requires.  I.e., you cannot set UseSSE to 2 on
diff -Nru openjdk.orig/hotspot/src/os/aix/vm/os_aix.cpp openjdk/hotspot/src/os/aix/vm/os_aix.cpp
--- openjdk.orig/hotspot/src/os/aix/vm/os_aix.cpp	2021-07-16 05:52:52.000000000 +0100
+++ openjdk/hotspot/src/os/aix/vm/os_aix.cpp	2021-07-27 18:05:29.413943171 +0100
@@ -56,6 +56,7 @@
 #include "runtime/mutexLocker.hpp"
 #include "runtime/objectMonitor.hpp"
 #include "runtime/orderAccess.inline.hpp"
+#include "runtime/os.hpp"
 #include "runtime/osThread.hpp"
 #include "runtime/perfMemory.hpp"
 #include "runtime/sharedRuntime.hpp"
@@ -389,10 +390,10 @@
   // default should be 4K.
   size_t data_page_size = SIZE_4K;
   {
-    void* p = ::malloc(SIZE_16M);
+    void* p = os::malloc(SIZE_16M, mtInternal);
     guarantee(p != NULL, "malloc failed");
     data_page_size = os::Aix::query_pagesize(p);
-    ::free(p);
+    os::free(p);
   }
 
   // query default shm page size (LDR_CNTRL SHMPSIZE)
diff -Nru openjdk.orig/hotspot/src/os/aix/vm/porting_aix.cpp openjdk/hotspot/src/os/aix/vm/porting_aix.cpp
--- openjdk.orig/hotspot/src/os/aix/vm/porting_aix.cpp	2021-07-16 05:52:52.000000000 +0100
+++ openjdk/hotspot/src/os/aix/vm/porting_aix.cpp	2021-07-27 18:05:29.414943183 +0100
@@ -23,6 +23,8 @@
  */
 
 #include "asm/assembler.hpp"
+#include "memory/allocation.inline.hpp"
+#include "runtime/os.hpp"
 #include "loadlib_aix.hpp"
 #include "porting_aix.hpp"
 #include "utilities/debug.hpp"
@@ -82,7 +84,7 @@
     while (n) {
       node* p = n;
       n = n->next;
-      free(p->v);
+      os::free(p->v);
       delete p;
     }
   }
@@ -94,7 +96,7 @@
       }
     }
     node* p = new node;
-    p->v = strdup(s);
+    p->v = os::strdup_check_oom(s);
     p->next = first;
     first = p;
     return p->v;
diff -Nru openjdk.orig/hotspot/src/os/windows/vm/perfMemory_windows.cpp openjdk/hotspot/src/os/windows/vm/perfMemory_windows.cpp
--- openjdk.orig/hotspot/src/os/windows/vm/perfMemory_windows.cpp	2021-07-16 05:52:52.000000000 +0100
+++ openjdk/hotspot/src/os/windows/vm/perfMemory_windows.cpp	2021-07-27 18:05:29.414943183 +0100
@@ -29,6 +29,7 @@
 #include "oops/oop.inline.hpp"
 #include "os_windows.inline.hpp"
 #include "runtime/handles.inline.hpp"
+#include "runtime/os.hpp"
 #include "runtime/perfMemory.hpp"
 #include "services/memTracker.hpp"
 #include "utilities/exceptions.hpp"
@@ -1382,7 +1383,7 @@
   // the file has been successfully created and the file mapping
   // object has been created.
   sharedmem_fileHandle = fh;
-  sharedmem_fileName = strdup(filename);
+  sharedmem_fileName = os::strdup(filename);
 
   return fmh;
 }
diff -Nru openjdk.orig/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp openjdk/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp
--- openjdk.orig/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp	2021-07-16 05:52:52.000000000 +0100
+++ openjdk/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp	2021-07-27 18:05:29.414943183 +0100
@@ -30,6 +30,7 @@
 #include "c1/c1_MacroAssembler.hpp"
 #include "c1/c1_ValueStack.hpp"
 #include "ci/ciInstance.hpp"
+#include "runtime/os.hpp"
 #ifdef TARGET_ARCH_x86
 # include "nativeInst_x86.hpp"
 # include "vmreg_x86.inline.hpp"
@@ -884,7 +885,7 @@
           stringStream st;
           st.print("bad oop %s at %d", r->as_Register()->name(), _masm->offset());
 #ifdef SPARC
-          _masm->_verify_oop(r->as_Register(), strdup(st.as_string()), __FILE__, __LINE__);
+          _masm->_verify_oop(r->as_Register(), os::strdup(st.as_string(), mtCompiler), __FILE__, __LINE__);
 #else
           _masm->verify_oop(r->as_Register());
 #endif
diff -Nru openjdk.orig/hotspot/src/share/vm/classfile/classLoader.cpp openjdk/hotspot/src/share/vm/classfile/classLoader.cpp
--- openjdk.orig/hotspot/src/share/vm/classfile/classLoader.cpp	2021-07-16 05:52:52.000000000 +0100
+++ openjdk/hotspot/src/share/vm/classfile/classLoader.cpp	2021-07-27 18:05:29.414943183 +0100
@@ -382,7 +382,7 @@
 }
 
 LazyClassPathEntry::LazyClassPathEntry(const char* path, const struct stat* st, bool throw_exception) : ClassPathEntry() {
-  _path = strdup(path);
+  _path = os::strdup_check_oom(path);
   _st = *st;
   _meta_index = NULL;
   _resolved_entry = NULL;
@@ -390,6 +390,10 @@
   _throw_exception = throw_exception;
 }
 
+LazyClassPathEntry::~LazyClassPathEntry() {
+  os::free((void*) _path);
+}
+
 bool LazyClassPathEntry::is_jar_file() {
   return ((_st.st_mode & S_IFREG) == S_IFREG);
 }
@@ -596,7 +600,7 @@
         default:
         {
           if (!skipCurrentJar && cur_entry != NULL) {
-            char* new_name = strdup(package_name);
+            char* new_name = os::strdup_check_oom(package_name);
             boot_class_path_packages.append(new_name);
           }
         }
diff -Nru openjdk.orig/hotspot/src/share/vm/classfile/classLoader.hpp openjdk/hotspot/src/share/vm/classfile/classLoader.hpp
--- openjdk.orig/hotspot/src/share/vm/classfile/classLoader.hpp	2021-07-16 05:52:52.000000000 +0100
+++ openjdk/hotspot/src/share/vm/classfile/classLoader.hpp	2021-07-27 18:07:47.527507912 +0100
@@ -136,7 +136,7 @@
   bool is_jar_file();
   const char* name()  { return _path; }
   LazyClassPathEntry(const char* path, const struct stat* st, bool throw_exception);
-  virtual ~LazyClassPathEntry() {}
+  virtual ~LazyClassPathEntry();
   u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
   ClassFileStream* open_stream(const char* name, TRAPS);
   void set_meta_index(MetaIndex* meta_index) { _meta_index = meta_index; }
diff -Nru openjdk.orig/hotspot/src/share/vm/compiler/compilerOracle.cpp openjdk/hotspot/src/share/vm/compiler/compilerOracle.cpp
--- openjdk.orig/hotspot/src/share/vm/compiler/compilerOracle.cpp	2021-07-16 05:52:52.000000000 +0100
+++ openjdk/hotspot/src/share/vm/compiler/compilerOracle.cpp	2021-07-27 18:05:29.415943194 +0100
@@ -33,6 +33,7 @@
 #include "oops/symbol.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/jniHandles.hpp"
+#include "runtime/os.hpp"
 
 class MethodMatcher : public CHeapObj<mtCompiler> {
  public:
@@ -219,7 +220,7 @@
                            const T value,  MethodMatcher* next) :
     MethodMatcher(class_name, class_mode, method_name, method_mode, signature, next),
                   _type(get_type_for<T>()), _value(copy_value<T>(value)) {
-    _option = strdup(opt);
+    _option = os::strdup_check_oom(opt);
   }
 
   ~TypedMethodOptionMatcher() {
diff -Nru openjdk.orig/hotspot/src/share/vm/opto/runtime.cpp openjdk/hotspot/src/share/vm/opto/runtime.cpp
--- openjdk.orig/hotspot/src/share/vm/opto/runtime.cpp	2021-07-16 05:52:52.000000000 +0100
+++ openjdk/hotspot/src/share/vm/opto/runtime.cpp	2021-07-27 18:05:29.415943194 +0100
@@ -1597,11 +1597,11 @@
   }
   NamedCounter* c;
   if (tag == NamedCounter::BiasedLockingCounter) {
-    c = new BiasedLockingNamedCounter(strdup(st.as_string()));
+    c = new BiasedLockingNamedCounter(st.as_string());
   } else if (tag == NamedCounter::RTMLockingCounter) {
-    c = new RTMLockingNamedCounter(strdup(st.as_string()));
+    c = new RTMLockingNamedCounter(st.as_string());
   } else {
-    c = new NamedCounter(strdup(st.as_string()), tag);
+    c = new NamedCounter(st.as_string(), tag);
   }
 
   // atomically add the new counter to the head of the list.  We only
diff -Nru openjdk.orig/hotspot/src/share/vm/opto/runtime.hpp openjdk/hotspot/src/share/vm/opto/runtime.hpp
--- openjdk.orig/hotspot/src/share/vm/opto/runtime.hpp	2021-07-16 05:52:52.000000000 +0100
+++ openjdk/hotspot/src/share/vm/opto/runtime.hpp	2021-07-27 18:05:29.415943194 +0100
@@ -74,11 +74,17 @@
 
  public:
   NamedCounter(const char *n, CounterTag tag = NoTag):
-    _name(n),
+    _name(n == NULL ? NULL : os::strdup(n)),
     _count(0),
     _next(NULL),
     _tag(tag) {}
 
+  ~NamedCounter() {
+    if (_name != NULL) {
+      os::free((void*)_name);
+    }
+  }
+
   const char * name() const     { return _name; }
   int count() const             { return _count; }
   address addr()                { return (address)&_count; }
diff -Nru openjdk.orig/hotspot/src/share/vm/runtime/arguments.cpp openjdk/hotspot/src/share/vm/runtime/arguments.cpp
--- openjdk.orig/hotspot/src/share/vm/runtime/arguments.cpp	2021-07-27 18:01:11.995026751 +0100
+++ openjdk/hotspot/src/share/vm/runtime/arguments.cpp	2021-07-27 18:05:29.416943205 +0100
@@ -820,7 +820,7 @@
   } else {
     *bldarray = REALLOC_C_HEAP_ARRAY(char*, *bldarray, new_count, mtInternal);
   }
-  (*bldarray)[*count] = strdup(arg);
+  (*bldarray)[*count] = os::strdup_check_oom(arg);
   *count = new_count;
 }
 
@@ -2259,7 +2259,7 @@
 }
 
 void Arguments::process_java_launcher_argument(const char* launcher, void* extra_info) {
-  _sun_java_launcher = strdup(launcher);
+  _sun_java_launcher = os::strdup_check_oom(launcher);
   if (strcmp("gamma", _sun_java_launcher) == 0) {
     _created_by_gamma_launcher = true;
   }
@@ -3410,7 +3410,7 @@
       // Redirect GC output to the file. -Xloggc:<filename>
       // ostream_init_log(), when called will use this filename
       // to initialize a fileStream.
-      _gc_log_filename = strdup(tail);
+      _gc_log_filename = os::strdup_check_oom(tail);
      if (!is_filename_valid(_gc_log_filename)) {
        jio_fprintf(defaultStream::output_stream(),
                   "Invalid file name for use with -Xloggc: Filename can only contain the "
diff -Nru openjdk.orig/hotspot/src/share/vm/runtime/fprofiler.cpp openjdk/hotspot/src/share/vm/runtime/fprofiler.cpp
--- openjdk.orig/hotspot/src/share/vm/runtime/fprofiler.cpp	2021-07-16 05:52:52.000000000 +0100
+++ openjdk/hotspot/src/share/vm/runtime/fprofiler.cpp	2021-07-27 18:05:29.416943205 +0100
@@ -628,10 +628,16 @@
   }
 
   vmNode(const char* name, const TickPosition where) : ProfilerNode() {
-    _name = name;
+    _name = os::strdup(name);
     update(where);
   }
 
+  ~vmNode() {
+    if (_name != NULL) {
+      os::free((void*)_name);
+    }
+  }
+
   const char *name()    const { return _name; }
   bool is_compiled()    const { return true; }
 
@@ -783,7 +789,7 @@
   assert(index >= 0, "Must be positive");
   // Note that we call strdup below since the symbol may be resource allocated
   if (!table[index]) {
-    table[index] = new (this) vmNode(os::strdup(name), where);
+    table[index] = new (this) vmNode(name, where);
   } else {
     ProfilerNode* prev = table[index];
     for(ProfilerNode* node = prev; node; node = node->next()) {
@@ -793,7 +799,7 @@
       }
       prev = node;
     }
-    prev->set_next(new (this) vmNode(os::strdup(name), where));
+    prev->set_next(new (this) vmNode(name, where));
   }
 }
 
diff -Nru openjdk.orig/hotspot/src/share/vm/runtime/os.cpp openjdk/hotspot/src/share/vm/runtime/os.cpp
--- openjdk.orig/hotspot/src/share/vm/runtime/os.cpp	2021-07-16 05:52:52.000000000 +0100
+++ openjdk/hotspot/src/share/vm/runtime/os.cpp	2021-07-27 18:05:29.416943205 +0100
@@ -552,6 +552,14 @@
 }
 
 
+char* os::strdup_check_oom(const char* str, MEMFLAGS flags) {
+  char* p = os::strdup(str, flags);
+  if (p == NULL) {
+    vm_exit_out_of_memory(strlen(str) + 1, OOM_MALLOC_ERROR, "os::strdup_check_oom");
+  }
+  return p;
+}
+
 
 #define paranoid                 0  /* only set to 1 if you suspect checking code has bug */
 
diff -Nru openjdk.orig/hotspot/src/share/vm/runtime/os.hpp openjdk/hotspot/src/share/vm/runtime/os.hpp
--- openjdk.orig/hotspot/src/share/vm/runtime/os.hpp	2021-07-16 05:52:52.000000000 +0100
+++ openjdk/hotspot/src/share/vm/runtime/os.hpp	2021-07-27 18:05:29.416943205 +0100
@@ -731,6 +731,8 @@
   static void  free    (void *memblock, MEMFLAGS flags = mtNone);
   static bool  check_heap(bool force = false);      // verify C heap integrity
   static char* strdup(const char *, MEMFLAGS flags = mtInternal);  // Like strdup
+  // Like strdup, but exit VM when strdup() returns NULL
+  static char* strdup_check_oom(const char*, MEMFLAGS flags = mtInternal);
 
 #ifndef PRODUCT
   static julong num_mallocs;         // # of calls to malloc/realloc
diff -Nru openjdk.orig/hotspot/src/share/vm/runtime/vmStructs.cpp openjdk/hotspot/src/share/vm/runtime/vmStructs.cpp
--- openjdk.orig/hotspot/src/share/vm/runtime/vmStructs.cpp	2021-07-16 05:52:52.000000000 +0100
+++ openjdk/hotspot/src/share/vm/runtime/vmStructs.cpp	2021-07-27 18:05:29.417943217 +0100
@@ -51,6 +51,7 @@
 #include "interpreter/bytecodes.hpp"
 #include "interpreter/interpreter.hpp"
 #include "memory/allocation.hpp"
+#include "memory/allocation.inline.hpp"
 #include "memory/cardTableRS.hpp"
 #include "memory/defNewGeneration.hpp"
 #include "memory/freeBlockDictionary.hpp"
@@ -92,6 +93,7 @@
 #include "runtime/globals.hpp"
 #include "runtime/java.hpp"
 #include "runtime/javaCalls.hpp"
+#include "runtime/os.hpp"
 #include "runtime/perfMemory.hpp"
 #include "runtime/serviceThread.hpp"
 #include "runtime/sharedRuntime.hpp"
@@ -3306,14 +3308,14 @@
     }
   }
   if (strstr(typeName, " const") == typeName + len - 6) {
-    char * s = strdup(typeName);
+    char * s = os::strdup_check_oom(typeName);
     s[len - 6] = '\0';
     // tty->print_cr("checking \"%s\" for \"%s\"", s, typeName);
     if (recursiveFindType(origtypes, s, true) == 1) {
-      free(s);
+      os::free(s);
       return 1;
     }
-    free(s);
+    os::free(s);
   }
   if (!isRecurse) {
     tty->print_cr("type \"%s\" not found", typeName);
diff -Nru openjdk.orig/hotspot/src/share/vm/services/management.cpp openjdk/hotspot/src/share/vm/services/management.cpp
--- openjdk.orig/hotspot/src/share/vm/services/management.cpp	2021-07-16 05:52:52.000000000 +0100
+++ openjdk/hotspot/src/share/vm/services/management.cpp	2021-07-27 18:05:29.417943217 +0100
@@ -1819,7 +1819,7 @@
   ResourceMark rm(THREAD); // thread->name() uses ResourceArea
 
   assert(thread->name() != NULL, "All threads should have a name");
-  _names_chars[_count] = strdup(thread->name());
+  _names_chars[_count] = os::strdup(thread->name());
   _times->long_at_put(_count, os::is_thread_cpu_time_supported() ?
                         os::thread_cpu_time(thread) : -1);
   _count++;
@@ -1837,7 +1837,7 @@
 
 ThreadTimesClosure::~ThreadTimesClosure() {
   for (int i = 0; i < _count; i++) {
-    free(_names_chars[i]);
+    os::free(_names_chars[i]);
   }
   FREE_C_HEAP_ARRAY(char *, _names_chars, mtInternal);
 }
diff -Nru openjdk.orig/hotspot/src/share/vm/shark/sharkBuilder.cpp openjdk/hotspot/src/share/vm/shark/sharkBuilder.cpp
--- openjdk.orig/hotspot/src/share/vm/shark/sharkBuilder.cpp	2021-07-16 05:52:52.000000000 +0100
+++ openjdk/hotspot/src/share/vm/shark/sharkBuilder.cpp	2021-07-27 18:05:29.417943217 +0100
@@ -413,7 +413,7 @@
   const char *name;
   if (value->hasName())
     // XXX this leaks, but it's only debug code
-    name = strdup(value->getName().str().c_str());
+    name = os::strdup(value->getName().str().c_str());
   else
     name = "unnamed_value";
 
