1 /* 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 #include "precompiled.hpp" 25 #include "memory/fencedMemory.hpp" 26 27 #include "memory/allocation.hpp" 28 #include "memory/allocation.inline.hpp" 29 #include "runtime/os.hpp" 30 31 void* FencedMemory::wrap_copy(const void* ptr, const size_t len, const void* tag) { 32 size_t total_sz = FencedMemory::get_total_size(len); 33 void* outerp = os::malloc(total_sz, mtInternal); 34 if (outerp != NULL) { 35 FencedMemory fenced(outerp, len, tag); 36 void* innerp = fenced.get_user_ptr(); 37 memcpy(innerp, ptr, len); 38 return innerp; 39 } 40 return NULL; // OOM 41 } 42 43 bool FencedMemory::free_copy(void* p) { 44 if (p == NULL) { 45 return true; 46 } 47 FencedMemory fenced((u_char*)p); 48 bool verify_ok = fenced.verify_fences(); 49 50 /* always attempt to free, pass problem on to any nested memchecker */ 51 os::free(fenced.release_for_freeing()); 52 53 return verify_ok; 54 } 55 56 void FencedMemory::print_on(outputStream* st) const { 57 if (_base_addr == NULL) { 58 st->print_cr("FencedMemory(" INTPTR_FORMAT ") not associated to any memory", this); 59 return; 60 } 61 st->print_cr("FencedMemory(" INTPTR_FORMAT ") base_addr=" PTR_FORMAT 62 " tag=" PTR_FORMAT " user_size=" SIZE_FORMAT " user_data=" PTR_FORMAT, 63 this, _base_addr, get_tag(), get_user_size(), get_user_ptr()); 64 65 Fence* fence = get_head_fence(); 66 st->print_cr(" Header fence @" PTR_FORMAT " is %s", fence, (fence->verify() ? "OK" : "BROKEN")); 67 fence = get_tail_fence(); 68 st->print_cr(" Trailer fence @" PTR_FORMAT " is %s", fence, (fence->verify() ? "OK" : "BROKEN")); 69 70 u_char udata = *get_user_ptr(); 71 switch (udata) { 72 case uninitBlockPad: 73 st->print_cr(" User data appears unused"); 74 break; 75 case freeBlockPad: 76 st->print_cr(" User data appears to have been freed"); 77 break; 78 default: 79 st->print_cr(" User data appears to be in use"); 80 } 81 } 82 83 // test code... 84 85 #ifndef PRODUCT 86 87 static void fenced_memory_test_check(void* p, size_t sz, void* tag) { 88 assert(p, "NULL pointer given to check"); 89 u_char* c = (u_char*) p; 90 FencedMemory fenced(c); 91 assert(fenced.get_tag() == tag, "Tag is not the same as supplied"); 92 assert(fenced.get_user_ptr() == c, "User pointer is not the same as supplied"); 93 assert(fenced.get_user_size() == sz, "User size is not the same as supplied"); 94 assert(fenced.verify_fences(), "Fence broken"); 95 } 96 97 void FencedMemory::test_fenced_memory() { 98 // Test the basic characteristics... 99 size_t total_sz = FencedMemory::get_total_size(1); 100 assert(total_sz > 1 && total_sz >= (sizeof(FenceHeader) + 1 + sizeof(Fence)), "Unexpected size"); 101 u_char* basep = (u_char*) os::malloc(total_sz, mtInternal); 102 103 FencedMemory fenced(basep, 1, (void*)0xf000f000); 104 105 assert(*basep == badResourceValue, "Expected fence in the form of badResourceValue"); 106 u_char* userp = fenced.get_user_ptr(); 107 assert(*userp == uninitBlockPad, "Expected uninitialized data in the form of uninitBlockPad"); 108 fenced_memory_test_check(userp, 1, (void*)0xf000f000); 109 110 void* freep = fenced.release_for_freeing(); 111 assert((u_char*)freep == basep, "Expected the same pointer fence was "); 112 assert(*userp == freeBlockPad, "Expected user data to be free block padded"); 113 assert(!fenced.verify_fences(), "Expected failed"); 114 os::free(freep); 115 116 // Test a number of odd sizes... 117 size_t sz = 0; 118 do { 119 void* p = os::malloc(FencedMemory::get_total_size(sz), mtInternal); 120 void* up = fenced.wrap_with_fences(p, sz, (void*)1); 121 memset(up, 0, sz); 122 fenced_memory_test_check(up, sz, (void*)1); 123 os::free(fenced.release_for_freeing()); 124 sz = (sz << 4) + 1; 125 } while (sz < (256 * 1024)); 126 127 // Test buffer overrun into head... 128 basep = (u_char*) os::malloc(FencedMemory::get_total_size(1), mtInternal); 129 fenced.wrap_with_fences(basep, 1); 130 *basep = 0; 131 assert(!fenced.verify_fences(), "Expected failure"); 132 os::free(basep); 133 134 // Test buffer overrun into tail with a number of odd sizes... 135 sz = 1; 136 do { 137 void* p = os::malloc(FencedMemory::get_total_size(sz), mtInternal); 138 void* up = fenced.wrap_with_fences(p, sz, (void*)1); 139 memset(up, 0, sz + 1); // Buffer-overwrite (within fence) 140 assert(!fenced.verify_fences(), "Fence was not broken as expected"); 141 os::free(fenced.release_for_freeing()); 142 sz = (sz << 4) + 1; 143 } while (sz < (256 * 1024)); 144 145 // Test wrap_copy/wrap_free... 146 assert(FencedMemory::free_copy(NULL), "Expected free NULL to be OK"); 147 148 const char* str = "Check my bounds out"; 149 size_t str_sz = strlen(str) + 1; 150 char* str_copy = (char*) FencedMemory::wrap_copy(str, str_sz); 151 fenced_memory_test_check(str_copy, str_sz, NULL); 152 assert(strcmp(str, str_copy) == 0, "Not identical copy"); 153 assert(FencedMemory::free_copy(str_copy), "Free copy failed to verify"); 154 155 void* no_data = NULL; 156 void* no_data_copy = FencedMemory::wrap_copy(no_data, 0); 157 assert(FencedMemory::free_copy(no_data_copy), "Expected valid fences even for no data copy"); 158 } 159 160 #endif // !PRODUCT 161