1/* Memory allocation used during tests. 2 3Copyright 2001, 2002, 2007, 2013 Free Software Foundation, Inc. 4 5This file is part of the GNU MP Library test suite. 6 7The GNU MP Library test suite is free software; you can redistribute it 8and/or modify it under the terms of the GNU General Public License as 9published by the Free Software Foundation; either version 3 of the License, 10or (at your option) any later version. 11 12The GNU MP Library test suite is distributed in the hope that it will be 13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 15Public License for more details. 16 17You should have received a copy of the GNU General Public License along with 18the 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 51struct header { 52 void *ptr; 53 size_t size; 54 struct header *next; 55}; 56 57struct 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). */ 61struct header ** 62tests_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 73int 74tests_memory_valid (void *ptr) 75{ 76 return (tests_memory_find (ptr) != NULL); 77} 78 79void * 80tests_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 109void * 110tests_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 167struct header ** 168tests_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 180void 181tests_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 207void 208tests_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 223void 224tests_memory_start (void) 225{ 226 mp_set_memory_functions (tests_allocate, tests_reallocate, tests_free); 227} 228 229void 230tests_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