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