blob: 236431e9100458ef5128235f51c55a71f8bf521f [file] [log] [blame]
Kinson Chika8fa74c2011-07-29 11:33:41 -07001/* 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>
Kinson Chik2cd211f2011-07-27 19:27:35 -0700114#ifndef LK_NO_TIME
115#include <time.h>
116#endif
Kinson Chika8fa74c2011-07-29 11:33:41 -0700117#include "cryptlib.h"
118#include <openssl/crypto.h>
119#include <openssl/buffer.h>
120#include <openssl/bio.h>
121#include <openssl/lhash.h>
122
123static int mh_mode=CRYPTO_MEM_CHECK_OFF;
124/* The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE
125 * when the application asks for it (usually after library initialisation
126 * for which no book-keeping is desired).
127 *
128 * State CRYPTO_MEM_CHECK_ON exists only temporarily when the library
129 * thinks that certain allocations should not be checked (e.g. the data
130 * structures used for memory checking). It is not suitable as an initial
131 * state: the library will unexpectedly enable memory checking when it
132 * executes one of those sections that want to disable checking
133 * temporarily.
134 *
135 * State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes no sense whatsoever.
136 */
137
138static unsigned long order = 0; /* number of memory requests */
139
140DECLARE_LHASH_OF(MEM);
141static LHASH_OF(MEM) *mh=NULL; /* hash-table of memory requests
142 * (address as key); access requires
143 * MALLOC2 lock */
144
145
146typedef struct app_mem_info_st
147/* For application-defined information (static C-string `info')
148 * to be displayed in memory leak list.
149 * Each thread has its own stack. For applications, there is
150 * CRYPTO_push_info("...") to push an entry,
151 * CRYPTO_pop_info() to pop an entry,
152 * CRYPTO_remove_all_info() to pop all entries.
153 */
154 {
155 CRYPTO_THREADID threadid;
156 const char *file;
157 int line;
158 const char *info;
159 struct app_mem_info_st *next; /* tail of thread's stack */
160 int references;
161 } APP_INFO;
162
163static void app_info_free(APP_INFO *);
164
165DECLARE_LHASH_OF(APP_INFO);
166static LHASH_OF(APP_INFO) *amih=NULL; /* hash-table with those
167 * app_mem_info_st's that are at
168 * the top of their thread's
169 * stack (with `thread' as key);
170 * access requires MALLOC2
171 * lock */
172
173typedef struct mem_st
174/* memory-block description */
175 {
176 void *addr;
177 int num;
178 const char *file;
179 int line;
180 CRYPTO_THREADID threadid;
181 unsigned long order;
182 time_t time;
183 APP_INFO *app_info;
184 } MEM;
185
186static long options = /* extra information to be recorded */
187#if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL)
188 V_CRYPTO_MDEBUG_TIME |
189#endif
190#if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL)
191 V_CRYPTO_MDEBUG_THREAD |
192#endif
193 0;
194
195
196static unsigned int num_disable = 0; /* num_disable > 0
197 * iff
198 * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE)
199 */
200
201/* Valid iff num_disable > 0. CRYPTO_LOCK_MALLOC2 is locked exactly in this
202 * case (by the thread named in disabling_thread).
203 */
204static CRYPTO_THREADID disabling_threadid;
205
206static void app_info_free(APP_INFO *inf)
207 {
208 if (--(inf->references) <= 0)
209 {
210 if (inf->next != NULL)
211 {
212 app_info_free(inf->next);
213 }
214 OPENSSL_free(inf);
215 }
216 }
217
218int CRYPTO_mem_ctrl(int mode)
219 {
220 int ret=mh_mode;
221
222 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
223 switch (mode)
224 {
225 /* for applications (not to be called while multiple threads
226 * use the library): */
227 case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */
228 mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
229 num_disable = 0;
230 break;
231 case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
232 mh_mode = 0;
233 num_disable = 0; /* should be true *before* MemCheck_stop is used,
234 or there'll be a lot of confusion */
235 break;
236
237 /* switch off temporarily (for library-internal use): */
238 case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
239 if (mh_mode & CRYPTO_MEM_CHECK_ON)
240 {
241 CRYPTO_THREADID cur;
242 CRYPTO_THREADID_current(&cur);
243 if (!num_disable || CRYPTO_THREADID_cmp(&disabling_threadid, &cur)) /* otherwise we already have the MALLOC2 lock */
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
288int 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
307void CRYPTO_dbg_set_options(long bits)
308 {
309 options = bits;
310 }
311
312long CRYPTO_dbg_get_options(void)
313 {
314 return options;
315 }
316
317static 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 }
329static IMPLEMENT_LHASH_COMP_FN(mem, MEM)
330
331static 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 }
340static IMPLEMENT_LHASH_HASH_FN(mem, MEM)
341
342/* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */
343static 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 }
348static IMPLEMENT_LHASH_COMP_FN(app_info, APP_INFO)
349
350static 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 }
359static IMPLEMENT_LHASH_HASH_FN(app_info, APP_INFO)
360
361static 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
399int 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
450int 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
465int 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
482static unsigned long break_order_num=0;
483void 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)
Unnati Gandhieef3dbf2014-07-17 14:45:43 +0530540#ifndef LK_NO_TIME
Kinson Chika8fa74c2011-07-29 11:33:41 -0700541 m->time=time(NULL);
Unnati Gandhieef3dbf2014-07-17 14:45:43 +0530542#else
543 m->time=0;
544#endif
Kinson Chika8fa74c2011-07-29 11:33:41 -0700545 else
546 m->time=0;
547
548 CRYPTO_THREADID_current(&tmp.threadid);
549 m->app_info=NULL;
550 if (amih != NULL
551 && (amim=lh_APP_INFO_retrieve(amih,&tmp)) != NULL)
552 {
553 m->app_info = amim;
554 amim->references++;
555 }
556
557 if ((mm=lh_MEM_insert(mh, m)) != NULL)
558 {
559 /* Not good, but don't sweat it */
560 if (mm->app_info != NULL)
561 {
562 mm->app_info->references--;
563 }
564 OPENSSL_free(mm);
565 }
566 err:
567 MemCheck_on(); /* release MALLOC2 lock
568 * if num_disabled drops to 0 */
569 }
570 break;
571 }
572 return;
573 }
574
575void CRYPTO_dbg_free(void *addr, int before_p)
576 {
577 MEM m,*mp;
578
579 switch(before_p)
580 {
581 case 0:
582 if (addr == NULL)
583 break;
584
585 if (is_MemCheck_on() && (mh != NULL))
586 {
587 MemCheck_off(); /* make sure we hold MALLOC2 lock */
588
589 m.addr=addr;
590 mp=lh_MEM_delete(mh,&m);
591 if (mp != NULL)
592 {
593#ifdef LEVITTE_DEBUG_MEM
594 fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] - 0x%p (%d)\n",
595 mp->order, mp->addr, mp->num);
596#endif
597 if (mp->app_info != NULL)
598 app_info_free(mp->app_info);
599 OPENSSL_free(mp);
600 }
601
602 MemCheck_on(); /* release MALLOC2 lock
603 * if num_disabled drops to 0 */
604 }
605 break;
606 case 1:
607 break;
608 }
609 }
610
611void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
612 const char *file, int line, int before_p)
613 {
614 MEM m,*mp;
615
616#ifdef LEVITTE_DEBUG_MEM
617 fprintf(stderr, "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n",
618 addr1, addr2, num, file, line, before_p);
619#endif
620
621 switch(before_p)
622 {
623 case 0:
624 break;
625 case 1:
626 if (addr2 == NULL)
627 break;
628
629 if (addr1 == NULL)
630 {
631 CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p);
632 break;
633 }
634
635 if (is_MemCheck_on())
636 {
637 MemCheck_off(); /* make sure we hold MALLOC2 lock */
638
639 m.addr=addr1;
640 mp=lh_MEM_delete(mh,&m);
641 if (mp != NULL)
642 {
643#ifdef LEVITTE_DEBUG_MEM
644 fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] * 0x%p (%d) -> 0x%p (%d)\n",
645 mp->order,
646 mp->addr, mp->num,
647 addr2, num);
648#endif
649 mp->addr=addr2;
650 mp->num=num;
651 (void)lh_MEM_insert(mh,mp);
652 }
653
654 MemCheck_on(); /* release MALLOC2 lock
655 * if num_disabled drops to 0 */
656 }
657 break;
658 }
659 return;
660 }
661
662
663typedef struct mem_leak_st
664 {
665 BIO *bio;
666 int chunks;
667 long bytes;
668 } MEM_LEAK;
669
Kinson Chik2cd211f2011-07-27 19:27:35 -0700670#ifndef LK_NO_TIME
Kinson Chika8fa74c2011-07-29 11:33:41 -0700671static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l)
672 {
673 char buf[1024];
674 char *bufp = buf;
675 APP_INFO *amip;
676 int ami_cnt;
677 struct tm *lcl = NULL;
678 CRYPTO_THREADID ti;
679
680#define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf))
681
682 if(m->addr == (char *)l->bio)
683 return;
684
685 if (options & V_CRYPTO_MDEBUG_TIME)
686 {
687 lcl = localtime(&m->time);
688
689 BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ",
690 lcl->tm_hour,lcl->tm_min,lcl->tm_sec);
691 bufp += strlen(bufp);
692 }
693
694 BIO_snprintf(bufp, BUF_REMAIN, "%5lu file=%s, line=%d, ",
695 m->order,m->file,m->line);
696 bufp += strlen(bufp);
697
698 if (options & V_CRYPTO_MDEBUG_THREAD)
699 {
700 BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ",
701 CRYPTO_THREADID_hash(&m->threadid));
702 bufp += strlen(bufp);
703 }
704
705 BIO_snprintf(bufp, BUF_REMAIN, "number=%d, address=%08lX\n",
706 m->num,(unsigned long)m->addr);
707 bufp += strlen(bufp);
708
709 BIO_puts(l->bio,buf);
710
711 l->chunks++;
712 l->bytes+=m->num;
713
714 amip=m->app_info;
715 ami_cnt=0;
716 if (!amip)
717 return;
718 CRYPTO_THREADID_cpy(&ti, &amip->threadid);
719
720 do
721 {
722 int buf_len;
723 int info_len;
724
725 ami_cnt++;
726 memset(buf,'>',ami_cnt);
727 BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt,
728 " thread=%lu, file=%s, line=%d, info=\"",
729 CRYPTO_THREADID_hash(&amip->threadid), amip->file,
730 amip->line);
731 buf_len=strlen(buf);
732 info_len=strlen(amip->info);
733 if (128 - buf_len - 3 < info_len)
734 {
735 memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
736 buf_len = 128 - 3;
737 }
738 else
739 {
740 BUF_strlcpy(buf + buf_len, amip->info,
741 sizeof buf - buf_len);
742 buf_len = strlen(buf);
743 }
744 BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n");
745
746 BIO_puts(l->bio,buf);
747
748 amip = amip->next;
749 }
750 while(amip && !CRYPTO_THREADID_cmp(&amip->threadid, &ti));
751
752#ifdef LEVITTE_DEBUG_MEM
753 if (amip)
754 {
755 fprintf(stderr, "Thread switch detected in backtrace!!!!\n");
756 abort();
757 }
758#endif
759 }
Unnati Gandhieef3dbf2014-07-17 14:45:43 +0530760#else
761static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l)
762{
763}
Kinson Chik2cd211f2011-07-27 19:27:35 -0700764#endif
Kinson Chika8fa74c2011-07-29 11:33:41 -0700765
766static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM, MEM_LEAK)
767
768void CRYPTO_mem_leaks(BIO *b)
769 {
770 MEM_LEAK ml;
771
772 if (mh == NULL && amih == NULL)
773 return;
774
775 MemCheck_off(); /* obtain MALLOC2 lock */
776
777 ml.bio=b;
778 ml.bytes=0;
779 ml.chunks=0;
780 if (mh != NULL)
781 lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak), MEM_LEAK,
782 &ml);
783 if (ml.chunks != 0)
784 {
785 BIO_printf(b,"%ld bytes leaked in %d chunks\n",
786 ml.bytes,ml.chunks);
787#ifdef CRYPTO_MDEBUG_ABORT
788 abort();
789#endif
790 }
791 else
792 {
793 /* Make sure that, if we found no leaks, memory-leak debugging itself
794 * does not introduce memory leaks (which might irritate
795 * external debugging tools).
796 * (When someone enables leak checking, but does not call
797 * this function, we declare it to be their fault.)
798 *
799 * XXX This should be in CRYPTO_mem_leaks_cb,
800 * and CRYPTO_mem_leaks should be implemented by
801 * using CRYPTO_mem_leaks_cb.
802 * (Also there should be a variant of lh_doall_arg
803 * that takes a function pointer instead of a void *;
804 * this would obviate the ugly and illegal
805 * void_fn_to_char kludge in CRYPTO_mem_leaks_cb.
806 * Otherwise the code police will come and get us.)
807 */
808 int old_mh_mode;
809
810 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
811
812 /* avoid deadlock when lh_free() uses CRYPTO_dbg_free(),
813 * which uses CRYPTO_is_mem_check_on */
814 old_mh_mode = mh_mode;
815 mh_mode = CRYPTO_MEM_CHECK_OFF;
816
817 if (mh != NULL)
818 {
819 lh_MEM_free(mh);
820 mh = NULL;
821 }
822 if (amih != NULL)
823 {
824 if (lh_APP_INFO_num_items(amih) == 0)
825 {
826 lh_APP_INFO_free(amih);
827 amih = NULL;
828 }
829 }
830
831 mh_mode = old_mh_mode;
832 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
833 }
834 MemCheck_on(); /* release MALLOC2 lock */
835 }
836
837#ifndef OPENSSL_NO_FP_API
838void CRYPTO_mem_leaks_fp(FILE *fp)
839 {
840 BIO *b;
841
842 if (mh == NULL) return;
843 /* Need to turn off memory checking when allocated BIOs ... especially
844 * as we're creating them at a time when we're trying to check we've not
845 * left anything un-free()'d!! */
846 MemCheck_off();
847 b = BIO_new(BIO_s_file());
848 MemCheck_on();
849 if(!b) return;
850 BIO_set_fp(b,fp,BIO_NOCLOSE);
851 CRYPTO_mem_leaks(b);
852 BIO_free(b);
853 }
854#endif
855
856
857
858/* FIXME: We really don't allow much to the callback. For example, it has
859 no chance of reaching the info stack for the item it processes. Should
860 it really be this way? -- Richard Levitte */
861/* NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside crypto.h
862 * If this code is restructured, remove the callback type if it is no longer
863 * needed. -- Geoff Thorpe */
864
865/* Can't pass CRYPTO_MEM_LEAK_CB directly to lh_MEM_doall_arg because it
866 * is a function pointer and conversion to void * is prohibited. Instead
867 * pass its address
868 */
869
870typedef CRYPTO_MEM_LEAK_CB *PCRYPTO_MEM_LEAK_CB;
871
872static void cb_leak_doall_arg(const MEM *m, PCRYPTO_MEM_LEAK_CB *cb)
873 {
874 (*cb)(m->order,m->file,m->line,m->num,m->addr);
875 }
876
877static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM, PCRYPTO_MEM_LEAK_CB)
878
879void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
880 {
881 if (mh == NULL) return;
882 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
883 lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), PCRYPTO_MEM_LEAK_CB,
884 &cb);
885 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
886 }