xref: /netbsd-src/external/lgpl3/gmp/dist/tests/memory.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
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.h"
24 #include "gmp-impl.h"
25 #include "tests.h"
26 
27 #if GMP_LIMB_BITS == 64
28 #define PATTERN1 CNST_LIMB(0xcafebabedeadbeef)
29 #define PATTERN2 CNST_LIMB(0xabacadabaedeedab)
30 #else
31 #define PATTERN1 CNST_LIMB(0xcafebabe)
32 #define PATTERN2 CNST_LIMB(0xdeadbeef)
33 #endif
34 
35 #if HAVE_INTPTR_T
36 #define PTRLIMB(p)  ((mp_limb_t) (intptr_t) p)
37 #else
38 #define PTRLIMB(p)  ((mp_limb_t) (size_t) p)
39 #endif
40 
41 /* Each block allocated is a separate malloc, for the benefit of a redzoning
42    malloc debugger during development or when bug hunting.
43 
44    Sizes passed when reallocating or freeing are checked (the default
45    routines don't care about these).
46 
47    Memory leaks are checked by requiring that all blocks have been freed
48    when tests_memory_end() is called.  Test programs must be sure to have
49    "clear"s for all temporary variables used.  */
50 
51 
52 struct header {
53   void           *ptr;
54   size_t         size;
55   struct header  *next;
56 };
57 
58 struct header  *tests_memory_list = NULL;
59 
60 /* Return a pointer to a pointer to the found block (so it can be updated
61    when unlinking). */
62 struct header **
63 tests_memory_find (void *ptr)
64 {
65   struct header  **hp;
66 
67   for (hp = &tests_memory_list; *hp != NULL; hp = &((*hp)->next))
68     if ((*hp)->ptr == ptr)
69       return hp;
70 
71   return NULL;
72 }
73 
74 int
75 tests_memory_valid (void *ptr)
76 {
77   return (tests_memory_find (ptr) != NULL);
78 }
79 
80 void *
81 tests_allocate (size_t size)
82 {
83   struct header  *h;
84   void *rptr, *ptr;
85   mp_limb_t PATTERN2_var;
86 
87   if (size == 0)
88     {
89       fprintf (stderr, "tests_allocate(): attempt to allocate 0 bytes\n");
90       abort ();
91     }
92 
93   h = (struct header *) __gmp_default_allocate (sizeof (*h));
94   h->next = tests_memory_list;
95   tests_memory_list = h;
96 
97   rptr = __gmp_default_allocate (size + 2 * sizeof (mp_limb_t));
98   ptr = (void *) ((gmp_intptr_t) rptr + sizeof (mp_limb_t));
99 
100   *((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)))
101     = PATTERN1 - PTRLIMB (ptr);
102   PATTERN2_var = PATTERN2 - PTRLIMB (ptr);
103   memcpy ((void *) ((gmp_intptr_t) ptr + size), &PATTERN2_var, sizeof (mp_limb_t));
104 
105   h->size = size;
106   h->ptr = ptr;
107   return h->ptr;
108 }
109 
110 void *
111 tests_reallocate (void *ptr, size_t old_size, size_t new_size)
112 {
113   struct header  **hp, *h;
114   void *rptr;
115   mp_limb_t PATTERN2_var;
116 
117   if (new_size == 0)
118     {
119       fprintf (stderr, "tests_reallocate(): attempt to reallocate %p to 0 bytes\n",
120 	       ptr);
121       abort ();
122     }
123 
124   hp = tests_memory_find (ptr);
125   if (hp == NULL)
126     {
127       fprintf (stderr, "tests_reallocate(): attempt to reallocate bad pointer %p\n",
128 	       ptr);
129       abort ();
130     }
131   h = *hp;
132 
133   if (h->size != old_size)
134     {
135       fprintf (stderr, "tests_reallocate(): bad old size %lu, should be %lu\n",
136 	       (unsigned long) old_size, (unsigned long) h->size);
137       abort ();
138     }
139 
140   if (*((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)))
141       != PATTERN1 - PTRLIMB (ptr))
142     {
143       fprintf (stderr, "in realloc: redzone clobbered before block\n");
144       abort ();
145     }
146   PATTERN2_var = PATTERN2 - PTRLIMB (ptr);
147   if (memcmp ((void *) ((gmp_intptr_t) ptr + h->size), &PATTERN2_var, sizeof (mp_limb_t)))
148     {
149       fprintf (stderr, "in realloc: redzone clobbered after block\n");
150       abort ();
151     }
152 
153   rptr = __gmp_default_reallocate ((void *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)),
154 				 old_size + 2 * sizeof (mp_limb_t),
155 				 new_size + 2 * sizeof (mp_limb_t));
156   ptr = (void *) ((gmp_intptr_t) rptr + sizeof (mp_limb_t));
157 
158   *((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)))
159     = PATTERN1 - PTRLIMB (ptr);
160   PATTERN2_var = PATTERN2 - PTRLIMB (ptr);
161   memcpy ((void *) ((gmp_intptr_t) ptr + new_size), &PATTERN2_var, sizeof (mp_limb_t));
162 
163   h->size = new_size;
164   h->ptr = ptr;
165   return h->ptr;
166 }
167 
168 struct header **
169 tests_free_find (void *ptr)
170 {
171   struct header  **hp = tests_memory_find (ptr);
172   if (hp == NULL)
173     {
174       fprintf (stderr, "tests_free(): attempt to free bad pointer %p\n",
175 	       ptr);
176       abort ();
177     }
178   return hp;
179 }
180 
181 void
182 tests_free_nosize (void *ptr)
183 {
184   struct header  **hp = tests_free_find (ptr);
185   struct header  *h = *hp;
186   mp_limb_t PATTERN2_var;
187 
188   *hp = h->next;  /* unlink */
189 
190   if (*((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)))
191       != PATTERN1 - PTRLIMB (ptr))
192     {
193       fprintf (stderr, "in free: redzone clobbered before block\n");
194       abort ();
195     }
196   PATTERN2_var = PATTERN2 - PTRLIMB (ptr);
197   if (memcmp ((void *) ((gmp_intptr_t) ptr + h->size), &PATTERN2_var, sizeof (mp_limb_t)))
198     {
199       fprintf (stderr, "in free: redzone clobbered after block\n");
200       abort ();
201     }
202 
203   __gmp_default_free ((void *) ((gmp_intptr_t) ptr - sizeof(mp_limb_t)),
204 		      h->size + 2 * sizeof (mp_limb_t));
205   __gmp_default_free (h, sizeof (*h));
206 }
207 
208 void
209 tests_free (void *ptr, size_t size)
210 {
211   struct header  **hp = tests_free_find (ptr);
212   struct header  *h = *hp;
213 
214   if (h->size != size)
215     {
216       fprintf (stderr, "tests_free(): bad size %lu, should be %lu\n",
217 	       (unsigned long) size, (unsigned long) h->size);
218       abort ();
219     }
220 
221   tests_free_nosize (ptr);
222 }
223 
224 void
225 tests_memory_start (void)
226 {
227   mp_set_memory_functions (tests_allocate, tests_reallocate, tests_free);
228 }
229 
230 void
231 tests_memory_end (void)
232 {
233   if (tests_memory_list != NULL)
234     {
235       struct header  *h;
236       unsigned  count;
237 
238       fprintf (stderr, "tests_memory_end(): not all memory freed\n");
239 
240       count = 0;
241       for (h = tests_memory_list; h != NULL; h = h->next)
242 	count++;
243 
244       fprintf (stderr, "    %u blocks remaining\n", count);
245       abort ();
246     }
247 }
248