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