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