Print the debug thingies on stderr instead of stdout. If for nothing
[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                         * access requires MALLOC2 lock */
86
87
88 typedef 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
105 static void app_info_free(APP_INFO *);
106
107 static 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
112 typedef 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
125 static 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
135 static unsigned int num_disable = 0; /* num_disable > 0
136                                       *     iff
137                                       * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE)
138                                       */
139 static 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
145 static 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
157 int 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
225 int 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
242 void CRYPTO_dbg_set_options(long bits)
243         {
244         options = bits;
245         }
246
247 long CRYPTO_dbg_get_options(void)
248         {
249         return options;
250         }
251
252 /* static int mem_cmp(MEM *a, MEM *b) */
253 static 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) */
260 static 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) */
271 static 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) */
278 static 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
288 static 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
325 int 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
375 int 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
390 int 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
407 static unsigned long break_order_num=0;
408 void 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
496 void 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
532 void 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
584 typedef struct mem_leak_st
585         {
586         BIO *bio;
587         int chunks;
588         long bytes;
589         } MEM_LEAK;
590
591 static 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                 BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ",
610                         lcl->tm_hour,lcl->tm_min,lcl->tm_sec);
611                 bufp += strlen(bufp);
612                 }
613
614         BIO_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                 BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ", m->thread);
621                 bufp += strlen(bufp);
622                 }
623
624         BIO_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                 BIO_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                         BUF_strlcpy(buf + buf_len, amip->info,
659                                     sizeof buf - buf_len);
660                         buf_len = strlen(buf);
661                         }
662                 BIO_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
679 static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM *, MEM_LEAK *)
680
681 void 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
748 void 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 */
774 static 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
779 static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM *, CRYPTO_MEM_LEAK_CB **)
780
781 void 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         }