src/share/vm/memory/guardedMemory.cpp

changeset 7032
fa62fb12cdca
child 9336
0fa4c2b668b9
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/memory/guardedMemory.cpp	Thu Aug 14 15:16:07 2014 +0200
     1.3 @@ -0,0 +1,161 @@
     1.4 +/*
     1.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.23 + * or visit www.oracle.com if you need additional information or have any
    1.24 + * questions.
    1.25 + *
    1.26 + */
    1.27 +#include "precompiled.hpp"
    1.28 +#include "memory/allocation.hpp"
    1.29 +#include "memory/allocation.inline.hpp"
    1.30 +#include "memory/guardedMemory.hpp"
    1.31 +#include "runtime/os.hpp"
    1.32 +
    1.33 +void* GuardedMemory::wrap_copy(const void* ptr, const size_t len, const void* tag) {
    1.34 +  size_t total_sz = GuardedMemory::get_total_size(len);
    1.35 +  void* outerp = os::malloc(total_sz, mtInternal);
    1.36 +  if (outerp != NULL) {
    1.37 +    GuardedMemory guarded(outerp, len, tag);
    1.38 +    void* innerp = guarded.get_user_ptr();
    1.39 +    memcpy(innerp, ptr, len);
    1.40 +    return innerp;
    1.41 +  }
    1.42 +  return NULL; // OOM
    1.43 +}
    1.44 +
    1.45 +bool GuardedMemory::free_copy(void* p) {
    1.46 +  if (p == NULL) {
    1.47 +    return true;
    1.48 +  }
    1.49 +  GuardedMemory guarded((u_char*)p);
    1.50 +  bool verify_ok = guarded.verify_guards();
    1.51 +
    1.52 +  /* always attempt to free, pass problem on to any nested memchecker */
    1.53 +  os::free(guarded.release_for_freeing());
    1.54 +
    1.55 +  return verify_ok;
    1.56 +}
    1.57 +
    1.58 +void GuardedMemory::print_on(outputStream* st) const {
    1.59 +  if (_base_addr == NULL) {
    1.60 +    st->print_cr("GuardedMemory(" PTR_FORMAT ") not associated to any memory", p2i(this));
    1.61 +    return;
    1.62 +  }
    1.63 +  st->print_cr("GuardedMemory(" PTR_FORMAT ") base_addr=" PTR_FORMAT
    1.64 +      " tag=" PTR_FORMAT " user_size=" SIZE_FORMAT " user_data=" PTR_FORMAT,
    1.65 +      p2i(this), p2i(_base_addr), p2i(get_tag()), get_user_size(), p2i(get_user_ptr()));
    1.66 +
    1.67 +  Guard* guard = get_head_guard();
    1.68 +  st->print_cr("  Header guard @" PTR_FORMAT " is %s", p2i(guard), (guard->verify() ? "OK" : "BROKEN"));
    1.69 +  guard = get_tail_guard();
    1.70 +  st->print_cr("  Trailer guard @" PTR_FORMAT " is %s", p2i(guard), (guard->verify() ? "OK" : "BROKEN"));
    1.71 +
    1.72 +  u_char udata = *get_user_ptr();
    1.73 +  switch (udata) {
    1.74 +  case uninitBlockPad:
    1.75 +    st->print_cr("  User data appears unused");
    1.76 +    break;
    1.77 +  case freeBlockPad:
    1.78 +    st->print_cr("  User data appears to have been freed");
    1.79 +    break;
    1.80 +  default:
    1.81 +    st->print_cr("  User data appears to be in use");
    1.82 +    break;
    1.83 +  }
    1.84 +}
    1.85 +
    1.86 +// test code...
    1.87 +
    1.88 +#ifndef PRODUCT
    1.89 +
    1.90 +static void guarded_memory_test_check(void* p, size_t sz, void* tag) {
    1.91 +  assert(p != NULL, "NULL pointer given to check");
    1.92 +  u_char* c = (u_char*) p;
    1.93 +  GuardedMemory guarded(c);
    1.94 +  assert(guarded.get_tag() == tag, "Tag is not the same as supplied");
    1.95 +  assert(guarded.get_user_ptr() == c, "User pointer is not the same as supplied");
    1.96 +  assert(guarded.get_user_size() == sz, "User size is not the same as supplied");
    1.97 +  assert(guarded.verify_guards(), "Guard broken");
    1.98 +}
    1.99 +
   1.100 +void GuardedMemory::test_guarded_memory() {
   1.101 +  // Test the basic characteristics...
   1.102 +  size_t total_sz = GuardedMemory::get_total_size(1);
   1.103 +  assert(total_sz > 1 && total_sz >= (sizeof(GuardHeader) + 1 + sizeof(Guard)), "Unexpected size");
   1.104 +  u_char* basep = (u_char*) os::malloc(total_sz, mtInternal);
   1.105 +
   1.106 +  GuardedMemory guarded(basep, 1, (void*)0xf000f000);
   1.107 +
   1.108 +  assert(*basep == badResourceValue, "Expected guard in the form of badResourceValue");
   1.109 +  u_char* userp = guarded.get_user_ptr();
   1.110 +  assert(*userp == uninitBlockPad, "Expected uninitialized data in the form of uninitBlockPad");
   1.111 +  guarded_memory_test_check(userp, 1, (void*)0xf000f000);
   1.112 +
   1.113 +  void* freep = guarded.release_for_freeing();
   1.114 +  assert((u_char*)freep == basep, "Expected the same pointer guard was ");
   1.115 +  assert(*userp == freeBlockPad, "Expected user data to be free block padded");
   1.116 +  assert(!guarded.verify_guards(), "Expected failed");
   1.117 +  os::free(freep);
   1.118 +
   1.119 +  // Test a number of odd sizes...
   1.120 +  size_t sz = 0;
   1.121 +  do {
   1.122 +    void* p = os::malloc(GuardedMemory::get_total_size(sz), mtInternal);
   1.123 +    void* up = guarded.wrap_with_guards(p, sz, (void*)1);
   1.124 +    memset(up, 0, sz);
   1.125 +    guarded_memory_test_check(up, sz, (void*)1);
   1.126 +    os::free(guarded.release_for_freeing());
   1.127 +    sz = (sz << 4) + 1;
   1.128 +  } while (sz < (256 * 1024));
   1.129 +
   1.130 +  // Test buffer overrun into head...
   1.131 +  basep = (u_char*) os::malloc(GuardedMemory::get_total_size(1), mtInternal);
   1.132 +  guarded.wrap_with_guards(basep, 1);
   1.133 +  *basep = 0;
   1.134 +  assert(!guarded.verify_guards(), "Expected failure");
   1.135 +  os::free(basep);
   1.136 +
   1.137 +  // Test buffer overrun into tail with a number of odd sizes...
   1.138 +  sz = 1;
   1.139 +  do {
   1.140 +    void* p = os::malloc(GuardedMemory::get_total_size(sz), mtInternal);
   1.141 +    void* up = guarded.wrap_with_guards(p, sz, (void*)1);
   1.142 +    memset(up, 0, sz + 1); // Buffer-overwrite (within guard)
   1.143 +    assert(!guarded.verify_guards(), "Guard was not broken as expected");
   1.144 +    os::free(guarded.release_for_freeing());
   1.145 +    sz = (sz << 4) + 1;
   1.146 +  } while (sz < (256 * 1024));
   1.147 +
   1.148 +  // Test wrap_copy/wrap_free...
   1.149 +  assert(GuardedMemory::free_copy(NULL), "Expected free NULL to be OK");
   1.150 +
   1.151 +  const char* str = "Check my bounds out";
   1.152 +  size_t str_sz = strlen(str) + 1;
   1.153 +  char* str_copy = (char*) GuardedMemory::wrap_copy(str, str_sz);
   1.154 +  guarded_memory_test_check(str_copy, str_sz, NULL);
   1.155 +  assert(strcmp(str, str_copy) == 0, "Not identical copy");
   1.156 +  assert(GuardedMemory::free_copy(str_copy), "Free copy failed to verify");
   1.157 +
   1.158 +  void* no_data = NULL;
   1.159 +  void* no_data_copy = GuardedMemory::wrap_copy(no_data, 0);
   1.160 +  assert(GuardedMemory::free_copy(no_data_copy), "Expected valid guards even for no data copy");
   1.161 +}
   1.162 +
   1.163 +#endif // !PRODUCT
   1.164 +

mercurial