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