0
|
1 /* Distributed Checksum Clearinghouse heap debugging |
|
2 * |
|
3 * Copyright (c) 2008 by Rhyolite Software, LLC |
|
4 * |
|
5 * This agreement is not applicable to any entity which sells anti-spam |
|
6 * solutions to others or provides an anti-spam solution as part of a |
|
7 * security solution sold to other entities, or to a private network |
|
8 * which employs the DCC or uses data provided by operation of the DCC |
|
9 * but does not provide corresponding data to other users. |
|
10 * |
|
11 * Permission to use, copy, modify, and distribute this software without |
|
12 * changes for any purpose with or without fee is hereby granted, provided |
|
13 * that the above copyright notice and this permission notice appear in all |
|
14 * copies and any distributed versions or copies are either unchanged |
|
15 * or not called anything similar to "DCC" or "Distributed Checksum |
|
16 * Clearinghouse". |
|
17 * |
|
18 * Parties not eligible to receive a license under this agreement can |
|
19 * obtain a commercial license to use DCC by contacting Rhyolite Software |
|
20 * at sales@rhyolite.com. |
|
21 * |
|
22 * A commercial license would be for Distributed Checksum and Reputation |
|
23 * Clearinghouse software. That software includes additional features. This |
|
24 * free license for Distributed ChecksumClearinghouse Software does not in any |
|
25 * way grant permision to use Distributed Checksum and Reputation Clearinghouse |
|
26 * software |
|
27 * |
|
28 * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL |
|
29 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES |
|
30 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC |
|
31 * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES |
|
32 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, |
|
33 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, |
|
34 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS |
|
35 * SOFTWARE. |
|
36 * |
|
37 * Rhyolite Software DCC 1.3.103-1.20 $Revision$ |
|
38 */ |
|
39 |
|
40 #include "dcc_defs.h" |
|
41 #include "dcc_heap_debug.h" |
|
42 #include <stdio.h> |
|
43 |
|
44 void dcc_malloc_lock(void); |
|
45 void dcc_malloc_unlock(void); |
|
46 |
|
47 #ifdef UNIX |
|
48 #include <unistd.h> |
|
49 #else /* !UNIX */ |
|
50 #include "malloc.h" |
|
51 #endif /* !UNIX */ |
|
52 |
|
53 |
|
54 typedef u_long SENTINEL; |
|
55 #define HEAD_SENTINEL_VALUE 0xdeadbeaf |
|
56 #define TAIL_SENTINEL_VALUE 0xbeafdead |
|
57 |
|
58 typedef struct mdbg{ |
|
59 SENTINEL head; |
|
60 struct mdbg *fwd, *bak; |
|
61 SENTINEL *tail; |
|
62 } MDBG; |
|
63 |
|
64 u_int dcc_num_mdbg; /* global to suppress warnings */ |
|
65 MDBG *dcc_mdbg_chain; /* when not used */ |
|
66 MDBG *bad_mp; |
|
67 int bad_i; |
|
68 |
|
69 /* leave a few names outside to make some `ar`s happy */ |
|
70 #ifdef DCC_DEBUG_HEAP |
|
71 |
|
72 |
|
73 /* this needs to do as little as possible to avoid calling malloc() |
|
74 * global and no NRATTRIB to avoid confusion in dumps */ |
|
75 void |
|
76 dcc_heap_abort(const char *m) |
|
77 { |
|
78 #ifdef UNIX |
|
79 static int die; /* suppress no-retun warning */ |
|
80 |
|
81 write(STDERR_FILENO, m, strlen(m)); |
|
82 if (++die) |
|
83 abort(); |
|
84 #else |
|
85 bad_message_box("heap_debug", 1, m); |
|
86 #endif |
|
87 } |
|
88 |
|
89 |
|
90 |
|
91 char * |
|
92 dcc_strdup(const char *s) |
|
93 { |
|
94 char *p; |
|
95 |
|
96 p = dcc_malloc(strlen(s)+1); |
|
97 strcpy(p, s); |
|
98 return p; |
|
99 } |
|
100 |
|
101 |
|
102 |
|
103 void |
|
104 dcc_malloc_check(void) |
|
105 { |
|
106 MDBG *mp; |
|
107 u_int i; |
|
108 |
|
109 i = dcc_num_mdbg; |
|
110 if (!i) |
|
111 return; |
|
112 |
|
113 mp = dcc_mdbg_chain; |
|
114 for (;;) { |
|
115 if (mp->head != HEAD_SENTINEL_VALUE |
|
116 || *mp->tail != TAIL_SENTINEL_VALUE) |
|
117 dcc_heap_abort("trashed heap sentinel"); |
|
118 if (mp->bak->fwd != mp |
|
119 || mp->fwd->bak != mp) { |
|
120 bad_mp = mp; |
|
121 bad_i = i; |
|
122 dcc_heap_abort("malloc chain trashed"); |
|
123 } |
|
124 if (--i == 0) { |
|
125 if (mp->fwd != dcc_mdbg_chain) { |
|
126 bad_mp = mp; |
|
127 bad_i = i; |
|
128 dcc_heap_abort("wrong malloc chain too long"); |
|
129 } |
|
130 #ifndef UNIX |
|
131 i = _heapchk(); |
|
132 if (i != _HEAPOK && i != _HEAPEMPTY) |
|
133 dcc_heap_abort("heapchk() failed"); |
|
134 #endif |
|
135 return; |
|
136 } else if (mp->fwd == dcc_mdbg_chain) { |
|
137 bad_mp = mp; |
|
138 bad_i = i; |
|
139 dcc_heap_abort("wrong malloc chain too short"); |
|
140 } |
|
141 mp = mp->fwd; |
|
142 } |
|
143 } |
|
144 |
|
145 |
|
146 |
|
147 void * |
|
148 dcc_malloc(size_t len) |
|
149 { |
|
150 MDBG *mp; |
|
151 |
|
152 dcc_malloc_lock(); |
|
153 dcc_malloc_check(); |
|
154 |
|
155 if (!len) |
|
156 dcc_heap_abort("malloc(0)"); |
|
157 |
|
158 len += sizeof(MDBG) + sizeof(mp->tail); |
|
159 len += (sizeof(mp->tail) - len) & (sizeof(mp->tail)-1); /* align tail */ |
|
160 |
|
161 mp = malloc(len); |
|
162 if (!mp) |
|
163 return mp; |
|
164 |
|
165 if (!dcc_num_mdbg) { |
|
166 mp->fwd = mp->bak = mp; |
|
167 } else { |
|
168 mp->bak = dcc_mdbg_chain; |
|
169 mp->fwd = dcc_mdbg_chain->fwd; |
|
170 mp->bak->fwd = mp; |
|
171 mp->fwd->bak = mp; |
|
172 } |
|
173 dcc_mdbg_chain = mp; |
|
174 mp->head = HEAD_SENTINEL_VALUE; |
|
175 mp->tail = (SENTINEL *)((u_char *)mp+len-sizeof(mp->tail)); |
|
176 *mp->tail = TAIL_SENTINEL_VALUE; |
|
177 dcc_num_mdbg++; |
|
178 dcc_malloc_unlock(); |
|
179 |
|
180 return (mp+1); |
|
181 } |
|
182 |
|
183 |
|
184 |
|
185 void * |
|
186 dcc_calloc(size_t n, size_t s) |
|
187 { |
|
188 void *p; |
|
189 |
|
190 s *= n; |
|
191 if (s == 0) |
|
192 dcc_heap_abort("zero calloc() size"); |
|
193 p = dcc_malloc(s); |
|
194 if (!p) |
|
195 return p; |
|
196 memset(p, 0, s); |
|
197 return p; |
|
198 } |
|
199 |
|
200 |
|
201 |
|
202 void |
|
203 dcc_free(void *p) |
|
204 { |
|
205 int i; |
|
206 MDBG *mp; |
|
207 |
|
208 dcc_malloc_lock(); |
|
209 dcc_malloc_check(); |
|
210 i = dcc_num_mdbg; |
|
211 mp = dcc_mdbg_chain; |
|
212 for (;;) { |
|
213 if (!i) |
|
214 dcc_heap_abort("freeing non-free"); |
|
215 if (mp+1 == p) |
|
216 break; |
|
217 mp = mp->fwd; |
|
218 i--; |
|
219 } |
|
220 |
|
221 if (dcc_mdbg_chain == mp) |
|
222 dcc_mdbg_chain = mp->fwd; |
|
223 mp->bak->fwd = mp->fwd; |
|
224 mp->fwd->bak = mp->bak; |
|
225 dcc_num_mdbg--; |
|
226 memset(mp, 0xf1, (u_char *)mp->tail+sizeof(mp->tail)-(u_char *)mp); |
|
227 dcc_malloc_check(); |
|
228 dcc_malloc_unlock(); |
|
229 |
|
230 free(mp); |
|
231 } |
|
232 #endif /* DCC_DEBUG_HEAP */ |