]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/mem_dbg.c
Security fixes brought forward from 0.9.7.
[thirdparty/openssl.git] / crypto / mem_dbg.c
CommitLineData
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
RL
57 */
58
59#include <stdio.h>
60#include <stdlib.h>
61#include <time.h>
62#include <openssl/crypto.h>
63#include <openssl/buffer.h>
64#include <openssl/bio.h>
65#include <openssl/lhash.h>
66#include "cryptlib.h"
67
0cd08cce
BM
68static int mh_mode=CRYPTO_MEM_CHECK_OFF;
69/* The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE
70 * when the application asks for it (usually after library initialisation
71 * for which no book-keeping is desired).
72 *
73 * State CRYPTO_MEM_CHECK_ON exists only temporarily when the library
9ac42ed8
RL
74 * thinks that certain allocations should not be checked (e.g. the data
75 * structures used for memory checking). It is not suitable as an initial
76 * state: the library will unexpectedly enable memory checking when it
77 * executes one of those sections that want to disable checking
78 * temporarily.
79 *
80 * State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes no sense whatsoever.
81 */
9ac42ed8 82
0cd08cce 83static unsigned long order = 0; /* number of memory requests */
934397ec
BM
84static LHASH *mh=NULL; /* hash-table of memory requests (address as key);
85 * access requires MALLOC2 lock */
9ac42ed8 86
9ac42ed8
RL
87
88typedef struct app_mem_info_st
0cd08cce
BM
89/* For application-defined information (static C-string `info')
90 * to be displayed in memory leak list.
91 * Each thread has its own stack. For applications, there is
2b6313d0
BM
92 * CRYPTO_push_info("...") to push an entry,
93 * CRYPTO_pop_info() to pop an entry,
94 * CRYPTO_remove_all_info() to pop all entries.
0cd08cce 95 */
9ac42ed8
RL
96 {
97 unsigned long thread;
98 const char *file;
99 int line;
100 const char *info;
0cd08cce 101 struct app_mem_info_st *next; /* tail of thread's stack */
9ac42ed8
RL
102 int references;
103 } APP_INFO;
104
0cd08cce
BM
105static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's
106 * that are at the top of their thread's stack
934397ec
BM
107 * (with `thread' as key);
108 * access requires MALLOC2 lock */
9ac42ed8
RL
109
110typedef struct mem_st
0cd08cce 111/* memory-block description */
9ac42ed8 112 {
65962686 113 void *addr;
9ac42ed8
RL
114 int num;
115 const char *file;
116 int line;
117 unsigned long thread;
118 unsigned long order;
119 time_t time;
120 APP_INFO *app_info;
121 } MEM;
122
0cd08cce
BM
123static long options = /* extra information to be recorded */
124#if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL)
125 V_CRYPTO_MDEBUG_TIME |
d8df48a9 126#endif
0cd08cce
BM
127#if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL)
128 V_CRYPTO_MDEBUG_THREAD |
d8df48a9 129#endif
0cd08cce 130 0;
d8df48a9 131
9ac42ed8 132
934397ec
BM
133static unsigned int num_disable = 0; /* num_disable > 0
134 * iff
135 * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE)
136 */
137static unsigned long disabling_thread = 0; /* Valid iff num_disable > 0.
138 * CRYPTO_LOCK_MALLOC2 is locked
139 * exactly in this case (by the
140 * thread named in disabling_thread).
141 */
9ac42ed8
RL
142
143int CRYPTO_mem_ctrl(int mode)
144 {
145 int ret=mh_mode;
146
147 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
148 switch (mode)
149 {
934397ec
BM
150 /* for applications (not to be called while multiple threads
151 * use the library): */
9ac42ed8
RL
152 case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */
153 mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
934397ec 154 num_disable = 0;
9ac42ed8
RL
155 break;
156 case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
157 mh_mode = 0;
934397ec
BM
158 num_disable = 0; /* should be true *before* MemCheck_stop is used,
159 or there'll be a lot of confusion */
9ac42ed8
RL
160 break;
161
162 /* switch off temporarily (for library-internal use): */
163 case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
164 if (mh_mode & CRYPTO_MEM_CHECK_ON)
165 {
934397ec 166 if (!num_disable || (disabling_thread != CRYPTO_thread_id())) /* otherwise we already have the MALLOC2 lock */
9ac42ed8
RL
167 {
168 /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while
169 * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if
0cd08cce
BM
170 * somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot release
171 * it because we block entry to this function).
9ac42ed8
RL
172 * Give them a chance, first, and then claim the locks in
173 * appropriate order (long-time lock first).
174 */
175 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
176 /* Note that after we have waited for CRYPTO_LOCK_MALLOC2
177 * and CRYPTO_LOCK_MALLOC, we'll still be in the right
178 * "case" and "if" branch because MemCheck_start and
179 * MemCheck_stop may never be used while there are multiple
180 * OpenSSL threads. */
181 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
182 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
934397ec 183 mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE;
9ac42ed8
RL
184 disabling_thread=CRYPTO_thread_id();
185 }
934397ec 186 num_disable++;
9ac42ed8
RL
187 }
188 break;
189 case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */
190 if (mh_mode & CRYPTO_MEM_CHECK_ON)
191 {
934397ec 192 if (num_disable) /* always true, or something is going wrong */
9ac42ed8 193 {
934397ec
BM
194 num_disable--;
195 if (num_disable == 0)
196 {
197 mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
198 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
199 }
9ac42ed8
RL
200 }
201 }
202 break;
203
204 default:
205 break;
206 }
207 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
208 return(ret);
209 }
210
0cd08cce 211int CRYPTO_is_mem_check_on(void)
9ac42ed8
RL
212 {
213 int ret = 0;
214
215 if (mh_mode & CRYPTO_MEM_CHECK_ON)
216 {
934397ec 217 CRYPTO_r_lock(CRYPTO_LOCK_MALLOC);
9ac42ed8
RL
218
219 ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
934397ec 220 || (disabling_thread != CRYPTO_thread_id());
9ac42ed8 221
934397ec 222 CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC);
9ac42ed8
RL
223 }
224 return(ret);
225 }
226
227
0cd08cce 228void CRYPTO_dbg_set_options(long bits)
9ac42ed8
RL
229 {
230 options = bits;
231 }
232
667ac4ec 233long CRYPTO_dbg_get_options(void)
9ac42ed8
RL
234 {
235 return options;
236 }
237
d0fa136c 238/* static int mem_cmp(MEM *a, MEM *b) */
8d28d5f8 239static int mem_cmp(const void *a_void, const void *b_void)
9ac42ed8 240 {
0774f470
BL
241 return((const char *)((const MEM *)a_void)->addr
242 - (const char *)((const MEM *)b_void)->addr);
9ac42ed8
RL
243 }
244
d0fa136c 245/* static unsigned long mem_hash(MEM *a) */
8d28d5f8 246static unsigned long mem_hash(const void *a_void)
9ac42ed8
RL
247 {
248 unsigned long ret;
249
8d28d5f8 250 ret=(unsigned long)((const MEM *)a_void)->addr;
9ac42ed8
RL
251
252 ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
253 return(ret);
254 }
255
d0fa136c 256/* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */
8d28d5f8 257static int app_info_cmp(const void *a_void, const void *b_void)
9ac42ed8 258 {
8d28d5f8
RL
259 return(((const APP_INFO *)a_void)->thread
260 != ((const APP_INFO *)b_void)->thread);
9ac42ed8
RL
261 }
262
d0fa136c 263/* static unsigned long app_info_hash(APP_INFO *a) */
8d28d5f8 264static unsigned long app_info_hash(const void *a_void)
9ac42ed8
RL
265 {
266 unsigned long ret;
267
8d28d5f8 268 ret=(unsigned long)((const APP_INFO *)a_void)->thread;
9ac42ed8
RL
269
270 ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
271 return(ret);
272 }
273
fe8686ba 274static APP_INFO *pop_info(void)
9ac42ed8
RL
275 {
276 APP_INFO tmp;
277 APP_INFO *ret = NULL;
278
279 if (amih != NULL)
280 {
281 tmp.thread=CRYPTO_thread_id();
9d1a01be 282 if ((ret=(APP_INFO *)lh_delete(amih,&tmp)) != NULL)
9ac42ed8
RL
283 {
284 APP_INFO *next=ret->next;
285
286 if (next != NULL)
287 {
288 next->references++;
289 lh_insert(amih,(char *)next);
290 }
3d6001f7 291#ifdef LEVITTE_DEBUG_MEM
9ac42ed8
RL
292 if (ret->thread != tmp.thread)
293 {
2b6313d0 294 fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
9ac42ed8
RL
295 ret->thread, tmp.thread);
296 abort();
297 }
298#endif
299 if (--(ret->references) <= 0)
300 {
301 ret->next = NULL;
302 if (next != NULL)
303 next->references--;
26a3a48d 304 OPENSSL_free(ret);
9ac42ed8
RL
305 }
306 }
307 }
308 return(ret);
309 }
310
2b6313d0 311int CRYPTO_push_info_(const char *info, const char *file, int line)
9ac42ed8
RL
312 {
313 APP_INFO *ami, *amim;
314 int ret=0;
315
316 if (is_MemCheck_on())
317 {
934397ec 318 MemCheck_off(); /* obtain MALLOC2 lock */
9ac42ed8 319
26a3a48d 320 if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL)
9ac42ed8
RL
321 {
322 ret=0;
323 goto err;
324 }
325 if (amih == NULL)
326 {
d0fa136c 327 if ((amih=lh_new(app_info_hash, app_info_cmp)) == NULL)
9ac42ed8 328 {
26a3a48d 329 OPENSSL_free(ami);
9ac42ed8
RL
330 ret=0;
331 goto err;
332 }
333 }
334
335 ami->thread=CRYPTO_thread_id();
336 ami->file=file;
337 ami->line=line;
338 ami->info=info;
339 ami->references=1;
340 ami->next=NULL;
341
342 if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL)
343 {
3d6001f7 344#ifdef LEVITTE_DEBUG_MEM
9ac42ed8
RL
345 if (ami->thread != amim->thread)
346 {
2b6313d0 347 fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
9ac42ed8
RL
348 amim->thread, ami->thread);
349 abort();
350 }
351#endif
352 ami->next=amim;
353 }
354 err:
934397ec 355 MemCheck_on(); /* release MALLOC2 lock */
9ac42ed8
RL
356 }
357
358 return(ret);
359 }
360
2b6313d0 361int CRYPTO_pop_info(void)
9ac42ed8
RL
362 {
363 int ret=0;
364
75acc288 365 if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */
9ac42ed8 366 {
934397ec 367 MemCheck_off(); /* obtain MALLOC2 lock */
9ac42ed8 368
2b6313d0 369 ret=(pop_info() != NULL);
9ac42ed8 370
934397ec 371 MemCheck_on(); /* release MALLOC2 lock */
9ac42ed8
RL
372 }
373 return(ret);
374 }
375
376int CRYPTO_remove_all_info(void)
377 {
378 int ret=0;
379
0cd08cce 380 if (is_MemCheck_on()) /* _must_ be true */
9ac42ed8 381 {
934397ec 382 MemCheck_off(); /* obtain MALLOC2 lock */
9ac42ed8 383
2b6313d0 384 while(pop_info() != NULL)
9ac42ed8
RL
385 ret++;
386
934397ec 387 MemCheck_on(); /* release MALLOC2 lock */
9ac42ed8
RL
388 }
389 return(ret);
390 }
391
392
393static unsigned long break_order_num=0;
394void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
395 int before_p)
396 {
397 MEM *m,*mm;
398 APP_INFO tmp,*amim;
399
400 switch(before_p & 127)
401 {
402 case 0:
403 break;
404 case 1:
405 if (addr == NULL)
406 break;
407
408 if (is_MemCheck_on())
409 {
934397ec 410 MemCheck_off(); /* make sure we hold MALLOC2 lock */
26a3a48d 411 if ((m=(MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL)
9ac42ed8 412 {
26a3a48d 413 OPENSSL_free(addr);
934397ec
BM
414 MemCheck_on(); /* release MALLOC2 lock
415 * if num_disabled drops to 0 */
9ac42ed8
RL
416 return;
417 }
418 if (mh == NULL)
419 {
d0fa136c 420 if ((mh=lh_new(mem_hash, mem_cmp)) == NULL)
9ac42ed8 421 {
26a3a48d
RL
422 OPENSSL_free(addr);
423 OPENSSL_free(m);
9ac42ed8
RL
424 addr=NULL;
425 goto err;
426 }
427 }
428
429 m->addr=addr;
430 m->file=file;
431 m->line=line;
432 m->num=num;
433 if (options & V_CRYPTO_MDEBUG_THREAD)
434 m->thread=CRYPTO_thread_id();
435 else
436 m->thread=0;
437
438 if (order == break_order_num)
439 {
440 /* BREAK HERE */
441 m->order=order;
442 }
443 m->order=order++;
3d6001f7
RL
444#ifdef LEVITTE_DEBUG_MEM
445 fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] %c 0x%p (%d)\n",
9ac42ed8
RL
446 m->order,
447 (before_p & 128) ? '*' : '+',
448 m->addr, m->num);
449#endif
450 if (options & V_CRYPTO_MDEBUG_TIME)
451 m->time=time(NULL);
452 else
453 m->time=0;
454
455 tmp.thread=CRYPTO_thread_id();
456 m->app_info=NULL;
457 if (amih != NULL
458 && (amim=(APP_INFO *)lh_retrieve(amih,(char *)&tmp)) != NULL)
459 {
460 m->app_info = amim;
461 amim->references++;
462 }
463
464 if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL)
465 {
466 /* Not good, but don't sweat it */
467 if (mm->app_info != NULL)
468 {
469 mm->app_info->references--;
470 }
26a3a48d 471 OPENSSL_free(mm);
9ac42ed8
RL
472 }
473 err:
934397ec
BM
474 MemCheck_on(); /* release MALLOC2 lock
475 * if num_disabled drops to 0 */
9ac42ed8
RL
476 }
477 break;
478 }
479 return;
480 }
481
482void CRYPTO_dbg_free(void *addr, int before_p)
483 {
484 MEM m,*mp;
485
486 switch(before_p)
487 {
488 case 0:
489 if (addr == NULL)
490 break;
491
492 if (is_MemCheck_on() && (mh != NULL))
493 {
934397ec 494 MemCheck_off(); /* make sure we hold MALLOC2 lock */
9ac42ed8
RL
495
496 m.addr=addr;
497 mp=(MEM *)lh_delete(mh,(char *)&m);
498 if (mp != NULL)
499 {
3d6001f7
RL
500#ifdef LEVITTE_DEBUG_MEM
501 fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] - 0x%p (%d)\n",
9ac42ed8
RL
502 mp->order, mp->addr, mp->num);
503#endif
504 if (mp->app_info != NULL)
505 {
506 mp->app_info->references--;
507 }
26a3a48d 508 OPENSSL_free(mp);
9ac42ed8
RL
509 }
510
934397ec
BM
511 MemCheck_on(); /* release MALLOC2 lock
512 * if num_disabled drops to 0 */
9ac42ed8
RL
513 }
514 break;
515 case 1:
516 break;
517 }
518 }
519
520void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
521 const char *file, int line, int before_p)
522 {
523 MEM m,*mp;
524
3d6001f7
RL
525#ifdef LEVITTE_DEBUG_MEM
526 fprintf(stderr, "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n",
9ac42ed8
RL
527 addr1, addr2, num, file, line, before_p);
528#endif
529
530 switch(before_p)
531 {
532 case 0:
533 break;
534 case 1:
535 if (addr2 == NULL)
536 break;
537
538 if (addr1 == NULL)
539 {
540 CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p);
541 break;
542 }
543
544 if (is_MemCheck_on())
545 {
934397ec 546 MemCheck_off(); /* make sure we hold MALLOC2 lock */
9ac42ed8
RL
547
548 m.addr=addr1;
549 mp=(MEM *)lh_delete(mh,(char *)&m);
550 if (mp != NULL)
551 {
3d6001f7
RL
552#ifdef LEVITTE_DEBUG_MEM
553 fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] * 0x%p (%d) -> 0x%p (%d)\n",
9ac42ed8
RL
554 mp->order,
555 mp->addr, mp->num,
556 addr2, num);
557#endif
558 mp->addr=addr2;
559 mp->num=num;
560 lh_insert(mh,(char *)mp);
561 }
562
934397ec
BM
563 MemCheck_on(); /* release MALLOC2 lock
564 * if num_disabled drops to 0 */
9ac42ed8
RL
565 }
566 break;
567 }
568 return;
569 }
570
571
572typedef struct mem_leak_st
573 {
574 BIO *bio;
575 int chunks;
576 long bytes;
577 } MEM_LEAK;
578
0774f470 579static void print_leak(const MEM *m, MEM_LEAK *l)
9ac42ed8
RL
580 {
581 char buf[1024];
582 char *bufp = buf;
583 APP_INFO *amip;
584 int ami_cnt;
585 struct tm *lcl = NULL;
586 unsigned long ti;
587
588 if(m->addr == (char *)l->bio)
589 return;
590
591 if (options & V_CRYPTO_MDEBUG_TIME)
592 {
593 lcl = localtime(&m->time);
594
595 sprintf(bufp, "[%02d:%02d:%02d] ",
596 lcl->tm_hour,lcl->tm_min,lcl->tm_sec);
597 bufp += strlen(bufp);
598 }
599
600 sprintf(bufp, "%5lu file=%s, line=%d, ",
601 m->order,m->file,m->line);
602 bufp += strlen(bufp);
603
604 if (options & V_CRYPTO_MDEBUG_THREAD)
605 {
606 sprintf(bufp, "thread=%lu, ", m->thread);
607 bufp += strlen(bufp);
608 }
609
610 sprintf(bufp, "number=%d, address=%08lX\n",
611 m->num,(unsigned long)m->addr);
612 bufp += strlen(bufp);
613
614 BIO_puts(l->bio,buf);
615
616 l->chunks++;
617 l->bytes+=m->num;
618
619 amip=m->app_info;
620 ami_cnt=0;
a8eeb155
BM
621 if (!amip)
622 return;
623 ti=amip->thread;
624
625 do
9ac42ed8
RL
626 {
627 int buf_len;
628 int info_len;
629
630 ami_cnt++;
631 memset(buf,'>',ami_cnt);
632 sprintf(buf + ami_cnt,
75acc288 633 " thread=%lu, file=%s, line=%d, info=\"",
9ac42ed8
RL
634 amip->thread, amip->file, amip->line);
635 buf_len=strlen(buf);
636 info_len=strlen(amip->info);
637 if (128 - buf_len - 3 < info_len)
638 {
639 memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
640 buf_len = 128 - 3;
641 }
642 else
643 {
644 strcpy(buf + buf_len, amip->info);
645 buf_len = strlen(buf);
646 }
647 sprintf(buf + buf_len, "\"\n");
648
649 BIO_puts(l->bio,buf);
650
651 amip = amip->next;
652 }
a8eeb155
BM
653 while(amip && amip->thread == ti);
654
3d6001f7 655#ifdef LEVITTE_DEBUG_MEM
9ac42ed8
RL
656 if (amip)
657 {
ed84dfab 658 fprintf(stderr, "Thread switch detected in backtrace!!!!\n");
9ac42ed8
RL
659 abort();
660 }
661#endif
662 }
663
0774f470 664static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM *, MEM_LEAK *)
98d517c5 665
9ac42ed8
RL
666void CRYPTO_mem_leaks(BIO *b)
667 {
668 MEM_LEAK ml;
9ac42ed8 669
6e22639f
BM
670 if (mh == NULL && amih == NULL)
671 return;
934397ec
BM
672
673 MemCheck_off(); /* obtain MALLOC2 lock */
674
9ac42ed8
RL
675 ml.bio=b;
676 ml.bytes=0;
677 ml.chunks=0;
6e22639f 678 if (mh != NULL)
98d517c5 679 lh_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak),
385d8138 680 (char *)&ml);
9ac42ed8
RL
681 if (ml.chunks != 0)
682 {
54a656ef
BL
683 BIO_printf(b,"%ld bytes leaked in %d chunks\n",
684 ml.bytes,ml.chunks);
9ac42ed8 685 }
6e22639f
BM
686 else
687 {
688 /* Make sure that, if we found no leaks, memory-leak debugging itself
689 * does not introduce memory leaks (which might irritate
690 * external debugging tools).
691 * (When someone enables leak checking, but does not call
692 * this function, we declare it to be their fault.)
693 *
694 * XXX This should be in CRYPTO_mem_leaks_cb,
695 * and CRYPTO_mem_leaks should be implemented by
696 * using CRYPTO_mem_leaks_cb.
697 * (Also their should be a variant of lh_doall_arg
698 * that takes a function pointer instead of a void *;
699 * this would obviate the ugly and illegal
700 * void_fn_to_char kludge in CRYPTO_mem_leaks_cb.
701 * Otherwise the code police will come and get us.)
702 */
3ac82faa
BM
703 int old_mh_mode;
704
6e22639f 705 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
3ac82faa
BM
706
707 /* avoid deadlock when lh_free() uses CRYPTO_dbg_free(),
708 * which uses CRYPTO_is_mem_check_on */
709 old_mh_mode = mh_mode;
710 mh_mode = CRYPTO_MEM_CHECK_OFF;
711
6e22639f
BM
712 if (mh != NULL)
713 {
714 lh_free(mh);
715 mh = NULL;
716 }
717 if (amih != NULL)
718 {
719 if (lh_num_items(amih) == 0)
720 {
721 lh_free(amih);
722 amih = NULL;
723 }
724 }
3ac82faa
BM
725
726 mh_mode = old_mh_mode;
6e22639f
BM
727 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
728 }
934397ec 729 MemCheck_on(); /* release MALLOC2 lock */
9ac42ed8
RL
730 }
731
cf1b7d96 732#ifndef OPENSSL_NO_FP_API
9ac42ed8
RL
733void CRYPTO_mem_leaks_fp(FILE *fp)
734 {
735 BIO *b;
736
737 if (mh == NULL) return;
5e2c4e23
GT
738 /* Need to turn off memory checking when allocated BIOs ... especially
739 * as we're creating them at a time when we're trying to check we've not
740 * left anything un-free()'d!! */
741 MemCheck_off();
3ae34e3a 742 b = BIO_new(BIO_s_file());
5e2c4e23 743 MemCheck_on();
3ae34e3a 744 if(!b) return;
9ac42ed8
RL
745 BIO_set_fp(b,fp,BIO_NOCLOSE);
746 CRYPTO_mem_leaks(b);
747 BIO_free(b);
748 }
749#endif
750
65962686
RL
751
752
753/* FIXME: We really don't allow much to the callback. For example, it has
754 no chance of reaching the info stack for the item it processes. Should
755 it really be this way? -- Richard Levitte */
98d517c5
GT
756/* NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside crypto.h
757 * If this code is restructured, remove the callback type if it is no longer
758 * needed. -- Geoff Thorpe */
0774f470 759static void cb_leak(const MEM *m, CRYPTO_MEM_LEAK_CB **cb)
65962686
RL
760 {
761 (**cb)(m->order,m->file,m->line,m->num,m->addr);
762 }
763
0774f470 764static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM *, CRYPTO_MEM_LEAK_CB **)
98d517c5 765
32654e79 766void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
65962686
RL
767 {
768 if (mh == NULL) return;
769 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
98d517c5 770 lh_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), &cb);
65962686
RL
771 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
772 }