Tomato 1.28
[tomato.git] / release / src / router / openssl / crypto / mem_dbg.c
blobef19d8f8448992b1687872780ca6bd2b3f942053
1 /* crypto/mem_dbg.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
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).
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.
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)"
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.
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.]
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <time.h>
62 #include <openssl/crypto.h>
63 #include <openssl/buffer.h>
64 #include <openssl/bio.h>
65 #include <openssl/lhash.h>
66 #include "cryptlib.h"
68 static int mh_mode=CRYPTO_MEM_CHECK_OFF;
69 /* The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE
70 * when the application asks for it (usually after library initialisation
71 * for which no book-keeping is desired).
73 * State CRYPTO_MEM_CHECK_ON exists only temporarily when the library
74 * thinks that certain allocations should not be checked (e.g. the data
75 * structures used for memory checking). It is not suitable as an initial
76 * state: the library will unexpectedly enable memory checking when it
77 * executes one of those sections that want to disable checking
78 * temporarily.
80 * State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes no sense whatsoever.
83 static unsigned long order = 0; /* number of memory requests */
84 static LHASH *mh=NULL; /* hash-table of memory requests (address as key);
85 * access requires MALLOC2 lock */
88 typedef struct app_mem_info_st
89 /* For application-defined information (static C-string `info')
90 * to be displayed in memory leak list.
91 * Each thread has its own stack. For applications, there is
92 * CRYPTO_push_info("...") to push an entry,
93 * CRYPTO_pop_info() to pop an entry,
94 * CRYPTO_remove_all_info() to pop all entries.
97 unsigned long thread;
98 const char *file;
99 int line;
100 const char *info;
101 struct app_mem_info_st *next; /* tail of thread's stack */
102 int references;
103 } APP_INFO;
105 static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's
106 * that are at the top of their thread's stack
107 * (with `thread' as key);
108 * access requires MALLOC2 lock */
110 typedef struct mem_st
111 /* memory-block description */
113 void *addr;
114 int num;
115 const char *file;
116 int line;
117 unsigned long thread;
118 unsigned long order;
119 time_t time;
120 APP_INFO *app_info;
121 } MEM;
123 static long options = /* extra information to be recorded */
124 #if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL)
125 V_CRYPTO_MDEBUG_TIME |
126 #endif
127 #if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL)
128 V_CRYPTO_MDEBUG_THREAD |
129 #endif
133 static unsigned int num_disable = 0; /* num_disable > 0
134 * iff
135 * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE)
137 static unsigned long disabling_thread = 0; /* Valid iff num_disable > 0.
138 * CRYPTO_LOCK_MALLOC2 is locked
139 * exactly in this case (by the
140 * thread named in disabling_thread).
143 int CRYPTO_mem_ctrl(int mode)
145 int ret=mh_mode;
147 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
148 switch (mode)
150 /* for applications (not to be called while multiple threads
151 * use the library): */
152 case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */
153 mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
154 num_disable = 0;
155 break;
156 case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
157 mh_mode = 0;
158 num_disable = 0; /* should be true *before* MemCheck_stop is used,
159 or there'll be a lot of confusion */
160 break;
162 /* switch off temporarily (for library-internal use): */
163 case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
164 if (mh_mode & CRYPTO_MEM_CHECK_ON)
166 if (!num_disable || (disabling_thread != CRYPTO_thread_id())) /* otherwise we already have the MALLOC2 lock */
168 /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while
169 * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if
170 * somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot release
171 * it because we block entry to this function).
172 * Give them a chance, first, and then claim the locks in
173 * appropriate order (long-time lock first).
175 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
176 /* Note that after we have waited for CRYPTO_LOCK_MALLOC2
177 * and CRYPTO_LOCK_MALLOC, we'll still be in the right
178 * "case" and "if" branch because MemCheck_start and
179 * MemCheck_stop may never be used while there are multiple
180 * OpenSSL threads. */
181 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
182 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
183 mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE;
184 disabling_thread=CRYPTO_thread_id();
186 num_disable++;
188 break;
189 case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */
190 if (mh_mode & CRYPTO_MEM_CHECK_ON)
192 if (num_disable) /* always true, or something is going wrong */
194 num_disable--;
195 if (num_disable == 0)
197 mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
198 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
202 break;
204 default:
205 break;
207 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
208 return(ret);
211 int CRYPTO_is_mem_check_on(void)
213 int ret = 0;
215 if (mh_mode & CRYPTO_MEM_CHECK_ON)
217 CRYPTO_r_lock(CRYPTO_LOCK_MALLOC);
219 ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
220 || (disabling_thread != CRYPTO_thread_id());
222 CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC);
224 return(ret);
228 void CRYPTO_dbg_set_options(long bits)
230 options = bits;
233 long CRYPTO_dbg_get_options(void)
235 return options;
238 static int mem_cmp(MEM *a, MEM *b)
240 return((char *)a->addr - (char *)b->addr);
243 static unsigned long mem_hash(MEM *a)
245 unsigned long ret;
247 ret=(unsigned long)a->addr;
249 ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
250 return(ret);
253 static int app_info_cmp(APP_INFO *a, APP_INFO *b)
255 return(a->thread != b->thread);
258 static unsigned long app_info_hash(APP_INFO *a)
260 unsigned long ret;
262 ret=(unsigned long)a->thread;
264 ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
265 return(ret);
268 static APP_INFO *pop_info()
270 APP_INFO tmp;
271 APP_INFO *ret = NULL;
273 if (amih != NULL)
275 tmp.thread=CRYPTO_thread_id();
276 if ((ret=(APP_INFO *)lh_delete(amih,&tmp)) != NULL)
278 APP_INFO *next=ret->next;
280 if (next != NULL)
282 next->references++;
283 lh_insert(amih,(char *)next);
285 #ifdef LEVITTE_DEBUG
286 if (ret->thread != tmp.thread)
288 fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
289 ret->thread, tmp.thread);
290 abort();
292 #endif
293 if (--(ret->references) <= 0)
295 ret->next = NULL;
296 if (next != NULL)
297 next->references--;
298 OPENSSL_free(ret);
302 return(ret);
305 int CRYPTO_push_info_(const char *info, const char *file, int line)
307 APP_INFO *ami, *amim;
308 int ret=0;
310 if (is_MemCheck_on())
312 MemCheck_off(); /* obtain MALLOC2 lock */
314 if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL)
316 ret=0;
317 goto err;
319 if (amih == NULL)
321 if ((amih=lh_new(app_info_hash,app_info_cmp)) == NULL)
323 OPENSSL_free(ami);
324 ret=0;
325 goto err;
329 ami->thread=CRYPTO_thread_id();
330 ami->file=file;
331 ami->line=line;
332 ami->info=info;
333 ami->references=1;
334 ami->next=NULL;
336 if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL)
338 #ifdef LEVITTE_DEBUG
339 if (ami->thread != amim->thread)
341 fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
342 amim->thread, ami->thread);
343 abort();
345 #endif
346 ami->next=amim;
348 err:
349 MemCheck_on(); /* release MALLOC2 lock */
352 return(ret);
355 int CRYPTO_pop_info(void)
357 int ret=0;
359 if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */
361 MemCheck_off(); /* obtain MALLOC2 lock */
363 ret=(pop_info() != NULL);
365 MemCheck_on(); /* release MALLOC2 lock */
367 return(ret);
370 int CRYPTO_remove_all_info(void)
372 int ret=0;
374 if (is_MemCheck_on()) /* _must_ be true */
376 MemCheck_off(); /* obtain MALLOC2 lock */
378 while(pop_info() != NULL)
379 ret++;
381 MemCheck_on(); /* release MALLOC2 lock */
383 return(ret);
387 static unsigned long break_order_num=0;
388 void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
389 int before_p)
391 MEM *m,*mm;
392 APP_INFO tmp,*amim;
394 switch(before_p & 127)
396 case 0:
397 break;
398 case 1:
399 if (addr == NULL)
400 break;
402 if (is_MemCheck_on())
404 MemCheck_off(); /* make sure we hold MALLOC2 lock */
405 if ((m=(MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL)
407 OPENSSL_free(addr);
408 MemCheck_on(); /* release MALLOC2 lock
409 * if num_disabled drops to 0 */
410 return;
412 if (mh == NULL)
414 if ((mh=lh_new(mem_hash,mem_cmp)) == NULL)
416 OPENSSL_free(addr);
417 OPENSSL_free(m);
418 addr=NULL;
419 goto err;
423 m->addr=addr;
424 m->file=file;
425 m->line=line;
426 m->num=num;
427 if (options & V_CRYPTO_MDEBUG_THREAD)
428 m->thread=CRYPTO_thread_id();
429 else
430 m->thread=0;
432 if (order == break_order_num)
434 /* BREAK HERE */
435 m->order=order;
437 m->order=order++;
438 #ifdef LEVITTE_DEBUG
439 fprintf(stderr, "LEVITTE_DEBUG: [%5d] %c 0x%p (%d)\n",
440 m->order,
441 (before_p & 128) ? '*' : '+',
442 m->addr, m->num);
443 #endif
444 if (options & V_CRYPTO_MDEBUG_TIME)
445 m->time=time(NULL);
446 else
447 m->time=0;
449 tmp.thread=CRYPTO_thread_id();
450 m->app_info=NULL;
451 if (amih != NULL
452 && (amim=(APP_INFO *)lh_retrieve(amih,(char *)&tmp)) != NULL)
454 m->app_info = amim;
455 amim->references++;
458 if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL)
460 /* Not good, but don't sweat it */
461 if (mm->app_info != NULL)
463 mm->app_info->references--;
465 OPENSSL_free(mm);
467 err:
468 MemCheck_on(); /* release MALLOC2 lock
469 * if num_disabled drops to 0 */
471 break;
473 return;
476 void CRYPTO_dbg_free(void *addr, int before_p)
478 MEM m,*mp;
480 switch(before_p)
482 case 0:
483 if (addr == NULL)
484 break;
486 if (is_MemCheck_on() && (mh != NULL))
488 MemCheck_off(); /* make sure we hold MALLOC2 lock */
490 m.addr=addr;
491 mp=(MEM *)lh_delete(mh,(char *)&m);
492 if (mp != NULL)
494 #ifdef LEVITTE_DEBUG
495 fprintf(stderr, "LEVITTE_DEBUG: [%5d] - 0x%p (%d)\n",
496 mp->order, mp->addr, mp->num);
497 #endif
498 if (mp->app_info != NULL)
500 mp->app_info->references--;
502 OPENSSL_free(mp);
505 MemCheck_on(); /* release MALLOC2 lock
506 * if num_disabled drops to 0 */
508 break;
509 case 1:
510 break;
514 void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
515 const char *file, int line, int before_p)
517 MEM m,*mp;
519 #ifdef LEVITTE_DEBUG
520 fprintf(stderr, "LEVITTE_DEBUG: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n",
521 addr1, addr2, num, file, line, before_p);
522 #endif
524 switch(before_p)
526 case 0:
527 break;
528 case 1:
529 if (addr2 == NULL)
530 break;
532 if (addr1 == NULL)
534 CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p);
535 break;
538 if (is_MemCheck_on())
540 MemCheck_off(); /* make sure we hold MALLOC2 lock */
542 m.addr=addr1;
543 mp=(MEM *)lh_delete(mh,(char *)&m);
544 if (mp != NULL)
546 #ifdef LEVITTE_DEBUG
547 fprintf(stderr, "LEVITTE_DEBUG: [%5d] * 0x%p (%d) -> 0x%p (%d)\n",
548 mp->order,
549 mp->addr, mp->num,
550 addr2, num);
551 #endif
552 mp->addr=addr2;
553 mp->num=num;
554 lh_insert(mh,(char *)mp);
557 MemCheck_on(); /* release MALLOC2 lock
558 * if num_disabled drops to 0 */
560 break;
562 return;
566 typedef struct mem_leak_st
568 BIO *bio;
569 int chunks;
570 long bytes;
571 } MEM_LEAK;
573 static void print_leak(MEM *m, MEM_LEAK *l)
575 char buf[1024];
576 char *bufp = buf;
577 APP_INFO *amip;
578 int ami_cnt;
579 struct tm *lcl = NULL;
580 unsigned long ti;
582 if(m->addr == (char *)l->bio)
583 return;
585 if (options & V_CRYPTO_MDEBUG_TIME)
587 lcl = localtime(&m->time);
589 sprintf(bufp, "[%02d:%02d:%02d] ",
590 lcl->tm_hour,lcl->tm_min,lcl->tm_sec);
591 bufp += strlen(bufp);
594 sprintf(bufp, "%5lu file=%s, line=%d, ",
595 m->order,m->file,m->line);
596 bufp += strlen(bufp);
598 if (options & V_CRYPTO_MDEBUG_THREAD)
600 sprintf(bufp, "thread=%lu, ", m->thread);
601 bufp += strlen(bufp);
604 sprintf(bufp, "number=%d, address=%08lX\n",
605 m->num,(unsigned long)m->addr);
606 bufp += strlen(bufp);
608 BIO_puts(l->bio,buf);
610 l->chunks++;
611 l->bytes+=m->num;
613 amip=m->app_info;
614 ami_cnt=0;
615 if (!amip)
616 return;
617 ti=amip->thread;
621 int buf_len;
622 int info_len;
624 ami_cnt++;
625 memset(buf,'>',ami_cnt);
626 sprintf(buf + ami_cnt,
627 " thread=%lu, file=%s, line=%d, info=\"",
628 amip->thread, amip->file, amip->line);
629 buf_len=strlen(buf);
630 info_len=strlen(amip->info);
631 if (128 - buf_len - 3 < info_len)
633 memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
634 buf_len = 128 - 3;
636 else
638 strcpy(buf + buf_len, amip->info);
639 buf_len = strlen(buf);
641 sprintf(buf + buf_len, "\"\n");
643 BIO_puts(l->bio,buf);
645 amip = amip->next;
647 while(amip && amip->thread == ti);
649 #ifdef LEVITTE_DEBUG
650 if (amip)
652 fprintf(stderr, "Thread switch detected in backtrace!!!!\n");
653 abort();
655 #endif
658 void CRYPTO_mem_leaks(BIO *b)
660 MEM_LEAK ml;
661 char buf[80];
663 if (mh == NULL && amih == NULL)
664 return;
666 MemCheck_off(); /* obtain MALLOC2 lock */
668 ml.bio=b;
669 ml.bytes=0;
670 ml.chunks=0;
671 if (mh != NULL)
672 lh_doall_arg(mh,(void (*)())print_leak,(char *)&ml);
673 if (ml.chunks != 0)
675 sprintf(buf,"%ld bytes leaked in %d chunks\n",
676 ml.bytes,ml.chunks);
677 BIO_puts(b,buf);
679 else
681 /* Make sure that, if we found no leaks, memory-leak debugging itself
682 * does not introduce memory leaks (which might irritate
683 * external debugging tools).
684 * (When someone enables leak checking, but does not call
685 * this function, we declare it to be their fault.)
687 * XXX This should be in CRYPTO_mem_leaks_cb,
688 * and CRYPTO_mem_leaks should be implemented by
689 * using CRYPTO_mem_leaks_cb.
690 * (Also their should be a variant of lh_doall_arg
691 * that takes a function pointer instead of a void *;
692 * this would obviate the ugly and illegal
693 * void_fn_to_char kludge in CRYPTO_mem_leaks_cb.
694 * Otherwise the code police will come and get us.)
696 int old_mh_mode;
698 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
700 /* avoid deadlock when lh_free() uses CRYPTO_dbg_free(),
701 * which uses CRYPTO_is_mem_check_on */
702 old_mh_mode = mh_mode;
703 mh_mode = CRYPTO_MEM_CHECK_OFF;
705 if (mh != NULL)
707 lh_free(mh);
708 mh = NULL;
710 if (amih != NULL)
712 if (lh_num_items(amih) == 0)
714 lh_free(amih);
715 amih = NULL;
719 mh_mode = old_mh_mode;
720 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
722 MemCheck_on(); /* release MALLOC2 lock */
725 #ifndef NO_FP_API
726 void CRYPTO_mem_leaks_fp(FILE *fp)
728 BIO *b;
730 if (mh == NULL) return;
731 if ((b=BIO_new(BIO_s_file())) == NULL)
732 return;
733 BIO_set_fp(b,fp,BIO_NOCLOSE);
734 CRYPTO_mem_leaks(b);
735 BIO_free(b);
737 #endif
741 /* FIXME: We really don't allow much to the callback. For example, it has
742 no chance of reaching the info stack for the item it processes. Should
743 it really be this way? -- Richard Levitte */
744 static void cb_leak(MEM *m,
745 void (**cb)(unsigned long, const char *, int, int, void *))
747 (**cb)(m->order,m->file,m->line,m->num,m->addr);
750 void CRYPTO_mem_leaks_cb(void (*cb)(unsigned long, const char *, int, int, void *))
752 if (mh == NULL) return;
753 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
754 lh_doall_arg(mh,(void (*)())cb_leak,(void *)&cb);
755 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);