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