mem-cleanup, cont'd.
[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 "internal/cryptlib.h"
116 #include <openssl/crypto.h>
117 #include <openssl/buffer.h>
118 #include <openssl/bio.h>
119 #include <openssl/lhash.h>
120 #if defined(CRYPTO_MDEBUG_BACKTRACE) && defined(__GNUC__)
121 # include <execinfo.h>
122 #endif
123
124 static int mh_mode = CRYPTO_MEM_CHECK_OFF;
125 /*
126  * The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE when
127  * the application asks for it (usually after library initialisation for
128  * which no book-keeping is desired). State CRYPTO_MEM_CHECK_ON exists only
129  * temporarily when the library thinks that certain allocations should not be
130  * checked (e.g. the data structures used for memory checking).  It is not
131  * suitable as an initial state: the library will unexpectedly enable memory
132  * checking when it executes one of those sections that want to disable
133  * checking temporarily. State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes
134  * no sense whatsoever.
135  */
136
137 static unsigned long order = 0; /* number of memory requests */
138
139 DECLARE_LHASH_OF(MEM);
140 static LHASH_OF(MEM) *mh = NULL; /* hash-table of memory requests (address as
141                                   * key); access requires MALLOC2 lock */
142
143 typedef struct app_mem_info_st
144 /*-
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 the
166                                          * top of their thread's stack (with
167                                          * `thread' as key); access requires
168                                          * MALLOC2 lock */
169
170 typedef struct mem_st
171 /* memory-block description */
172 {
173     void *addr;
174     int num;
175     const char *file;
176     int line;
177     CRYPTO_THREADID threadid;
178     unsigned long order;
179     time_t time;
180     APP_INFO *app_info;
181 #if defined(CRYPTO_MDEBUG_BACKTRACE) && defined(__GNUC__)
182     void *array[30];
183     size_t array_siz;
184 #endif
185 } MEM;
186
187 static long options =           /* extra information to be recorded */
188 #if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL)
189     V_CRYPTO_MDEBUG_TIME |
190 #endif
191 #if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL)
192     V_CRYPTO_MDEBUG_THREAD |
193 #endif
194     0;
195
196 static unsigned int num_disable = 0; /* num_disable > 0 iff mh_mode ==
197                                       * 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)
208         return;
209     if (--(inf->references) <= 0) {
210         app_info_free(inf->next);
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 use the
223          * library):
224          */
225     case CRYPTO_MEM_CHECK_ON:  /* aka MemCheck_start() */
226         mh_mode = CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE;
227         num_disable = 0;
228         break;
229     case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
230         mh_mode = 0;
231         num_disable = 0;        /* should be true *before* MemCheck_stop is
232                                  * used, or there'll be a lot of confusion */
233         break;
234
235         /* switch off temporarily (for library-internal use): */
236     case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
237         if (mh_mode & CRYPTO_MEM_CHECK_ON) {
238             CRYPTO_THREADID cur;
239             CRYPTO_THREADID_current(&cur);
240             /* see if we don't have the MALLOC2 lock already */
241             if (!num_disable
242                 || CRYPTO_THREADID_cmp(&disabling_threadid, &cur)) {
243                 /*
244                  * Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed
245                  * while we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock
246                  * if somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot
247                  * release it because we block entry to this function). Give
248                  * 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                 /*
253                  * Note that after we have waited for CRYPTO_LOCK_MALLOC2 and
254                  * CRYPTO_LOCK_MALLOC, we'll still be in the right "case" and
255                  * "if" branch because MemCheck_start and MemCheck_stop may
256                  * never be used while there are multiple OpenSSL threads.
257                  */
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             if (num_disable) {  /* always true, or something is going wrong */
269                 num_disable--;
270                 if (num_disable == 0) {
271                     mh_mode |= CRYPTO_MEM_CHECK_ENABLE;
272                     CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
273                 }
274             }
275         }
276         break;
277
278     default:
279         break;
280     }
281     CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
282     return (ret);
283 }
284
285 int CRYPTO_is_mem_check_on(void)
286 {
287     int ret = 0;
288
289     if (mh_mode & CRYPTO_MEM_CHECK_ON) {
290         CRYPTO_THREADID cur;
291         CRYPTO_THREADID_current(&cur);
292         CRYPTO_r_lock(CRYPTO_LOCK_MALLOC);
293
294         ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
295             || CRYPTO_THREADID_cmp(&disabling_threadid, &cur);
296
297         CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC);
298     }
299     return (ret);
300 }
301
302 void CRYPTO_dbg_set_options(long bits)
303 {
304     options = bits;
305 }
306
307 long CRYPTO_dbg_get_options(void)
308 {
309     return options;
310 }
311
312 static int mem_cmp(const MEM *a, const MEM *b)
313 {
314 #ifdef _WIN64
315     const char *ap = (const char *)a->addr, *bp = (const char *)b->addr;
316     if (ap == bp)
317         return 0;
318     else if (ap > bp)
319         return 1;
320     else
321         return -1;
322 #else
323     return (const char *)a->addr - (const char *)b->addr;
324 #endif
325 }
326
327 static IMPLEMENT_LHASH_COMP_FN(mem, MEM)
328
329 static unsigned long mem_hash(const MEM *a)
330 {
331     size_t ret;
332
333     ret = (size_t)a->addr;
334
335     ret = ret * 17851 + (ret >> 14) * 7 + (ret >> 4) * 251;
336     return (ret);
337 }
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
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
360 static IMPLEMENT_LHASH_HASH_FN(app_info, APP_INFO)
361
362 static APP_INFO *pop_info(void)
363 {
364     APP_INFO tmp;
365     APP_INFO *ret = NULL;
366
367     if (amih != NULL) {
368         CRYPTO_THREADID_current(&tmp.threadid);
369         if ((ret = lh_APP_INFO_delete(amih, &tmp)) != NULL) {
370             APP_INFO *next = ret->next;
371
372             if (next != NULL) {
373                 next->references++;
374                 (void)lh_APP_INFO_insert(amih, next);
375             }
376             if (--(ret->references) <= 0) {
377                 ret->next = NULL;
378                 if (next != NULL)
379                     next->references--;
380                 OPENSSL_free(ret);
381             }
382         }
383     }
384     return (ret);
385 }
386
387 int CRYPTO_push_info_(const char *info, const char *file, int line)
388 {
389     APP_INFO *ami, *amim;
390     int ret = 0;
391
392     if (is_MemCheck_on()) {
393         MemCheck_off();         /* obtain MALLOC2 lock */
394
395         if ((ami = OPENSSL_malloc(sizeof(*ami))) == NULL) {
396             ret = 0;
397             goto err;
398         }
399         if (amih == NULL) {
400             if ((amih = lh_APP_INFO_new()) == NULL) {
401                 OPENSSL_free(ami);
402                 ret = 0;
403                 goto err;
404             }
405         }
406
407         CRYPTO_THREADID_current(&ami->threadid);
408         ami->file = file;
409         ami->line = line;
410         ami->info = info;
411         ami->references = 1;
412         ami->next = NULL;
413
414         if ((amim = lh_APP_INFO_insert(amih, ami)) != NULL)
415             ami->next = amim;
416  err:
417         MemCheck_on();          /* release MALLOC2 lock */
418     }
419
420     return (ret);
421 }
422
423 int CRYPTO_pop_info(void)
424 {
425     int ret = 0;
426
427     if (is_MemCheck_on()) {     /* _must_ be true, or something went severely
428                                  * wrong */
429         MemCheck_off();         /* obtain MALLOC2 lock */
430
431         ret = (pop_info() != NULL);
432
433         MemCheck_on();          /* release MALLOC2 lock */
434     }
435     return (ret);
436 }
437
438 int CRYPTO_remove_all_info(void)
439 {
440     int ret = 0;
441
442     if (is_MemCheck_on()) {     /* _must_ be true */
443         MemCheck_off();         /* obtain MALLOC2 lock */
444
445         while (pop_info() != NULL)
446             ret++;
447
448         MemCheck_on();          /* release MALLOC2 lock */
449     }
450     return (ret);
451 }
452
453 static unsigned long break_order_num = 0;
454 void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
455                        int before_p)
456 {
457     MEM *m, *mm;
458     APP_INFO tmp, *amim;
459
460     switch (before_p & 127) {
461     case 0:
462         break;
463     case 1:
464         if (addr == NULL)
465             break;
466
467         if (is_MemCheck_on()) {
468             MemCheck_off();     /* make sure we hold MALLOC2 lock */
469             if ((m = OPENSSL_malloc(sizeof(*m))) == NULL) {
470                 OPENSSL_free(addr);
471                 MemCheck_on();  /* release MALLOC2 lock if num_disabled drops
472                                  * to 0 */
473                 return;
474             }
475             if (mh == NULL) {
476                 if ((mh = lh_MEM_new()) == NULL) {
477                     OPENSSL_free(addr);
478                     OPENSSL_free(m);
479                     addr = NULL;
480                     goto err;
481                 }
482             }
483
484             m->addr = addr;
485             m->file = file;
486             m->line = line;
487             m->num = num;
488             if (options & V_CRYPTO_MDEBUG_THREAD)
489                 CRYPTO_THREADID_current(&m->threadid);
490             else
491                 memset(&m->threadid, 0, sizeof(m->threadid));
492
493             if (order == break_order_num) {
494                 /* BREAK HERE */
495                 m->order = order;
496             }
497             m->order = order++;
498             if (options & V_CRYPTO_MDEBUG_TIME)
499                 m->time = time(NULL);
500             else
501                 m->time = 0;
502 #if defined(CRYPTO_MDEBUG_BACKTRACE) && defined(__GNUC__)
503             m->array_siz = backtrace(m->array, OSSL_NELEM(m->array));
504 #endif
505
506             CRYPTO_THREADID_current(&tmp.threadid);
507             m->app_info = NULL;
508             if (amih != NULL
509                 && (amim = lh_APP_INFO_retrieve(amih, &tmp)) != NULL) {
510                 m->app_info = amim;
511                 amim->references++;
512             }
513
514             if ((mm = lh_MEM_insert(mh, m)) != NULL) {
515                 /* Not good, but don't sweat it */
516                 if (mm->app_info != NULL) {
517                     mm->app_info->references--;
518                 }
519                 OPENSSL_free(mm);
520             }
521  err:
522             MemCheck_on();      /* release MALLOC2 lock if num_disabled drops
523                                  * to 0 */
524         }
525         break;
526     }
527     return;
528 }
529
530 void CRYPTO_dbg_free(void *addr, int before_p)
531 {
532     MEM m, *mp;
533
534     switch (before_p) {
535     case 0:
536         if (addr == NULL)
537             break;
538
539         if (is_MemCheck_on() && (mh != NULL)) {
540             MemCheck_off();     /* make sure we hold MALLOC2 lock */
541
542             m.addr = addr;
543             mp = lh_MEM_delete(mh, &m);
544             if (mp != NULL) {
545                 app_info_free(mp->app_info);
546                 OPENSSL_free(mp);
547             }
548
549             MemCheck_on();      /* release MALLOC2 lock if num_disabled drops
550                                  * to 0 */
551         }
552         break;
553     case 1:
554         break;
555     }
556 }
557
558 void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
559                         const char *file, int line, int before_p)
560 {
561     MEM m, *mp;
562
563     switch (before_p) {
564     case 0:
565         break;
566     case 1:
567         if (addr2 == NULL)
568             break;
569
570         if (addr1 == NULL) {
571             CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p);
572             break;
573         }
574
575         if (is_MemCheck_on()) {
576             MemCheck_off();     /* make sure we hold MALLOC2 lock */
577
578             m.addr = addr1;
579             mp = lh_MEM_delete(mh, &m);
580             if (mp != NULL) {
581                 mp->addr = addr2;
582                 mp->num = num;
583 #if defined(CRYPTO_MDEBUG_BACKTRACE) && defined(__GNUC__)
584                 mp->array_siz = backtrace(mp->array, OSSL_NELEM(mp->array));
585 #endif
586                 (void)lh_MEM_insert(mh, mp);
587             }
588
589             MemCheck_on();      /* release MALLOC2 lock if num_disabled drops
590                                  * to 0 */
591         }
592         break;
593     }
594     return;
595 }
596
597 typedef struct mem_leak_st {
598     BIO *bio;
599     int chunks;
600     int seen;
601     long bytes;
602 } MEM_LEAK;
603
604 static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l)
605 {
606     char buf[1024];
607     char *bufp = buf;
608     APP_INFO *amip;
609     int ami_cnt;
610     struct tm *lcl = NULL;
611     CRYPTO_THREADID ti;
612
613 #define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf))
614
615     /* Is one "leak" the BIO we were given? */
616     if (m->addr == (char *)l->bio) {
617         l->seen = 1;
618         return;
619     }
620
621     if (options & V_CRYPTO_MDEBUG_TIME) {
622         lcl = localtime(&m->time);
623
624         BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ",
625                      lcl->tm_hour, lcl->tm_min, lcl->tm_sec);
626         bufp += strlen(bufp);
627     }
628
629     BIO_snprintf(bufp, BUF_REMAIN, "%5lu file=%s, line=%d, ",
630                  m->order, m->file, m->line);
631     bufp += strlen(bufp);
632
633     if (options & V_CRYPTO_MDEBUG_THREAD) {
634         BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ",
635                      CRYPTO_THREADID_hash(&m->threadid));
636         bufp += strlen(bufp);
637     }
638
639     BIO_snprintf(bufp, BUF_REMAIN, "number=%d, address=%p\n",
640                  m->num, m->addr);
641     bufp += strlen(bufp);
642
643     BIO_puts(l->bio, buf);
644
645     l->chunks++;
646     l->bytes += m->num;
647
648     amip = m->app_info;
649     ami_cnt = 0;
650     if (amip) {
651         CRYPTO_THREADID_cpy(&ti, &amip->threadid);
652
653         do {
654             int buf_len;
655             int info_len;
656
657             ami_cnt++;
658             memset(buf, '>', ami_cnt);
659             BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt,
660                          " thread=%lu, file=%s, line=%d, info=\"",
661                          CRYPTO_THREADID_hash(&amip->threadid), amip->file,
662                          amip->line);
663             buf_len = strlen(buf);
664             info_len = strlen(amip->info);
665             if (128 - buf_len - 3 < info_len) {
666                 memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
667                 buf_len = 128 - 3;
668             } else {
669                 OPENSSL_strlcpy(buf + buf_len, amip->info, sizeof buf - buf_len);
670                 buf_len = strlen(buf);
671             }
672             BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n");
673
674             BIO_puts(l->bio, buf);
675
676             amip = amip->next;
677         }
678         while (amip && !CRYPTO_THREADID_cmp(&amip->threadid, &ti));
679     }
680
681 #if defined(CRYPTO_MDEBUG_BACKTRACE) && defined(__GNUC__)
682     {
683         size_t i;
684         char **strings = backtrace_symbols(m->array, m->array_siz);
685         for (i = 0; i < m->array_siz; i++)
686             fprintf(stderr, "##> %s\n", strings[i]);
687
688         free(strings);
689     }
690 #endif
691 }
692
693 static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM, MEM_LEAK)
694
695 void CRYPTO_mem_leaks(BIO *b)
696 {
697     MEM_LEAK ml;
698
699     if (mh == NULL && amih == NULL)
700         return;
701
702     MemCheck_off();             /* obtain MALLOC2 lock */
703
704     ml.bio = b;
705     ml.bytes = 0;
706     ml.chunks = 0;
707     ml.seen = 0;
708     if (mh != NULL)
709         lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak), MEM_LEAK, &ml);
710     /* Don't count the BIO that was passed in as a "leak" */
711     if (ml.seen && ml.chunks >= 1 && ml.bytes >= (int)sizeof (*b)) {
712         ml.chunks--;
713         ml.bytes -= (int)sizeof (*b);
714     }
715     if (ml.chunks != 0) {
716         BIO_printf(b, "%ld bytes leaked in %d chunks\n", ml.bytes, ml.chunks);
717 #ifdef CRYPTO_MDEBUG_ABORT
718         abort();
719 #endif
720     } else {
721         /*
722          * Make sure that, if we found no leaks, memory-leak debugging itself
723          * does not introduce memory leaks (which might irritate external
724          * debugging tools). (When someone enables leak checking, but does not
725          * call this function, we declare it to be their fault.) XXX This
726          * should be in CRYPTO_mem_leaks_cb, and CRYPTO_mem_leaks should be
727          * implemented by using CRYPTO_mem_leaks_cb. (Also there should be a
728          * variant of lh_doall_arg that takes a function pointer instead of a
729          * void *; this would obviate the ugly and illegal void_fn_to_char
730          * kludge in CRYPTO_mem_leaks_cb. Otherwise the code police will come
731          * and get us.)
732          */
733         int old_mh_mode;
734
735         CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
736
737         /*
738          * avoid deadlock when lh_free() uses CRYPTO_dbg_free(), which uses
739          * CRYPTO_is_mem_check_on
740          */
741         old_mh_mode = mh_mode;
742         mh_mode = CRYPTO_MEM_CHECK_OFF;
743
744         lh_MEM_free(mh);
745         mh = NULL;
746         if (amih != NULL) {
747             if (lh_APP_INFO_num_items(amih) == 0) {
748                 lh_APP_INFO_free(amih);
749                 amih = NULL;
750             }
751         }
752
753         mh_mode = old_mh_mode;
754         CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
755     }
756     MemCheck_on();              /* release MALLOC2 lock */
757 }
758
759 #ifndef OPENSSL_NO_STDIO
760 void CRYPTO_mem_leaks_fp(FILE *fp)
761 {
762     BIO *b;
763
764     if (mh == NULL)
765         return;
766     /*
767      * Need to turn off memory checking when allocated BIOs ... especially as
768      * we're creating them at a time when we're trying to check we've not
769      * left anything un-free()'d!!
770      */
771     MemCheck_off();
772     b = BIO_new(BIO_s_file());
773     MemCheck_on();
774     if (b == NULL)
775         return;
776     BIO_set_fp(b, fp, BIO_NOCLOSE);
777     CRYPTO_mem_leaks(b);
778     BIO_free(b);
779 }
780 #endif
781
782 /*
783  * FIXME: We really don't allow much to the callback.  For example, it has no
784  * chance of reaching the info stack for the item it processes.  Should it
785  * really be this way? -- Richard Levitte
786  */
787 /*
788  * NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside
789  * crypto.h If this code is restructured, remove the callback type if it is
790  * no longer needed. -- Geoff Thorpe
791  */
792
793 /*
794  * Can't pass CRYPTO_MEM_LEAK_CB directly to lh_MEM_doall_arg because it is a
795  * function pointer and conversion to void * is prohibited. Instead pass its
796  * address
797  */
798
799 typedef CRYPTO_MEM_LEAK_CB *PCRYPTO_MEM_LEAK_CB;
800
801 static void cb_leak_doall_arg(const MEM *m, PCRYPTO_MEM_LEAK_CB *cb)
802 {
803     (*cb) (m->order, m->file, m->line, m->num, m->addr);
804 }
805
806 static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM, PCRYPTO_MEM_LEAK_CB)
807
808 void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
809 {
810     if (mh == NULL)
811         return;
812     CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
813     lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), PCRYPTO_MEM_LEAK_CB,
814                      &cb);
815     CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
816 }