LHASH revamp. make depend.
[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  * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
60  *
61  * Redistribution and use in source and binary forms, with or without
62  * modification, are permitted provided that the following conditions
63  * are met:
64  *
65  * 1. Redistributions of source code must retain the above copyright
66  *    notice, this list of conditions and the following disclaimer. 
67  *
68  * 2. Redistributions in binary form must reproduce the above copyright
69  *    notice, this list of conditions and the following disclaimer in
70  *    the documentation and/or other materials provided with the
71  *    distribution.
72  *
73  * 3. All advertising materials mentioning features or use of this
74  *    software must display the following acknowledgment:
75  *    "This product includes software developed by the OpenSSL Project
76  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77  *
78  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79  *    endorse or promote products derived from this software without
80  *    prior written permission. For written permission, please contact
81  *    openssl-core@openssl.org.
82  *
83  * 5. Products derived from this software may not be called "OpenSSL"
84  *    nor may "OpenSSL" appear in their names without prior written
85  *    permission of the OpenSSL Project.
86  *
87  * 6. Redistributions of any form whatsoever must retain the following
88  *    acknowledgment:
89  *    "This product includes software developed by the OpenSSL Project
90  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91  *
92  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
96  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103  * OF THE POSSIBILITY OF SUCH DAMAGE.
104  * ====================================================================
105  *
106  * This product includes cryptographic software written by Eric Young
107  * (eay@cryptsoft.com).  This product includes software written by Tim
108  * Hudson (tjh@cryptsoft.com).
109  *
110  */
111
112 #include <stdio.h>
113 #include <stdlib.h>
114 #include <time.h>       
115 #include "cryptlib.h"
116 #include <openssl/crypto.h>
117 #include <openssl/buffer.h>
118 #include <openssl/bio.h>
119 #include <openssl/lhash.h>
120
121 static int mh_mode=CRYPTO_MEM_CHECK_OFF;
122 /* The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE
123  * when the application asks for it (usually after library initialisation
124  * for which no book-keeping is desired).
125  *
126  * State CRYPTO_MEM_CHECK_ON exists only temporarily when the library
127  * thinks that certain allocations should not be checked (e.g. the data
128  * structures used for memory checking).  It is not suitable as an initial
129  * state: the library will unexpectedly enable memory checking when it
130  * executes one of those sections that want to disable checking
131  * temporarily.
132  *
133  * State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes no sense whatsoever.
134  */
135
136 static unsigned long order = 0; /* number of memory requests */
137
138 DECLARE_LHASH_OF(MEM);
139 static LHASH_OF(MEM) *mh=NULL; /* hash-table of memory requests
140                                 * (address as key); access requires
141                                 * MALLOC2 lock */
142
143
144 typedef struct app_mem_info_st
145 /* For application-defined information (static C-string `info')
146  * to be displayed in memory leak list.
147  * Each thread has its own stack.  For applications, there is
148  *   CRYPTO_push_info("...")     to push an entry,
149  *   CRYPTO_pop_info()           to pop an entry,
150  *   CRYPTO_remove_all_info()    to pop all entries.
151  */
152         {
153         CRYPTO_THREADID threadid;
154         const char *file;
155         int line;
156         const char *info;
157         struct app_mem_info_st *next; /* tail of thread's stack */
158         int references;
159         } APP_INFO;
160
161 static void app_info_free(APP_INFO *);
162
163 DECLARE_LHASH_OF(APP_INFO);
164 static LHASH_OF(APP_INFO) *amih=NULL; /* hash-table with those
165                                        * app_mem_info_st's that are at
166                                        * the top of their thread's
167                                        * stack (with `thread' as key);
168                                        * access requires MALLOC2
169                                        * lock */
170
171 typedef struct mem_st
172 /* memory-block description */
173         {
174         void *addr;
175         int num;
176         const char *file;
177         int line;
178         CRYPTO_THREADID threadid;
179         unsigned long order;
180         time_t time;
181         APP_INFO *app_info;
182         } MEM;
183
184 static long options =             /* extra information to be recorded */
185 #if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL)
186         V_CRYPTO_MDEBUG_TIME |
187 #endif
188 #if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL)
189         V_CRYPTO_MDEBUG_THREAD |
190 #endif
191         0;
192
193
194 static unsigned int num_disable = 0; /* num_disable > 0
195                                       *     iff
196                                       * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE)
197                                       */
198
199 /* Valid iff num_disable > 0.  CRYPTO_LOCK_MALLOC2 is locked exactly in this
200  * case (by the thread named in disabling_threadid). */
201 static CRYPTO_THREADID disabling_threadid;
202
203 static void app_info_free(APP_INFO *inf)
204         {
205         if (--(inf->references) <= 0)
206                 {
207                 if (inf->next != NULL)
208                         {
209                         app_info_free(inf->next);
210                         }
211                 OPENSSL_free(inf);
212                 }
213         }
214
215 int CRYPTO_mem_ctrl(int mode)
216         {
217         int ret=mh_mode;
218
219         CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
220         switch (mode)
221                 {
222         /* for applications (not to be called while multiple threads
223          * use the library): */
224         case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */
225                 mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
226                 num_disable = 0;
227                 break;
228         case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
229                 mh_mode = 0;
230                 num_disable = 0; /* should be true *before* MemCheck_stop is used,
231                                     or there'll be a lot of confusion */
232                 break;
233
234         /* switch off temporarily (for library-internal use): */
235         case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
236                 if (mh_mode & CRYPTO_MEM_CHECK_ON)
237                         {
238                         CRYPTO_THREADID tid;
239                         CRYPTO_THREADID_set(&tid);
240                         if (!num_disable || CRYPTO_THREADID_cmp(&tid,
241                                                 &disabling_threadid))
242                                 {
243                                 /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while
244                                  * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if
245                                  * somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot release
246                                  * it because we block entry to this function).
247                                  * Give them a chance, first, and then claim the locks in
248                                  * appropriate order (long-time lock first).
249                                  */
250                                 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
251                                 /* Note that after we have waited for CRYPTO_LOCK_MALLOC2
252                                  * and CRYPTO_LOCK_MALLOC, we'll still be in the right
253                                  * "case" and "if" branch because MemCheck_start and
254                                  * MemCheck_stop may never be used while there are multiple
255                                  * OpenSSL threads. */
256                                 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
257                                 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
258                                 mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE;
259                                 CRYPTO_THREADID_set(&disabling_threadid);
260                                 }
261                         num_disable++;
262                         }
263                 break;
264         case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */
265                 if (mh_mode & CRYPTO_MEM_CHECK_ON)
266                         {
267                         if (num_disable) /* always true, or something is going wrong */
268                                 {
269                                 num_disable--;
270                                 if (num_disable == 0)
271                                         {
272                                         mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
273                                         CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
274                                         }
275                                 }
276                         }
277                 break;
278
279         default:
280                 break;
281                 }
282         CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
283         return(ret);
284         }
285
286 int CRYPTO_is_mem_check_on(void)
287         {
288         int ret = 0;
289
290         if (mh_mode & CRYPTO_MEM_CHECK_ON)
291                 {
292                 CRYPTO_THREADID tid;
293                 CRYPTO_THREADID_set(&tid);
294                 CRYPTO_r_lock(CRYPTO_LOCK_MALLOC);
295
296                 ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE) ||
297                         CRYPTO_THREADID_cmp(&tid, &disabling_threadid);
298
299                 CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC);
300                 }
301         return(ret);
302         }       
303
304
305 void CRYPTO_dbg_set_options(long bits)
306         {
307         options = bits;
308         }
309
310 long CRYPTO_dbg_get_options(void)
311         {
312         return options;
313         }
314
315 static int mem_cmp(const MEM *a, const MEM *b)
316         {
317 #ifdef _WIN64
318         const char *a=(const char *)a->addr,
319                    *b=(const char *)b->addr;
320         if (a==b)       return 0;
321         else if (a>b)   return 1;
322         else            return -1;
323 #else
324         return (const char *)a->addr - (const char *)b->addr;
325 #endif
326         }
327 static IMPLEMENT_LHASH_COMP_FN(mem, MEM)
328
329 static unsigned long mem_hash(const MEM *a)
330         {
331         unsigned long ret;
332
333         ret=(unsigned long)a->addr;
334
335         ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
336         return(ret);
337         }
338 static IMPLEMENT_LHASH_HASH_FN(mem, MEM)
339
340 /* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */
341 static int app_info_cmp(const void *a_void, const void *b_void)
342         {
343         return CRYPTO_THREADID_cmp(&((const APP_INFO *)a_void)->threadid,
344                                 &((const APP_INFO *)b_void)->threadid);
345         }
346 static IMPLEMENT_LHASH_COMP_FN(app_info, APP_INFO)
347
348 static unsigned long app_info_hash(const APP_INFO *a)
349         {
350         unsigned long ret;
351         ret = CRYPTO_THREADID_hash(&a->threadid);
352         ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
353         return(ret);
354         }
355 static IMPLEMENT_LHASH_HASH_FN(app_info, APP_INFO)
356
357 static APP_INFO *pop_info(void)
358         {
359         APP_INFO tmp;
360         APP_INFO *ret = NULL;
361
362         if (amih != NULL)
363                 {
364                 CRYPTO_THREADID_set(&tmp.threadid);
365                 if ((ret=lh_APP_INFO_delete(amih,&tmp)) != NULL)
366                         {
367                         APP_INFO *next=ret->next;
368
369                         if (next != NULL)
370                                 {
371                                 next->references++;
372                                 lh_APP_INFO_insert(amih,next);
373                                 }
374 #ifdef LEVITTE_DEBUG_MEM
375                         if (CRYPTO_THREADID_cmp(&ret->threadid, &tmp.threadid))
376                                 {
377                                 fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
378                                         CRYPTO_THREADID_hash(&ret->threadid),
379                                         CRYPTO_THREADID_hash(&tmp.threadid));
380                                 abort();
381                                 }
382 #endif
383                         if (--(ret->references) <= 0)
384                                 {
385                                 ret->next = NULL;
386                                 if (next != NULL)
387                                         next->references--;
388                                 OPENSSL_free(ret);
389                                 }
390                         }
391                 }
392         return(ret);
393         }
394
395 int CRYPTO_push_info_(const char *info, const char *file, int line)
396         {
397         APP_INFO *ami, *amim;
398         int ret=0;
399
400         if (is_MemCheck_on())
401                 {
402                 MemCheck_off(); /* obtain MALLOC2 lock */
403
404                 if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL)
405                         {
406                         ret=0;
407                         goto err;
408                         }
409                 if (amih == NULL)
410                         {
411                         if ((amih=lh_APP_INFO_new()) == NULL)
412                                 {
413                                 OPENSSL_free(ami);
414                                 ret=0;
415                                 goto err;
416                                 }
417                         }
418
419                 CRYPTO_THREADID_set(&ami->threadid);
420                 ami->file=file;
421                 ami->line=line;
422                 ami->info=info;
423                 ami->references=1;
424                 ami->next=NULL;
425
426                 if ((amim=lh_APP_INFO_insert(amih,ami)) != NULL)
427                         {
428 #ifdef LEVITTE_DEBUG_MEM
429                         if (CRYPTO_THREADID_cmp(&ami->threadid, &amim->threadid))
430                                 {
431                                 fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
432                                         CRYPTO_THREADID_hash(&amim->threadid),
433                                         CRYPTO_THREADID_hash(&ami->threadid));
434                                 abort();
435                                 }
436 #endif
437                         ami->next=amim;
438                         }
439  err:
440                 MemCheck_on(); /* release MALLOC2 lock */
441                 }
442
443         return(ret);
444         }
445
446 int CRYPTO_pop_info(void)
447         {
448         int ret=0;
449
450         if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */
451                 {
452                 MemCheck_off(); /* obtain MALLOC2 lock */
453
454                 ret=(pop_info() != NULL);
455
456                 MemCheck_on(); /* release MALLOC2 lock */
457                 }
458         return(ret);
459         }
460
461 int CRYPTO_remove_all_info(void)
462         {
463         int ret=0;
464
465         if (is_MemCheck_on()) /* _must_ be true */
466                 {
467                 MemCheck_off(); /* obtain MALLOC2 lock */
468
469                 while(pop_info() != NULL)
470                         ret++;
471
472                 MemCheck_on(); /* release MALLOC2 lock */
473                 }
474         return(ret);
475         }
476
477
478 static unsigned long break_order_num=0;
479 void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
480         int before_p)
481         {
482         MEM *m,*mm;
483         APP_INFO tmp,*amim;
484
485         switch(before_p & 127)
486                 {
487         case 0:
488                 break;
489         case 1:
490                 if (addr == NULL)
491                         break;
492
493                 if (is_MemCheck_on())
494                         {
495                         MemCheck_off(); /* make sure we hold MALLOC2 lock */
496                         if ((m=(MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL)
497                                 {
498                                 OPENSSL_free(addr);
499                                 MemCheck_on(); /* release MALLOC2 lock
500                                                 * if num_disabled drops to 0 */
501                                 return;
502                                 }
503                         if (mh == NULL)
504                                 {
505                                 if ((mh=lh_MEM_new()) == NULL)
506                                         {
507                                         OPENSSL_free(addr);
508                                         OPENSSL_free(m);
509                                         addr=NULL;
510                                         goto err;
511                                         }
512                                 }
513
514                         m->addr=addr;
515                         m->file=file;
516                         m->line=line;
517                         m->num=num;
518                         CRYPTO_THREADID_set(&m->threadid);
519
520                         if (order == break_order_num)
521                                 {
522                                 /* BREAK HERE */
523                                 m->order=order;
524                                 }
525                         m->order=order++;
526 #ifdef LEVITTE_DEBUG_MEM
527                         fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] %c 0x%p (%d)\n",
528                                 m->order,
529                                 (before_p & 128) ? '*' : '+',
530                                 m->addr, m->num);
531 #endif
532                         if (options & V_CRYPTO_MDEBUG_TIME)
533                                 m->time=time(NULL);
534                         else
535                                 m->time=0;
536
537                         CRYPTO_THREADID_set(&m->threadid);
538                         m->app_info=NULL;
539                         if (amih != NULL
540                             && (amim=lh_APP_INFO_retrieve(amih,&tmp)) != NULL)
541                                 {
542                                 m->app_info = amim;
543                                 amim->references++;
544                                 }
545
546                         if ((mm=lh_MEM_insert(mh, m)) != NULL)
547                                 {
548                                 /* Not good, but don't sweat it */
549                                 if (mm->app_info != NULL)
550                                         {
551                                         mm->app_info->references--;
552                                         }
553                                 OPENSSL_free(mm);
554                                 }
555                 err:
556                         MemCheck_on(); /* release MALLOC2 lock
557                                         * if num_disabled drops to 0 */
558                         }
559                 break;
560                 }
561         return;
562         }
563
564 void CRYPTO_dbg_free(void *addr, int before_p)
565         {
566         MEM m,*mp;
567
568         switch(before_p)
569                 {
570         case 0:
571                 if (addr == NULL)
572                         break;
573
574                 if (is_MemCheck_on() && (mh != NULL))
575                         {
576                         MemCheck_off(); /* make sure we hold MALLOC2 lock */
577
578                         m.addr=addr;
579                         mp=lh_MEM_delete(mh,&m);
580                         if (mp != NULL)
581                                 {
582 #ifdef LEVITTE_DEBUG_MEM
583                         fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] - 0x%p (%d)\n",
584                                 mp->order, mp->addr, mp->num);
585 #endif
586                                 if (mp->app_info != NULL)
587                                         app_info_free(mp->app_info);
588                                 OPENSSL_free(mp);
589                                 }
590
591                         MemCheck_on(); /* release MALLOC2 lock
592                                         * if num_disabled drops to 0 */
593                         }
594                 break;
595         case 1:
596                 break;
597                 }
598         }
599
600 void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
601         const char *file, int line, int before_p)
602         {
603         MEM m,*mp;
604
605 #ifdef LEVITTE_DEBUG_MEM
606         fprintf(stderr, "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n",
607                 addr1, addr2, num, file, line, before_p);
608 #endif
609
610         switch(before_p)
611                 {
612         case 0:
613                 break;
614         case 1:
615                 if (addr2 == NULL)
616                         break;
617
618                 if (addr1 == NULL)
619                         {
620                         CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p);
621                         break;
622                         }
623
624                 if (is_MemCheck_on())
625                         {
626                         MemCheck_off(); /* make sure we hold MALLOC2 lock */
627
628                         m.addr=addr1;
629                         mp=lh_MEM_delete(mh,&m);
630                         if (mp != NULL)
631                                 {
632 #ifdef LEVITTE_DEBUG_MEM
633                                 fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] * 0x%p (%d) -> 0x%p (%d)\n",
634                                         mp->order,
635                                         mp->addr, mp->num,
636                                         addr2, num);
637 #endif
638                                 mp->addr=addr2;
639                                 mp->num=num;
640                                 lh_MEM_insert(mh,mp);
641                                 }
642
643                         MemCheck_on(); /* release MALLOC2 lock
644                                         * if num_disabled drops to 0 */
645                         }
646                 break;
647                 }
648         return;
649         }
650
651
652 typedef struct mem_leak_st
653         {
654         BIO *bio;
655         int chunks;
656         long bytes;
657         } MEM_LEAK;
658
659 static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l)
660         {
661         char buf[1024];
662         char *bufp = buf;
663         APP_INFO *amip;
664         int ami_cnt;
665         struct tm *lcl = NULL;
666         CRYPTO_THREADID tid;
667
668 #define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf))
669
670         if(m->addr == (char *)l->bio)
671             return;
672
673         if (options & V_CRYPTO_MDEBUG_TIME)
674                 {
675                 lcl = localtime(&m->time);
676         
677                 BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ",
678                         lcl->tm_hour,lcl->tm_min,lcl->tm_sec);
679                 bufp += strlen(bufp);
680                 }
681
682         BIO_snprintf(bufp, BUF_REMAIN, "%5lu file=%s, line=%d, ",
683                 m->order,m->file,m->line);
684         bufp += strlen(bufp);
685
686         if (options & V_CRYPTO_MDEBUG_THREAD)
687                 {
688                 BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ",
689                         CRYPTO_THREADID_hash(&m->threadid));
690                 bufp += strlen(bufp);
691                 }
692
693         BIO_snprintf(bufp, BUF_REMAIN, "number=%d, address=%08lX\n",
694                 m->num,(unsigned long)m->addr);
695         bufp += strlen(bufp);
696
697         BIO_puts(l->bio,buf);
698         
699         l->chunks++;
700         l->bytes+=m->num;
701
702         amip=m->app_info;
703         ami_cnt=0;
704         if (!amip)
705                 return;
706         CRYPTO_THREADID_set(&tid);
707         
708         do
709                 {
710                 int buf_len;
711                 int info_len;
712
713                 ami_cnt++;
714                 memset(buf,'>',ami_cnt);
715                 BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt,
716                         " thread=%lu, file=%s, line=%d, info=\"",
717                         CRYPTO_THREADID_hash(&amip->threadid), amip->file, amip->line);
718                 buf_len=strlen(buf);
719                 info_len=strlen(amip->info);
720                 if (128 - buf_len - 3 < info_len)
721                         {
722                         memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
723                         buf_len = 128 - 3;
724                         }
725                 else
726                         {
727                         BUF_strlcpy(buf + buf_len, amip->info,
728                                     sizeof buf - buf_len);
729                         buf_len = strlen(buf);
730                         }
731                 BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n");
732                 
733                 BIO_puts(l->bio,buf);
734
735                 amip = amip->next;
736                 }
737         while(amip && !CRYPTO_THREADID_cmp(&amip->threadid, &tid));
738
739 #ifdef LEVITTE_DEBUG_MEM
740         if (amip)
741                 {
742                 fprintf(stderr, "Thread switch detected in backtrace!!!!\n");
743                 abort();
744                 }
745 #endif
746         }
747
748 static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM, MEM_LEAK)
749
750 void CRYPTO_mem_leaks(BIO *b)
751         {
752         MEM_LEAK ml;
753
754         if (mh == NULL && amih == NULL)
755                 return;
756
757         MemCheck_off(); /* obtain MALLOC2 lock */
758
759         ml.bio=b;
760         ml.bytes=0;
761         ml.chunks=0;
762         if (mh != NULL)
763                 lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak), MEM_LEAK,
764                                  &ml);
765         if (ml.chunks != 0)
766                 {
767                 BIO_printf(b,"%ld bytes leaked in %d chunks\n",
768                            ml.bytes,ml.chunks);
769                 }
770         else
771                 {
772                 /* Make sure that, if we found no leaks, memory-leak debugging itself
773                  * does not introduce memory leaks (which might irritate
774                  * external debugging tools).
775                  * (When someone enables leak checking, but does not call
776                  * this function, we declare it to be their fault.)
777                  *
778                  * XXX    This should be in CRYPTO_mem_leaks_cb,
779                  * and CRYPTO_mem_leaks should be implemented by
780                  * using CRYPTO_mem_leaks_cb.
781                  * (Also their should be a variant of lh_doall_arg
782                  * that takes a function pointer instead of a void *;
783                  * this would obviate the ugly and illegal
784                  * void_fn_to_char kludge in CRYPTO_mem_leaks_cb.
785                  * Otherwise the code police will come and get us.)
786                  */
787                 int old_mh_mode;
788
789                 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
790
791                 /* avoid deadlock when lh_free() uses CRYPTO_dbg_free(),
792                  * which uses CRYPTO_is_mem_check_on */
793                 old_mh_mode = mh_mode;
794                 mh_mode = CRYPTO_MEM_CHECK_OFF;
795
796                 if (mh != NULL)
797                         {
798                         lh_MEM_free(mh);
799                         mh = NULL;
800                         }
801                 if (amih != NULL)
802                         {
803                         if (lh_APP_INFO_num_items(amih) == 0) 
804                                 {
805                                 lh_APP_INFO_free(amih);
806                                 amih = NULL;
807                                 }
808                         }
809
810                 mh_mode = old_mh_mode;
811                 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
812                 }
813         MemCheck_on(); /* release MALLOC2 lock */
814         }
815
816 #ifndef OPENSSL_NO_FP_API
817 void CRYPTO_mem_leaks_fp(FILE *fp)
818         {
819         BIO *b;
820
821         if (mh == NULL) return;
822         /* Need to turn off memory checking when allocated BIOs ... especially
823          * as we're creating them at a time when we're trying to check we've not
824          * left anything un-free()'d!! */
825         MemCheck_off();
826         b = BIO_new(BIO_s_file());
827         MemCheck_on();
828         if(!b) return;
829         BIO_set_fp(b,fp,BIO_NOCLOSE);
830         CRYPTO_mem_leaks(b);
831         BIO_free(b);
832         }
833 #endif
834
835
836
837 /* FIXME: We really don't allow much to the callback.  For example, it has
838    no chance of reaching the info stack for the item it processes.  Should
839    it really be this way?  -- Richard Levitte */
840 /* NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside crypto.h
841  * If this code is restructured, remove the callback type if it is no longer
842  * needed. -- Geoff Thorpe */
843 static void cb_leak_doall_arg(const MEM *m, CRYPTO_MEM_LEAK_CB *cb)
844         {
845         cb(m->order,m->file,m->line,m->num,m->addr);
846         }
847
848 static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM, CRYPTO_MEM_LEAK_CB)
849
850 void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
851         {
852         if (mh == NULL) return;
853         CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
854         lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), CRYPTO_MEM_LEAK_CB,
855                          cb);
856         CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
857         }