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