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