blob: 4ab54b77034a7a10f883a819feff68068421bd92 [file] [log] [blame]
Austin Schuhbb1338c2024-06-15 19:31:16 -07001/* 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}