In bn_mul_recursive(), make sure the comba routines are only called
[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 static int mem_cmp(void *a_void, void *b_void)
224         {
225         return((char *)((MEM *)a_void)->addr - (char *)((MEM *)b_void)->addr);
226         }
227
228 /* static unsigned long mem_hash(MEM *a) */
229 static unsigned long mem_hash(void *a_void)
230         {
231         unsigned long ret;
232
233         ret=(unsigned long)((MEM *)a_void)->addr;
234
235         ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
236         return(ret);
237         }
238
239 /* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */
240 static int app_info_cmp(void *a_void, void *b_void)
241         {
242         return(((APP_INFO *)a_void)->thread != ((APP_INFO *)b_void)->thread);
243         }
244
245 /* static unsigned long app_info_hash(APP_INFO *a) */
246 static unsigned long app_info_hash(void *a_void)
247         {
248         unsigned long ret;
249
250         ret=(unsigned long)((APP_INFO *)a_void)->thread;
251
252         ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
253         return(ret);
254         }
255
256 static APP_INFO *pop_info(void)
257         {
258         APP_INFO tmp;
259         APP_INFO *ret = NULL;
260
261         if (amih != NULL)
262                 {
263                 tmp.thread=CRYPTO_thread_id();
264                 if ((ret=(APP_INFO *)lh_delete(amih,&tmp)) != NULL)
265                         {
266                         APP_INFO *next=ret->next;
267
268                         if (next != NULL)
269                                 {
270                                 next->references++;
271                                 lh_insert(amih,(char *)next);
272                                 }
273 #ifdef LEVITTE_DEBUG_MEM
274                         if (ret->thread != tmp.thread)
275                                 {
276                                 fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
277                                         ret->thread, tmp.thread);
278                                 abort();
279                                 }
280 #endif
281                         if (--(ret->references) <= 0)
282                                 {
283                                 ret->next = NULL;
284                                 if (next != NULL)
285                                         next->references--;
286                                 OPENSSL_free(ret);
287                                 }
288                         }
289                 }
290         return(ret);
291         }
292
293 int CRYPTO_push_info_(const char *info, const char *file, int line)
294         {
295         APP_INFO *ami, *amim;
296         int ret=0;
297
298         if (is_MemCheck_on())
299                 {
300                 MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */
301
302                 if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL)
303                         {
304                         ret=0;
305                         goto err;
306                         }
307                 if (amih == NULL)
308                         {
309                         if ((amih=lh_new(app_info_hash, app_info_cmp)) == NULL)
310                                 {
311                                 OPENSSL_free(ami);
312                                 ret=0;
313                                 goto err;
314                                 }
315                         }
316
317                 ami->thread=CRYPTO_thread_id();
318                 ami->file=file;
319                 ami->line=line;
320                 ami->info=info;
321                 ami->references=1;
322                 ami->next=NULL;
323
324                 if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL)
325                         {
326 #ifdef LEVITTE_DEBUG_MEM
327                         if (ami->thread != amim->thread)
328                                 {
329                                 fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
330                                         amim->thread, ami->thread);
331                                 abort();
332                                 }
333 #endif
334                         ami->next=amim;
335                         }
336  err:
337                 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
338                 }
339
340         return(ret);
341         }
342
343 int CRYPTO_pop_info(void)
344         {
345         int ret=0;
346
347         if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */
348                 {
349                 MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */
350
351                 ret=(pop_info() != NULL);
352
353                 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
354                 }
355         return(ret);
356         }
357
358 int CRYPTO_remove_all_info(void)
359         {
360         int ret=0;
361
362         if (is_MemCheck_on()) /* _must_ be true */
363                 {
364                 MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */
365
366                 while(pop_info() != NULL)
367                         ret++;
368
369                 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
370                 }
371         return(ret);
372         }
373
374
375 static unsigned long break_order_num=0;
376 void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
377         int before_p)
378         {
379         MEM *m,*mm;
380         APP_INFO tmp,*amim;
381
382         switch(before_p & 127)
383                 {
384         case 0:
385                 break;
386         case 1:
387                 if (addr == NULL)
388                         break;
389
390                 if (is_MemCheck_on())
391                         {
392                         MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */
393                         if ((m=(MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL)
394                                 {
395                                 OPENSSL_free(addr);
396                                 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
397                                 return;
398                                 }
399                         if (mh == NULL)
400                                 {
401                                 if ((mh=lh_new(mem_hash, mem_cmp)) == NULL)
402                                         {
403                                         OPENSSL_free(addr);
404                                         OPENSSL_free(m);
405                                         addr=NULL;
406                                         goto err;
407                                         }
408                                 }
409
410                         m->addr=addr;
411                         m->file=file;
412                         m->line=line;
413                         m->num=num;
414                         if (options & V_CRYPTO_MDEBUG_THREAD)
415                                 m->thread=CRYPTO_thread_id();
416                         else
417                                 m->thread=0;
418
419                         if (order == break_order_num)
420                                 {
421                                 /* BREAK HERE */
422                                 m->order=order;
423                                 }
424                         m->order=order++;
425 #ifdef LEVITTE_DEBUG_MEM
426                         fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] %c 0x%p (%d)\n",
427                                 m->order,
428                                 (before_p & 128) ? '*' : '+',
429                                 m->addr, m->num);
430 #endif
431                         if (options & V_CRYPTO_MDEBUG_TIME)
432                                 m->time=time(NULL);
433                         else
434                                 m->time=0;
435
436                         tmp.thread=CRYPTO_thread_id();
437                         m->app_info=NULL;
438                         if (amih != NULL
439                                 && (amim=(APP_INFO *)lh_retrieve(amih,(char *)&tmp)) != NULL)
440                                 {
441                                 m->app_info = amim;
442                                 amim->references++;
443                                 }
444
445                         if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL)
446                                 {
447                                 /* Not good, but don't sweat it */
448                                 if (mm->app_info != NULL)
449                                         {
450                                         mm->app_info->references--;
451                                         }
452                                 OPENSSL_free(mm);
453                                 }
454                 err:
455                         MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
456                         }
457                 break;
458                 }
459         return;
460         }
461
462 void CRYPTO_dbg_free(void *addr, int before_p)
463         {
464         MEM m,*mp;
465
466         switch(before_p)
467                 {
468         case 0:
469                 if (addr == NULL)
470                         break;
471
472                 if (is_MemCheck_on() && (mh != NULL))
473                         {
474                         MemCheck_off();
475
476                         m.addr=addr;
477                         mp=(MEM *)lh_delete(mh,(char *)&m);
478                         if (mp != NULL)
479                                 {
480 #ifdef LEVITTE_DEBUG_MEM
481                         fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] - 0x%p (%d)\n",
482                                 mp->order, mp->addr, mp->num);
483 #endif
484                                 if (mp->app_info != NULL)
485                                         {
486                                         mp->app_info->references--;
487                                         }
488                                 OPENSSL_free(mp);
489                                 }
490
491                         MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
492                         }
493                 break;
494         case 1:
495                 break;
496                 }
497         }
498
499 void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
500         const char *file, int line, int before_p)
501         {
502         MEM m,*mp;
503
504 #ifdef LEVITTE_DEBUG_MEM
505         fprintf(stderr, "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n",
506                 addr1, addr2, num, file, line, before_p);
507 #endif
508
509         switch(before_p)
510                 {
511         case 0:
512                 break;
513         case 1:
514                 if (addr2 == NULL)
515                         break;
516
517                 if (addr1 == NULL)
518                         {
519                         CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p);
520                         break;
521                         }
522
523                 if (is_MemCheck_on())
524                         {
525                         MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */
526
527                         m.addr=addr1;
528                         mp=(MEM *)lh_delete(mh,(char *)&m);
529                         if (mp != NULL)
530                                 {
531 #ifdef LEVITTE_DEBUG_MEM
532                                 fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] * 0x%p (%d) -> 0x%p (%d)\n",
533                                         mp->order,
534                                         mp->addr, mp->num,
535                                         addr2, num);
536 #endif
537                                 mp->addr=addr2;
538                                 mp->num=num;
539                                 lh_insert(mh,(char *)mp);
540                                 }
541
542                         MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
543                         }
544                 break;
545                 }
546         return;
547         }
548
549
550 typedef struct mem_leak_st
551         {
552         BIO *bio;
553         int chunks;
554         long bytes;
555         } MEM_LEAK;
556
557 static void print_leak(MEM *m, MEM_LEAK *l)
558         {
559         char buf[1024];
560         char *bufp = buf;
561         APP_INFO *amip;
562         int ami_cnt;
563         struct tm *lcl = NULL;
564         unsigned long ti;
565
566         if(m->addr == (char *)l->bio)
567             return;
568
569         if (options & V_CRYPTO_MDEBUG_TIME)
570                 {
571                 lcl = localtime(&m->time);
572         
573                 sprintf(bufp, "[%02d:%02d:%02d] ",
574                         lcl->tm_hour,lcl->tm_min,lcl->tm_sec);
575                 bufp += strlen(bufp);
576                 }
577
578         sprintf(bufp, "%5lu file=%s, line=%d, ",
579                 m->order,m->file,m->line);
580         bufp += strlen(bufp);
581
582         if (options & V_CRYPTO_MDEBUG_THREAD)
583                 {
584                 sprintf(bufp, "thread=%lu, ", m->thread);
585                 bufp += strlen(bufp);
586                 }
587
588         sprintf(bufp, "number=%d, address=%08lX\n",
589                 m->num,(unsigned long)m->addr);
590         bufp += strlen(bufp);
591
592         BIO_puts(l->bio,buf);
593         
594         l->chunks++;
595         l->bytes+=m->num;
596
597         amip=m->app_info;
598         ami_cnt=0;
599         if (!amip)
600                 return;
601         ti=amip->thread;
602         
603         do
604                 {
605                 int buf_len;
606                 int info_len;
607
608                 ami_cnt++;
609                 memset(buf,'>',ami_cnt);
610                 sprintf(buf + ami_cnt,
611                         " thread=%lu, file=%s, line=%d, info=\"",
612                         amip->thread, amip->file, amip->line);
613                 buf_len=strlen(buf);
614                 info_len=strlen(amip->info);
615                 if (128 - buf_len - 3 < info_len)
616                         {
617                         memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
618                         buf_len = 128 - 3;
619                         }
620                 else
621                         {
622                         strcpy(buf + buf_len, amip->info);
623                         buf_len = strlen(buf);
624                         }
625                 sprintf(buf + buf_len, "\"\n");
626                 
627                 BIO_puts(l->bio,buf);
628
629                 amip = amip->next;
630                 }
631         while(amip && amip->thread == ti);
632                 
633 #ifdef LEVITTE_DEBUG_MEM
634         if (amip)
635                 {
636                 fprintf(stderr, "Thread switch detected in backtrace!!!!\n");
637                 abort();
638                 }
639 #endif
640         }
641
642 void CRYPTO_mem_leaks(BIO *b)
643         {
644         MEM_LEAK ml;
645         char buf[80];
646
647         if (mh == NULL && amih == NULL)
648                 return;
649         ml.bio=b;
650         ml.bytes=0;
651         ml.chunks=0;
652         MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */
653         if (mh != NULL)
654                 lh_doall_arg(mh, (LHASH_DOALL_ARG_FN_TYPE)print_leak,
655                                 (char *)&ml);
656         if (ml.chunks != 0)
657                 {
658                 sprintf(buf,"%ld bytes leaked in %d chunks\n",
659                         ml.bytes,ml.chunks);
660                 BIO_puts(b,buf);
661                 }
662         else
663                 {
664                 /* Make sure that, if we found no leaks, memory-leak debugging itself
665                  * does not introduce memory leaks (which might irritate
666                  * external debugging tools).
667                  * (When someone enables leak checking, but does not call
668                  * this function, we declare it to be their fault.)
669                  *
670                  * XXX    This should be in CRYPTO_mem_leaks_cb,
671                  * and CRYPTO_mem_leaks should be implemented by
672                  * using CRYPTO_mem_leaks_cb.
673                  * (Also their should be a variant of lh_doall_arg
674                  * that takes a function pointer instead of a void *;
675                  * this would obviate the ugly and illegal
676                  * void_fn_to_char kludge in CRYPTO_mem_leaks_cb.
677                  * Otherwise the code police will come and get us.)
678                  */
679                 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
680                 if (mh != NULL)
681                         {
682                         lh_free(mh);
683                         mh = NULL;
684                         }
685                 if (amih != NULL)
686                         {
687                         if (lh_num_items(amih) == 0) 
688                                 {
689                                 lh_free(amih);
690                                 amih = NULL;
691                                 }
692                         }
693                 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
694                 }
695         MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
696
697 #if 0
698         lh_stats_bio(mh,b);
699         lh_node_stats_bio(mh,b);
700         lh_node_usage_stats_bio(mh,b);
701 #endif
702         }
703
704 #ifndef NO_FP_API
705 void CRYPTO_mem_leaks_fp(FILE *fp)
706         {
707         BIO *b;
708
709         if (mh == NULL) return;
710         if ((b=BIO_new(BIO_s_file())) == NULL)
711                 return;
712         BIO_set_fp(b,fp,BIO_NOCLOSE);
713         CRYPTO_mem_leaks(b);
714         BIO_free(b);
715         }
716 #endif
717
718
719
720 /* FIXME: We really don't allow much to the callback.  For example, it has
721    no chance of reaching the info stack for the item it processes.  Should
722    it really be this way?  -- Richard Levitte */
723 static void cb_leak(MEM *m,
724                     void (**cb)(unsigned long, const char *, int, int, void *))
725         {
726         (**cb)(m->order,m->file,m->line,m->num,m->addr);
727         }
728
729 void CRYPTO_mem_leaks_cb(void (*cb)(unsigned long, const char *, int, int, void *))
730         {
731         if (mh == NULL) return;
732         CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
733         lh_doall_arg(mh, (LHASH_DOALL_ARG_FN_TYPE)cb_leak,(void *)&cb);
734         CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
735         }