xref: /netbsd-src/external/lgpl3/gmp/dist/tests/memory.c (revision 72c7faa4dbb41dbb0238d6b4a109da0d4b236dd4)
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 **
tests_memory_find(void * ptr)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
tests_memory_valid(void * ptr)74 tests_memory_valid (void *ptr)
75 {
76   return (tests_memory_find (ptr) != NULL);
77 }
78 
79 void *
tests_allocate(size_t size)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 *
tests_reallocate(void * ptr,size_t old_size,size_t new_size)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 **
tests_free_find(void * ptr)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
tests_free_nosize(void * ptr)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
tests_free(void * ptr,size_t size)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
tests_memory_start(void)224 tests_memory_start (void)
225 {
226   mp_set_memory_functions (tests_allocate, tests_reallocate, tests_free);
227 }
228 
229 void
tests_memory_end(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