]>
Commit | Line | Data |
---|---|---|
9ac42ed8 | 1 | /* crypto/mem_dbg.c */ |
08807172 RL |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | |
9ac42ed8 | 4 | * |
08807172 RL |
5 | * This package is an SSL implementation written |
6 | * by Eric Young (eay@cryptsoft.com). | |
7 | * The implementation was written so as to conform with Netscapes SSL. | |
8 | * | |
9 | * This library is free for commercial and non-commercial use as long as | |
10 | * the following conditions are aheared to. The following conditions | |
11 | * apply to all code found in this distribution, be it the RC4, RSA, | |
12 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation | |
13 | * included with this distribution is covered by the same copyright terms | |
14 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). | |
15 | * | |
16 | * Copyright remains Eric Young's, and as such any Copyright notices in | |
17 | * the code are not to be removed. | |
18 | * If this package is used in a product, Eric Young should be given attribution | |
19 | * as the author of the parts of the library used. | |
20 | * This can be in the form of a textual message at program startup or | |
21 | * in documentation (online or textual) provided with the package. | |
22 | * | |
9ac42ed8 RL |
23 | * Redistribution and use in source and binary forms, with or without |
24 | * modification, are permitted provided that the following conditions | |
25 | * are met: | |
08807172 RL |
26 | * 1. Redistributions of source code must retain the copyright |
27 | * notice, this list of conditions and the following disclaimer. | |
9ac42ed8 | 28 | * 2. Redistributions in binary form must reproduce the above copyright |
08807172 RL |
29 | * notice, this list of conditions and the following disclaimer in the |
30 | * documentation and/or other materials provided with the distribution. | |
31 | * 3. All advertising materials mentioning features or use of this software | |
32 | * must display the following acknowledgement: | |
33 | * "This product includes cryptographic software written by | |
34 | * Eric Young (eay@cryptsoft.com)" | |
35 | * The word 'cryptographic' can be left out if the rouines from the library | |
36 | * being used are not cryptographic related :-). | |
37 | * 4. If you include any Windows specific code (or a derivative thereof) from | |
38 | * the apps directory (application code) you must include an acknowledgement: | |
39 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" | |
40 | * | |
41 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND | |
42 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
43 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
44 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
45 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
46 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
47 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
48 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
49 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
50 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
51 | * SUCH DAMAGE. | |
52 | * | |
53 | * The licence and distribution terms for any publically available version or | |
54 | * derivative of this code cannot be changed. i.e. this code cannot simply be | |
55 | * copied and put under another distribution licence | |
56 | * [including the GNU Public Licence.] | |
9ac42ed8 | 57 | */ |
48fc582f BM |
58 | /* ==================================================================== |
59 | * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. | |
60 | * | |
61 | * Redistribution and use in source and binary forms, with or without | |
62 | * modification, are permitted provided that the following conditions | |
63 | * are met: | |
64 | * | |
65 | * 1. Redistributions of source code must retain the above copyright | |
66 | * notice, this list of conditions and the following disclaimer. | |
67 | * | |
68 | * 2. Redistributions in binary form must reproduce the above copyright | |
69 | * notice, this list of conditions and the following disclaimer in | |
70 | * the documentation and/or other materials provided with the | |
71 | * distribution. | |
72 | * | |
73 | * 3. All advertising materials mentioning features or use of this | |
74 | * software must display the following acknowledgment: | |
75 | * "This product includes software developed by the OpenSSL Project | |
76 | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" | |
77 | * | |
78 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
79 | * endorse or promote products derived from this software without | |
80 | * prior written permission. For written permission, please contact | |
81 | * openssl-core@openssl.org. | |
82 | * | |
83 | * 5. Products derived from this software may not be called "OpenSSL" | |
84 | * nor may "OpenSSL" appear in their names without prior written | |
85 | * permission of the OpenSSL Project. | |
86 | * | |
87 | * 6. Redistributions of any form whatsoever must retain the following | |
88 | * acknowledgment: | |
89 | * "This product includes software developed by the OpenSSL Project | |
90 | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" | |
91 | * | |
92 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
93 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
94 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
95 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
96 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
97 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
98 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
99 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
100 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
101 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
102 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
103 | * OF THE POSSIBILITY OF SUCH DAMAGE. | |
104 | * ==================================================================== | |
105 | * | |
106 | * This product includes cryptographic software written by Eric Young | |
107 | * (eay@cryptsoft.com). This product includes software written by Tim | |
108 | * Hudson (tjh@cryptsoft.com). | |
109 | * | |
110 | */ | |
9ac42ed8 RL |
111 | |
112 | #include <stdio.h> | |
113 | #include <stdlib.h> | |
114 | #include <time.h> | |
25a66ee3 | 115 | #include "cryptlib.h" |
9ac42ed8 RL |
116 | #include <openssl/crypto.h> |
117 | #include <openssl/buffer.h> | |
118 | #include <openssl/bio.h> | |
119 | #include <openssl/lhash.h> | |
9ac42ed8 | 120 | |
0cd08cce BM |
121 | static int mh_mode=CRYPTO_MEM_CHECK_OFF; |
122 | /* The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE | |
123 | * when the application asks for it (usually after library initialisation | |
124 | * for which no book-keeping is desired). | |
125 | * | |
126 | * State CRYPTO_MEM_CHECK_ON exists only temporarily when the library | |
9ac42ed8 RL |
127 | * thinks that certain allocations should not be checked (e.g. the data |
128 | * structures used for memory checking). It is not suitable as an initial | |
129 | * state: the library will unexpectedly enable memory checking when it | |
130 | * executes one of those sections that want to disable checking | |
131 | * temporarily. | |
132 | * | |
133 | * State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes no sense whatsoever. | |
134 | */ | |
9ac42ed8 | 135 | |
0cd08cce | 136 | static unsigned long order = 0; /* number of memory requests */ |
934397ec BM |
137 | static LHASH *mh=NULL; /* hash-table of memory requests (address as key); |
138 | * access requires MALLOC2 lock */ | |
9ac42ed8 | 139 | |
9ac42ed8 RL |
140 | |
141 | typedef struct app_mem_info_st | |
0cd08cce BM |
142 | /* For application-defined information (static C-string `info') |
143 | * to be displayed in memory leak list. | |
144 | * Each thread has its own stack. For applications, there is | |
2b6313d0 BM |
145 | * CRYPTO_push_info("...") to push an entry, |
146 | * CRYPTO_pop_info() to pop an entry, | |
147 | * CRYPTO_remove_all_info() to pop all entries. | |
0cd08cce | 148 | */ |
9ac42ed8 | 149 | { |
48fc582f BM |
150 | unsigned long thread_id; |
151 | void *thread_idptr; | |
9ac42ed8 RL |
152 | const char *file; |
153 | int line; | |
154 | const char *info; | |
0cd08cce | 155 | struct app_mem_info_st *next; /* tail of thread's stack */ |
9ac42ed8 RL |
156 | int references; |
157 | } APP_INFO; | |
158 | ||
9dc61049 BM |
159 | static void app_info_free(APP_INFO *); |
160 | ||
0cd08cce BM |
161 | static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's |
162 | * that are at the top of their thread's stack | |
934397ec BM |
163 | * (with `thread' as key); |
164 | * access requires MALLOC2 lock */ | |
9ac42ed8 RL |
165 | |
166 | typedef struct mem_st | |
0cd08cce | 167 | /* memory-block description */ |
9ac42ed8 | 168 | { |
65962686 | 169 | void *addr; |
9ac42ed8 RL |
170 | int num; |
171 | const char *file; | |
172 | int line; | |
48fc582f BM |
173 | unsigned long thread_id; |
174 | void *thread_idptr; | |
9ac42ed8 RL |
175 | unsigned long order; |
176 | time_t time; | |
177 | APP_INFO *app_info; | |
178 | } MEM; | |
179 | ||
0cd08cce BM |
180 | static long options = /* extra information to be recorded */ |
181 | #if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL) | |
182 | V_CRYPTO_MDEBUG_TIME | | |
d8df48a9 | 183 | #endif |
0cd08cce BM |
184 | #if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL) |
185 | V_CRYPTO_MDEBUG_THREAD | | |
d8df48a9 | 186 | #endif |
0cd08cce | 187 | 0; |
d8df48a9 | 188 | |
9ac42ed8 | 189 | |
934397ec BM |
190 | static unsigned int num_disable = 0; /* num_disable > 0 |
191 | * iff | |
192 | * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE) | |
193 | */ | |
48fc582f BM |
194 | |
195 | /* The following two variables, disabling_thread_id and disabling_thread_idptr, | |
196 | * are valid iff num_disable > 0. CRYPTO_LOCK_MALLOC2 is locked exactly in | |
197 | * this case (by the thread named in disabling_thread_id / disabling_thread_idptr). | |
198 | */ | |
199 | static unsigned long disabling_thread_id = 0; | |
200 | static void *disabling_thread_idptr = NULL; | |
9ac42ed8 | 201 | |
9dc61049 BM |
202 | static void app_info_free(APP_INFO *inf) |
203 | { | |
204 | if (--(inf->references) <= 0) | |
205 | { | |
206 | if (inf->next != NULL) | |
207 | { | |
208 | app_info_free(inf->next); | |
209 | } | |
210 | OPENSSL_free(inf); | |
211 | } | |
212 | } | |
213 | ||
9ac42ed8 RL |
214 | int CRYPTO_mem_ctrl(int mode) |
215 | { | |
216 | int ret=mh_mode; | |
217 | ||
218 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); | |
219 | switch (mode) | |
220 | { | |
934397ec BM |
221 | /* for applications (not to be called while multiple threads |
222 | * use the library): */ | |
9ac42ed8 RL |
223 | case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */ |
224 | mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE; | |
934397ec | 225 | num_disable = 0; |
9ac42ed8 RL |
226 | break; |
227 | case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */ | |
228 | mh_mode = 0; | |
934397ec BM |
229 | num_disable = 0; /* should be true *before* MemCheck_stop is used, |
230 | or there'll be a lot of confusion */ | |
9ac42ed8 RL |
231 | break; |
232 | ||
233 | /* switch off temporarily (for library-internal use): */ | |
234 | case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */ | |
235 | if (mh_mode & CRYPTO_MEM_CHECK_ON) | |
236 | { | |
48fc582f BM |
237 | if (!num_disable |
238 | || (disabling_thread_id != CRYPTO_thread_id()) | |
239 | || (disabling_thread_idptr != CRYPTO_thread_idptr())) /* otherwise we already have the MALLOC2 lock */ | |
9ac42ed8 RL |
240 | { |
241 | /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while | |
242 | * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if | |
0cd08cce BM |
243 | * somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot release |
244 | * it because we block entry to this function). | |
9ac42ed8 RL |
245 | * Give them a chance, first, and then claim the locks in |
246 | * appropriate order (long-time lock first). | |
247 | */ | |
248 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); | |
249 | /* Note that after we have waited for CRYPTO_LOCK_MALLOC2 | |
250 | * and CRYPTO_LOCK_MALLOC, we'll still be in the right | |
251 | * "case" and "if" branch because MemCheck_start and | |
252 | * MemCheck_stop may never be used while there are multiple | |
253 | * OpenSSL threads. */ | |
254 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); | |
255 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); | |
934397ec | 256 | mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE; |
48fc582f BM |
257 | disabling_thread_id=CRYPTO_thread_id(); |
258 | disabling_thread_idptr=CRYPTO_thread_idptr(); | |
9ac42ed8 | 259 | } |
934397ec | 260 | num_disable++; |
9ac42ed8 RL |
261 | } |
262 | break; | |
263 | case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */ | |
264 | if (mh_mode & CRYPTO_MEM_CHECK_ON) | |
265 | { | |
934397ec | 266 | if (num_disable) /* always true, or something is going wrong */ |
9ac42ed8 | 267 | { |
934397ec BM |
268 | num_disable--; |
269 | if (num_disable == 0) | |
270 | { | |
271 | mh_mode|=CRYPTO_MEM_CHECK_ENABLE; | |
272 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); | |
273 | } | |
9ac42ed8 RL |
274 | } |
275 | } | |
276 | break; | |
277 | ||
278 | default: | |
279 | break; | |
280 | } | |
281 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); | |
282 | return(ret); | |
283 | } | |
284 | ||
0cd08cce | 285 | int CRYPTO_is_mem_check_on(void) |
9ac42ed8 RL |
286 | { |
287 | int ret = 0; | |
288 | ||
289 | if (mh_mode & CRYPTO_MEM_CHECK_ON) | |
290 | { | |
934397ec | 291 | CRYPTO_r_lock(CRYPTO_LOCK_MALLOC); |
9ac42ed8 RL |
292 | |
293 | ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE) | |
48fc582f BM |
294 | || (disabling_thread_id != CRYPTO_thread_id()) |
295 | || (disabling_thread_idptr != CRYPTO_thread_idptr()); | |
9ac42ed8 | 296 | |
934397ec | 297 | CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC); |
9ac42ed8 RL |
298 | } |
299 | return(ret); | |
300 | } | |
301 | ||
302 | ||
0cd08cce | 303 | void CRYPTO_dbg_set_options(long bits) |
9ac42ed8 RL |
304 | { |
305 | options = bits; | |
306 | } | |
307 | ||
667ac4ec | 308 | long CRYPTO_dbg_get_options(void) |
9ac42ed8 RL |
309 | { |
310 | return options; | |
311 | } | |
312 | ||
d0fa136c | 313 | /* static int mem_cmp(MEM *a, MEM *b) */ |
8d28d5f8 | 314 | static int mem_cmp(const void *a_void, const void *b_void) |
9ac42ed8 | 315 | { |
1875e6db AP |
316 | #ifdef _WIN64 |
317 | const char *a=(const char *)((const MEM *)a_void)->addr, | |
318 | *b=(const char *)((const MEM *)b_void)->addr; | |
319 | if (a==b) return 0; | |
320 | else if (a>b) return 1; | |
321 | else return -1; | |
322 | #else | |
0774f470 BL |
323 | return((const char *)((const MEM *)a_void)->addr |
324 | - (const char *)((const MEM *)b_void)->addr); | |
1875e6db | 325 | #endif |
9ac42ed8 RL |
326 | } |
327 | ||
d0fa136c | 328 | /* static unsigned long mem_hash(MEM *a) */ |
8d28d5f8 | 329 | static unsigned long mem_hash(const void *a_void) |
9ac42ed8 RL |
330 | { |
331 | unsigned long ret; | |
332 | ||
8d28d5f8 | 333 | ret=(unsigned long)((const MEM *)a_void)->addr; |
9ac42ed8 RL |
334 | |
335 | ret=ret*17851+(ret>>14)*7+(ret>>4)*251; | |
336 | return(ret); | |
337 | } | |
338 | ||
d0fa136c | 339 | /* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */ |
8d28d5f8 | 340 | static int app_info_cmp(const void *a_void, const void *b_void) |
9ac42ed8 | 341 | { |
48fc582f BM |
342 | return (((const APP_INFO *)a_void)->thread_id != ((const APP_INFO *)b_void)->thread_id) |
343 | || (((const APP_INFO *)a_void)->thread_idptr != ((const APP_INFO *)b_void)->thread_idptr); | |
9ac42ed8 RL |
344 | } |
345 | ||
d0fa136c | 346 | /* static unsigned long app_info_hash(APP_INFO *a) */ |
8d28d5f8 | 347 | static unsigned long app_info_hash(const void *a_void) |
9ac42ed8 | 348 | { |
48fc582f | 349 | unsigned long id1, id2; |
9ac42ed8 RL |
350 | unsigned long ret; |
351 | ||
48fc582f BM |
352 | id1=(unsigned long)((const APP_INFO *)a_void)->thread_id; |
353 | id2=(unsigned long)((const APP_INFO *)a_void)->thread_idptr; | |
354 | ret = id1 + id2; | |
9ac42ed8 RL |
355 | |
356 | ret=ret*17851+(ret>>14)*7+(ret>>4)*251; | |
357 | return(ret); | |
358 | } | |
359 | ||
fe8686ba | 360 | static APP_INFO *pop_info(void) |
9ac42ed8 RL |
361 | { |
362 | APP_INFO tmp; | |
363 | APP_INFO *ret = NULL; | |
364 | ||
365 | if (amih != NULL) | |
366 | { | |
48fc582f BM |
367 | tmp.thread_id=CRYPTO_thread_id(); |
368 | tmp.thread_idptr=CRYPTO_thread_idptr(); | |
9d1a01be | 369 | if ((ret=(APP_INFO *)lh_delete(amih,&tmp)) != NULL) |
9ac42ed8 RL |
370 | { |
371 | APP_INFO *next=ret->next; | |
372 | ||
373 | if (next != NULL) | |
374 | { | |
375 | next->references++; | |
376 | lh_insert(amih,(char *)next); | |
377 | } | |
3d6001f7 | 378 | #ifdef LEVITTE_DEBUG_MEM |
48fc582f | 379 | if (ret->thread_id != tmp.thread_id || ret->thread_idptr != tmp.thread_idptr) |
9ac42ed8 | 380 | { |
48fc582f BM |
381 | fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu/%p) than the current thread (%lu/%p)!!!!\n", |
382 | ret->thread_id, ret->thread_idptr, tmp.thread_id, tmp.thread_idptr); | |
9ac42ed8 RL |
383 | abort(); |
384 | } | |
385 | #endif | |
386 | if (--(ret->references) <= 0) | |
387 | { | |
388 | ret->next = NULL; | |
389 | if (next != NULL) | |
390 | next->references--; | |
26a3a48d | 391 | OPENSSL_free(ret); |
9ac42ed8 RL |
392 | } |
393 | } | |
394 | } | |
395 | return(ret); | |
396 | } | |
397 | ||
2b6313d0 | 398 | int CRYPTO_push_info_(const char *info, const char *file, int line) |
9ac42ed8 RL |
399 | { |
400 | APP_INFO *ami, *amim; | |
401 | int ret=0; | |
402 | ||
403 | if (is_MemCheck_on()) | |
404 | { | |
934397ec | 405 | MemCheck_off(); /* obtain MALLOC2 lock */ |
9ac42ed8 | 406 | |
26a3a48d | 407 | if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL) |
9ac42ed8 RL |
408 | { |
409 | ret=0; | |
410 | goto err; | |
411 | } | |
412 | if (amih == NULL) | |
413 | { | |
d0fa136c | 414 | if ((amih=lh_new(app_info_hash, app_info_cmp)) == NULL) |
9ac42ed8 | 415 | { |
26a3a48d | 416 | OPENSSL_free(ami); |
9ac42ed8 RL |
417 | ret=0; |
418 | goto err; | |
419 | } | |
420 | } | |
421 | ||
48fc582f BM |
422 | ami->thread_id=CRYPTO_thread_id(); |
423 | ami->thread_idptr=CRYPTO_thread_idptr(); | |
9ac42ed8 RL |
424 | ami->file=file; |
425 | ami->line=line; | |
426 | ami->info=info; | |
427 | ami->references=1; | |
428 | ami->next=NULL; | |
429 | ||
430 | if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL) | |
431 | { | |
3d6001f7 | 432 | #ifdef LEVITTE_DEBUG_MEM |
48fc582f | 433 | if (ami->thread_id != amim->thread_id || ami->thread_idptr != amim->thread_idptr) |
9ac42ed8 | 434 | { |
48fc582f BM |
435 | fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu/%p) than the current thread (%lu/%p)!!!!\n", |
436 | amim->thread_id, amim->thread_idptr, ami->thread_id, ami->thread_idptr); | |
9ac42ed8 RL |
437 | abort(); |
438 | } | |
439 | #endif | |
440 | ami->next=amim; | |
441 | } | |
442 | err: | |
934397ec | 443 | MemCheck_on(); /* release MALLOC2 lock */ |
9ac42ed8 RL |
444 | } |
445 | ||
446 | return(ret); | |
447 | } | |
448 | ||
2b6313d0 | 449 | int CRYPTO_pop_info(void) |
9ac42ed8 RL |
450 | { |
451 | int ret=0; | |
452 | ||
75acc288 | 453 | if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */ |
9ac42ed8 | 454 | { |
934397ec | 455 | MemCheck_off(); /* obtain MALLOC2 lock */ |
9ac42ed8 | 456 | |
2b6313d0 | 457 | ret=(pop_info() != NULL); |
9ac42ed8 | 458 | |
934397ec | 459 | MemCheck_on(); /* release MALLOC2 lock */ |
9ac42ed8 RL |
460 | } |
461 | return(ret); | |
462 | } | |
463 | ||
464 | int CRYPTO_remove_all_info(void) | |
465 | { | |
466 | int ret=0; | |
467 | ||
0cd08cce | 468 | if (is_MemCheck_on()) /* _must_ be true */ |
9ac42ed8 | 469 | { |
934397ec | 470 | MemCheck_off(); /* obtain MALLOC2 lock */ |
9ac42ed8 | 471 | |
2b6313d0 | 472 | while(pop_info() != NULL) |
9ac42ed8 RL |
473 | ret++; |
474 | ||
934397ec | 475 | MemCheck_on(); /* release MALLOC2 lock */ |
9ac42ed8 RL |
476 | } |
477 | return(ret); | |
478 | } | |
479 | ||
480 | ||
481 | static unsigned long break_order_num=0; | |
482 | void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line, | |
483 | int before_p) | |
484 | { | |
485 | MEM *m,*mm; | |
486 | APP_INFO tmp,*amim; | |
487 | ||
488 | switch(before_p & 127) | |
489 | { | |
490 | case 0: | |
491 | break; | |
492 | case 1: | |
493 | if (addr == NULL) | |
494 | break; | |
495 | ||
496 | if (is_MemCheck_on()) | |
497 | { | |
934397ec | 498 | MemCheck_off(); /* make sure we hold MALLOC2 lock */ |
26a3a48d | 499 | if ((m=(MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL) |
9ac42ed8 | 500 | { |
26a3a48d | 501 | OPENSSL_free(addr); |
934397ec BM |
502 | MemCheck_on(); /* release MALLOC2 lock |
503 | * if num_disabled drops to 0 */ | |
9ac42ed8 RL |
504 | return; |
505 | } | |
506 | if (mh == NULL) | |
507 | { | |
d0fa136c | 508 | if ((mh=lh_new(mem_hash, mem_cmp)) == NULL) |
9ac42ed8 | 509 | { |
26a3a48d RL |
510 | OPENSSL_free(addr); |
511 | OPENSSL_free(m); | |
9ac42ed8 RL |
512 | addr=NULL; |
513 | goto err; | |
514 | } | |
515 | } | |
516 | ||
517 | m->addr=addr; | |
518 | m->file=file; | |
519 | m->line=line; | |
520 | m->num=num; | |
521 | if (options & V_CRYPTO_MDEBUG_THREAD) | |
48fc582f BM |
522 | { |
523 | m->thread_id=CRYPTO_thread_id(); | |
524 | m->thread_idptr=CRYPTO_thread_idptr(); | |
525 | } | |
9ac42ed8 | 526 | else |
48fc582f BM |
527 | { |
528 | m->thread_id=0; | |
529 | m->thread_idptr=NULL; | |
530 | } | |
9ac42ed8 RL |
531 | |
532 | if (order == break_order_num) | |
533 | { | |
534 | /* BREAK HERE */ | |
535 | m->order=order; | |
536 | } | |
537 | m->order=order++; | |
3d6001f7 | 538 | #ifdef LEVITTE_DEBUG_MEM |
48fc582f | 539 | fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] %c 0x%p (%d)\n", |
9ac42ed8 RL |
540 | m->order, |
541 | (before_p & 128) ? '*' : '+', | |
542 | m->addr, m->num); | |
543 | #endif | |
544 | if (options & V_CRYPTO_MDEBUG_TIME) | |
545 | m->time=time(NULL); | |
546 | else | |
547 | m->time=0; | |
548 | ||
48fc582f BM |
549 | tmp.thread_id=CRYPTO_thread_id(); |
550 | tmp.thread_idptr=CRYPTO_thread_idptr(); | |
9ac42ed8 RL |
551 | m->app_info=NULL; |
552 | if (amih != NULL | |
553 | && (amim=(APP_INFO *)lh_retrieve(amih,(char *)&tmp)) != NULL) | |
554 | { | |
555 | m->app_info = amim; | |
556 | amim->references++; | |
557 | } | |
558 | ||
559 | if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL) | |
560 | { | |
561 | /* Not good, but don't sweat it */ | |
562 | if (mm->app_info != NULL) | |
563 | { | |
564 | mm->app_info->references--; | |
565 | } | |
26a3a48d | 566 | OPENSSL_free(mm); |
9ac42ed8 RL |
567 | } |
568 | err: | |
934397ec BM |
569 | MemCheck_on(); /* release MALLOC2 lock |
570 | * if num_disabled drops to 0 */ | |
9ac42ed8 RL |
571 | } |
572 | break; | |
573 | } | |
574 | return; | |
575 | } | |
576 | ||
577 | void CRYPTO_dbg_free(void *addr, int before_p) | |
578 | { | |
579 | MEM m,*mp; | |
580 | ||
581 | switch(before_p) | |
582 | { | |
583 | case 0: | |
584 | if (addr == NULL) | |
585 | break; | |
586 | ||
587 | if (is_MemCheck_on() && (mh != NULL)) | |
588 | { | |
934397ec | 589 | MemCheck_off(); /* make sure we hold MALLOC2 lock */ |
9ac42ed8 RL |
590 | |
591 | m.addr=addr; | |
592 | mp=(MEM *)lh_delete(mh,(char *)&m); | |
593 | if (mp != NULL) | |
594 | { | |
3d6001f7 | 595 | #ifdef LEVITTE_DEBUG_MEM |
48fc582f | 596 | fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] - 0x%p (%d)\n", |
9ac42ed8 RL |
597 | mp->order, mp->addr, mp->num); |
598 | #endif | |
599 | if (mp->app_info != NULL) | |
9dc61049 | 600 | app_info_free(mp->app_info); |
26a3a48d | 601 | OPENSSL_free(mp); |
9ac42ed8 RL |
602 | } |
603 | ||
934397ec BM |
604 | MemCheck_on(); /* release MALLOC2 lock |
605 | * if num_disabled drops to 0 */ | |
9ac42ed8 RL |
606 | } |
607 | break; | |
608 | case 1: | |
609 | break; | |
610 | } | |
611 | } | |
612 | ||
613 | void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num, | |
614 | const char *file, int line, int before_p) | |
615 | { | |
616 | MEM m,*mp; | |
617 | ||
3d6001f7 RL |
618 | #ifdef LEVITTE_DEBUG_MEM |
619 | fprintf(stderr, "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n", | |
9ac42ed8 RL |
620 | addr1, addr2, num, file, line, before_p); |
621 | #endif | |
622 | ||
623 | switch(before_p) | |
624 | { | |
625 | case 0: | |
626 | break; | |
627 | case 1: | |
628 | if (addr2 == NULL) | |
629 | break; | |
630 | ||
631 | if (addr1 == NULL) | |
632 | { | |
633 | CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p); | |
634 | break; | |
635 | } | |
636 | ||
637 | if (is_MemCheck_on()) | |
638 | { | |
934397ec | 639 | MemCheck_off(); /* make sure we hold MALLOC2 lock */ |
9ac42ed8 RL |
640 | |
641 | m.addr=addr1; | |
642 | mp=(MEM *)lh_delete(mh,(char *)&m); | |
643 | if (mp != NULL) | |
644 | { | |
3d6001f7 | 645 | #ifdef LEVITTE_DEBUG_MEM |
48fc582f | 646 | fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] * 0x%p (%d) -> 0x%p (%d)\n", |
9ac42ed8 RL |
647 | mp->order, |
648 | mp->addr, mp->num, | |
649 | addr2, num); | |
650 | #endif | |
651 | mp->addr=addr2; | |
652 | mp->num=num; | |
653 | lh_insert(mh,(char *)mp); | |
654 | } | |
655 | ||
934397ec BM |
656 | MemCheck_on(); /* release MALLOC2 lock |
657 | * if num_disabled drops to 0 */ | |
9ac42ed8 RL |
658 | } |
659 | break; | |
660 | } | |
661 | return; | |
662 | } | |
663 | ||
664 | ||
665 | typedef struct mem_leak_st | |
666 | { | |
667 | BIO *bio; | |
668 | int chunks; | |
669 | long bytes; | |
670 | } MEM_LEAK; | |
671 | ||
0774f470 | 672 | static void print_leak(const MEM *m, MEM_LEAK *l) |
9ac42ed8 RL |
673 | { |
674 | char buf[1024]; | |
675 | char *bufp = buf; | |
676 | APP_INFO *amip; | |
677 | int ami_cnt; | |
678 | struct tm *lcl = NULL; | |
679 | unsigned long ti; | |
48fc582f | 680 | void *tip; |
9ac42ed8 | 681 | |
d420ac2c RL |
682 | #define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf)) |
683 | ||
9ac42ed8 RL |
684 | if(m->addr == (char *)l->bio) |
685 | return; | |
686 | ||
687 | if (options & V_CRYPTO_MDEBUG_TIME) | |
688 | { | |
689 | lcl = localtime(&m->time); | |
690 | ||
d420ac2c | 691 | BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ", |
9ac42ed8 RL |
692 | lcl->tm_hour,lcl->tm_min,lcl->tm_sec); |
693 | bufp += strlen(bufp); | |
694 | } | |
695 | ||
d420ac2c | 696 | BIO_snprintf(bufp, BUF_REMAIN, "%5lu file=%s, line=%d, ", |
9ac42ed8 RL |
697 | m->order,m->file,m->line); |
698 | bufp += strlen(bufp); | |
699 | ||
700 | if (options & V_CRYPTO_MDEBUG_THREAD) | |
701 | { | |
48fc582f | 702 | BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu/%p, ", m->thread_id, m->thread_idptr); |
9ac42ed8 RL |
703 | bufp += strlen(bufp); |
704 | } | |
705 | ||
d420ac2c | 706 | BIO_snprintf(bufp, BUF_REMAIN, "number=%d, address=%08lX\n", |
9ac42ed8 RL |
707 | m->num,(unsigned long)m->addr); |
708 | bufp += strlen(bufp); | |
709 | ||
710 | BIO_puts(l->bio,buf); | |
711 | ||
712 | l->chunks++; | |
713 | l->bytes+=m->num; | |
714 | ||
715 | amip=m->app_info; | |
716 | ami_cnt=0; | |
a8eeb155 BM |
717 | if (!amip) |
718 | return; | |
48fc582f BM |
719 | ti=amip->thread_id; |
720 | tip=amip->thread_idptr; | |
a8eeb155 BM |
721 | |
722 | do | |
9ac42ed8 RL |
723 | { |
724 | int buf_len; | |
725 | int info_len; | |
726 | ||
727 | ami_cnt++; | |
728 | memset(buf,'>',ami_cnt); | |
d420ac2c | 729 | BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt, |
48fc582f BM |
730 | " thread=%lu/%p, file=%s, line=%d, info=\"", |
731 | amip->thread_id, amip->thread_idptr, amip->file, amip->line); | |
9ac42ed8 RL |
732 | buf_len=strlen(buf); |
733 | info_len=strlen(amip->info); | |
734 | if (128 - buf_len - 3 < info_len) | |
735 | { | |
736 | memcpy(buf + buf_len, amip->info, 128 - buf_len - 3); | |
737 | buf_len = 128 - 3; | |
738 | } | |
739 | else | |
740 | { | |
d420ac2c RL |
741 | BUF_strlcpy(buf + buf_len, amip->info, |
742 | sizeof buf - buf_len); | |
9ac42ed8 RL |
743 | buf_len = strlen(buf); |
744 | } | |
d420ac2c | 745 | BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n"); |
9ac42ed8 RL |
746 | |
747 | BIO_puts(l->bio,buf); | |
748 | ||
749 | amip = amip->next; | |
750 | } | |
48fc582f | 751 | while(amip && amip->thread_id == ti && amip->thread_idptr == tip); |
a8eeb155 | 752 | |
3d6001f7 | 753 | #ifdef LEVITTE_DEBUG_MEM |
9ac42ed8 RL |
754 | if (amip) |
755 | { | |
ed84dfab | 756 | fprintf(stderr, "Thread switch detected in backtrace!!!!\n"); |
9ac42ed8 RL |
757 | abort(); |
758 | } | |
759 | #endif | |
760 | } | |
761 | ||
0774f470 | 762 | static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM *, MEM_LEAK *) |
98d517c5 | 763 | |
9ac42ed8 RL |
764 | void CRYPTO_mem_leaks(BIO *b) |
765 | { | |
766 | MEM_LEAK ml; | |
9ac42ed8 | 767 | |
6e22639f BM |
768 | if (mh == NULL && amih == NULL) |
769 | return; | |
934397ec BM |
770 | |
771 | MemCheck_off(); /* obtain MALLOC2 lock */ | |
772 | ||
9ac42ed8 RL |
773 | ml.bio=b; |
774 | ml.bytes=0; | |
775 | ml.chunks=0; | |
6e22639f | 776 | if (mh != NULL) |
98d517c5 | 777 | lh_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak), |
385d8138 | 778 | (char *)&ml); |
9ac42ed8 RL |
779 | if (ml.chunks != 0) |
780 | { | |
54a656ef BL |
781 | BIO_printf(b,"%ld bytes leaked in %d chunks\n", |
782 | ml.bytes,ml.chunks); | |
9ac42ed8 | 783 | } |
6e22639f BM |
784 | else |
785 | { | |
786 | /* Make sure that, if we found no leaks, memory-leak debugging itself | |
787 | * does not introduce memory leaks (which might irritate | |
788 | * external debugging tools). | |
789 | * (When someone enables leak checking, but does not call | |
790 | * this function, we declare it to be their fault.) | |
791 | * | |
792 | * XXX This should be in CRYPTO_mem_leaks_cb, | |
793 | * and CRYPTO_mem_leaks should be implemented by | |
794 | * using CRYPTO_mem_leaks_cb. | |
795 | * (Also their should be a variant of lh_doall_arg | |
796 | * that takes a function pointer instead of a void *; | |
797 | * this would obviate the ugly and illegal | |
798 | * void_fn_to_char kludge in CRYPTO_mem_leaks_cb. | |
799 | * Otherwise the code police will come and get us.) | |
800 | */ | |
3ac82faa BM |
801 | int old_mh_mode; |
802 | ||
6e22639f | 803 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); |
3ac82faa BM |
804 | |
805 | /* avoid deadlock when lh_free() uses CRYPTO_dbg_free(), | |
806 | * which uses CRYPTO_is_mem_check_on */ | |
807 | old_mh_mode = mh_mode; | |
808 | mh_mode = CRYPTO_MEM_CHECK_OFF; | |
809 | ||
6e22639f BM |
810 | if (mh != NULL) |
811 | { | |
812 | lh_free(mh); | |
813 | mh = NULL; | |
814 | } | |
815 | if (amih != NULL) | |
816 | { | |
817 | if (lh_num_items(amih) == 0) | |
818 | { | |
819 | lh_free(amih); | |
820 | amih = NULL; | |
821 | } | |
822 | } | |
3ac82faa BM |
823 | |
824 | mh_mode = old_mh_mode; | |
6e22639f BM |
825 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); |
826 | } | |
934397ec | 827 | MemCheck_on(); /* release MALLOC2 lock */ |
9ac42ed8 RL |
828 | } |
829 | ||
cf1b7d96 | 830 | #ifndef OPENSSL_NO_FP_API |
9ac42ed8 RL |
831 | void CRYPTO_mem_leaks_fp(FILE *fp) |
832 | { | |
833 | BIO *b; | |
834 | ||
835 | if (mh == NULL) return; | |
5e2c4e23 GT |
836 | /* Need to turn off memory checking when allocated BIOs ... especially |
837 | * as we're creating them at a time when we're trying to check we've not | |
838 | * left anything un-free()'d!! */ | |
839 | MemCheck_off(); | |
3ae34e3a | 840 | b = BIO_new(BIO_s_file()); |
5e2c4e23 | 841 | MemCheck_on(); |
3ae34e3a | 842 | if(!b) return; |
9ac42ed8 RL |
843 | BIO_set_fp(b,fp,BIO_NOCLOSE); |
844 | CRYPTO_mem_leaks(b); | |
845 | BIO_free(b); | |
846 | } | |
847 | #endif | |
848 | ||
65962686 RL |
849 | |
850 | ||
851 | /* FIXME: We really don't allow much to the callback. For example, it has | |
852 | no chance of reaching the info stack for the item it processes. Should | |
853 | it really be this way? -- Richard Levitte */ | |
98d517c5 GT |
854 | /* NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside crypto.h |
855 | * If this code is restructured, remove the callback type if it is no longer | |
856 | * needed. -- Geoff Thorpe */ | |
0774f470 | 857 | static void cb_leak(const MEM *m, CRYPTO_MEM_LEAK_CB **cb) |
65962686 RL |
858 | { |
859 | (**cb)(m->order,m->file,m->line,m->num,m->addr); | |
860 | } | |
861 | ||
0774f470 | 862 | static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM *, CRYPTO_MEM_LEAK_CB **) |
98d517c5 | 863 | |
32654e79 | 864 | void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb) |
65962686 RL |
865 | { |
866 | if (mh == NULL) return; | |
867 | CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); | |
98d517c5 | 868 | lh_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), &cb); |
65962686 RL |
869 | CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); |
870 | } |