1 /* Memory allocation used during tests. 2 3 Copyright 2001, 2002, 2007, 2013 Free Software Foundation, Inc. 4 5 This file is part of the GNU MP Library test suite. 6 7 The GNU MP Library test suite is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 3 of the License, 10 or (at your option) any later version. 11 12 The GNU MP Library test suite is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 15 Public License for more details. 16 17 You should have received a copy of the GNU General Public License along with 18 the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ 19 20 #include <stdio.h> 21 #include <stdlib.h> /* for abort */ 22 #include <string.h> /* for memcpy, memcmp */ 23 #include "gmp-impl.h" 24 #include "tests.h" 25 26 #if GMP_LIMB_BITS == 64 27 #define PATTERN1 CNST_LIMB(0xcafebabedeadbeef) 28 #define PATTERN2 CNST_LIMB(0xabacadabaedeedab) 29 #else 30 #define PATTERN1 CNST_LIMB(0xcafebabe) 31 #define PATTERN2 CNST_LIMB(0xdeadbeef) 32 #endif 33 34 #if HAVE_INTPTR_T 35 #define PTRLIMB(p) ((mp_limb_t) (intptr_t) p) 36 #else 37 #define PTRLIMB(p) ((mp_limb_t) (size_t) p) 38 #endif 39 40 /* Each block allocated is a separate malloc, for the benefit of a redzoning 41 malloc debugger during development or when bug hunting. 42 43 Sizes passed when reallocating or freeing are checked (the default 44 routines don't care about these). 45 46 Memory leaks are checked by requiring that all blocks have been freed 47 when tests_memory_end() is called. Test programs must be sure to have 48 "clear"s for all temporary variables used. */ 49 50 51 struct header { 52 void *ptr; 53 size_t size; 54 struct header *next; 55 }; 56 57 struct header *tests_memory_list = NULL; 58 59 /* Return a pointer to a pointer to the found block (so it can be updated 60 when unlinking). */ 61 struct header ** 62 tests_memory_find (void *ptr) 63 { 64 struct header **hp; 65 66 for (hp = &tests_memory_list; *hp != NULL; hp = &((*hp)->next)) 67 if ((*hp)->ptr == ptr) 68 return hp; 69 70 return NULL; 71 } 72 73 int 74 tests_memory_valid (void *ptr) 75 { 76 return (tests_memory_find (ptr) != NULL); 77 } 78 79 void * 80 tests_allocate (size_t size) 81 { 82 struct header *h; 83 void *rptr, *ptr; 84 mp_limb_t PATTERN2_var; 85 86 if (size == 0) 87 { 88 fprintf (stderr, "tests_allocate(): attempt to allocate 0 bytes\n"); 89 abort (); 90 } 91 92 h = (struct header *) __gmp_default_allocate (sizeof (*h)); 93 h->next = tests_memory_list; 94 tests_memory_list = h; 95 96 rptr = __gmp_default_allocate (size + 2 * sizeof (mp_limb_t)); 97 ptr = (void *) ((gmp_intptr_t) rptr + sizeof (mp_limb_t)); 98 99 *((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t))) 100 = PATTERN1 - PTRLIMB (ptr); 101 PATTERN2_var = PATTERN2 - PTRLIMB (ptr); 102 memcpy ((void *) ((gmp_intptr_t) ptr + size), &PATTERN2_var, sizeof (mp_limb_t)); 103 104 h->size = size; 105 h->ptr = ptr; 106 return h->ptr; 107 } 108 109 void * 110 tests_reallocate (void *ptr, size_t old_size, size_t new_size) 111 { 112 struct header **hp, *h; 113 void *rptr; 114 mp_limb_t PATTERN2_var; 115 116 if (new_size == 0) 117 { 118 fprintf (stderr, "tests_reallocate(): attempt to reallocate %p to 0 bytes\n", 119 ptr); 120 abort (); 121 } 122 123 hp = tests_memory_find (ptr); 124 if (hp == NULL) 125 { 126 fprintf (stderr, "tests_reallocate(): attempt to reallocate bad pointer %p\n", 127 ptr); 128 abort (); 129 } 130 h = *hp; 131 132 if (h->size != old_size) 133 { 134 fprintf (stderr, "tests_reallocate(): bad old size %lu, should be %lu\n", 135 (unsigned long) old_size, (unsigned long) h->size); 136 abort (); 137 } 138 139 if (*((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t))) 140 != PATTERN1 - PTRLIMB (ptr)) 141 { 142 fprintf (stderr, "in realloc: redzone clobbered before block\n"); 143 abort (); 144 } 145 PATTERN2_var = PATTERN2 - PTRLIMB (ptr); 146 if (memcmp ((void *) ((gmp_intptr_t) ptr + h->size), &PATTERN2_var, sizeof (mp_limb_t))) 147 { 148 fprintf (stderr, "in realloc: redzone clobbered after block\n"); 149 abort (); 150 } 151 152 rptr = __gmp_default_reallocate ((void *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)), 153 old_size + 2 * sizeof (mp_limb_t), 154 new_size + 2 * sizeof (mp_limb_t)); 155 ptr = (void *) ((gmp_intptr_t) rptr + sizeof (mp_limb_t)); 156 157 *((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t))) 158 = PATTERN1 - PTRLIMB (ptr); 159 PATTERN2_var = PATTERN2 - PTRLIMB (ptr); 160 memcpy ((void *) ((gmp_intptr_t) ptr + new_size), &PATTERN2_var, sizeof (mp_limb_t)); 161 162 h->size = new_size; 163 h->ptr = ptr; 164 return h->ptr; 165 } 166 167 struct header ** 168 tests_free_find (void *ptr) 169 { 170 struct header **hp = tests_memory_find (ptr); 171 if (hp == NULL) 172 { 173 fprintf (stderr, "tests_free(): attempt to free bad pointer %p\n", 174 ptr); 175 abort (); 176 } 177 return hp; 178 } 179 180 void 181 tests_free_nosize (void *ptr) 182 { 183 struct header **hp = tests_free_find (ptr); 184 struct header *h = *hp; 185 mp_limb_t PATTERN2_var; 186 187 *hp = h->next; /* unlink */ 188 189 if (*((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t))) 190 != PATTERN1 - PTRLIMB (ptr)) 191 { 192 fprintf (stderr, "in free: redzone clobbered before block\n"); 193 abort (); 194 } 195 PATTERN2_var = PATTERN2 - PTRLIMB (ptr); 196 if (memcmp ((void *) ((gmp_intptr_t) ptr + h->size), &PATTERN2_var, sizeof (mp_limb_t))) 197 { 198 fprintf (stderr, "in free: redzone clobbered after block\n"); 199 abort (); 200 } 201 202 __gmp_default_free ((void *) ((gmp_intptr_t) ptr - sizeof(mp_limb_t)), 203 h->size + 2 * sizeof (mp_limb_t)); 204 __gmp_default_free (h, sizeof (*h)); 205 } 206 207 void 208 tests_free (void *ptr, size_t size) 209 { 210 struct header **hp = tests_free_find (ptr); 211 struct header *h = *hp; 212 213 if (h->size != size) 214 { 215 fprintf (stderr, "tests_free(): bad size %lu, should be %lu\n", 216 (unsigned long) size, (unsigned long) h->size); 217 abort (); 218 } 219 220 tests_free_nosize (ptr); 221 } 222 223 void 224 tests_memory_start (void) 225 { 226 mp_set_memory_functions (tests_allocate, tests_reallocate, tests_free); 227 } 228 229 void 230 tests_memory_end (void) 231 { 232 if (tests_memory_list != NULL) 233 { 234 struct header *h; 235 unsigned count; 236 237 fprintf (stderr, "tests_memory_end(): not all memory freed\n"); 238 239 count = 0; 240 for (h = tests_memory_list; h != NULL; h = h->next) 241 count++; 242 243 fprintf (stderr, " %u blocks remaining\n", count); 244 abort (); 245 } 246 } 247