- Made sure some changed behavior is documented in CHANGES.
[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 #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"
67
68 /* State CRYPTO_MEM_CHECK_ON exists only temporarily when the library
69  * thinks that certain allocations should not be checked (e.g. the data
70  * structures used for memory checking).  It is not suitable as an initial
71  * state: the library will unexpectedly enable memory checking when it
72  * executes one of those sections that want to disable checking
73  * temporarily.
74  *
75  * State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes no sense whatsoever.
76  */
77 static int mh_mode=CRYPTO_MEM_CHECK_OFF;
78 static unsigned long disabling_thread = 0;
79
80
81 static unsigned long order=0;
82
83 static LHASH *amih=NULL;
84
85 typedef struct app_mem_info_st
86         {       
87         unsigned long thread;
88         const char *file;
89         int line;
90         const char *info;
91         struct app_mem_info_st *next;
92         int references;
93         } APP_INFO;
94
95 static LHASH *mh=NULL;
96
97 typedef struct mem_st
98         {
99         char *addr;
100         int num;
101         const char *file;
102         int line;
103         unsigned long thread;
104         unsigned long order;
105         time_t time;
106         APP_INFO *app_info;
107         } MEM;
108
109
110 #ifdef CRYPTO_MDEBUG_ALL
111 # ifndef CRYPTO_MDEBUG_TIME
112 #  define CRYPTO_MDEBUG_TIME
113 # endif
114 # ifndef CRYPTO_MDEBUG_THREAD
115 #  define CRYPTO_MDEBUG_THREAD
116 # endif
117 #endif
118
119 /* Get defaults that will depend on some macros defined elsewhere */
120 #ifdef CRYPTO_MDEBUG_TIME
121 #define DEF_V_CRYPTO_MDEBUG_TIME V_CRYPTO_MDEBUG_TIME
122 #else
123 #define DEF_V_CRYPTO_MDEBUG_TIME 0
124 #endif
125 #ifdef CRYPTO_MDEBUG_THREAD
126 #define DEF_V_CRYPTO_MDEBUG_THREAD V_CRYPTO_MDEBUG_THREAD
127 #else
128 #define DEF_V_CRYPTO_MDEBUG_THREAD 0
129 #endif
130
131 static int options = DEF_V_CRYPTO_MDEBUG_TIME | DEF_V_CRYPTO_MDEBUG_THREAD;
132
133
134 int CRYPTO_mem_ctrl(int mode)
135         {
136         int ret=mh_mode;
137
138         CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
139         switch (mode)
140                 {
141         /* for applications: */
142         case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */
143                 mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
144                 disabling_thread = 0;
145                 break;
146         case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
147                 mh_mode = 0;
148                 disabling_thread = 0;
149                 break;
150
151         /* switch off temporarily (for library-internal use): */
152         case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
153                 if (mh_mode & CRYPTO_MEM_CHECK_ON)
154                         {
155                         mh_mode&= ~CRYPTO_MEM_CHECK_ENABLE;
156                         if (disabling_thread != CRYPTO_thread_id()) /* otherwise we already have the MALLOC2 lock */
157                                 {
158                                 /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while
159                                  * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if
160                                  * somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot release it
161                                  * because we block entry to this function).
162                                  * Give them a chance, first, and then claim the locks in
163                                  * appropriate order (long-time lock first).
164                                  */
165                                 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
166                                 /* Note that after we have waited for CRYPTO_LOCK_MALLOC2
167                                  * and CRYPTO_LOCK_MALLOC, we'll still be in the right
168                                  * "case" and "if" branch because MemCheck_start and
169                                  * MemCheck_stop may never be used while there are multiple
170                                  * OpenSSL threads. */
171                                 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
172                                 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
173                                 disabling_thread=CRYPTO_thread_id();
174                                 }
175                         }
176                 break;
177         case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */
178                 if (mh_mode & CRYPTO_MEM_CHECK_ON)
179                         {
180                         mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
181                         if (disabling_thread != 0)
182                                 {
183                                 disabling_thread=0;
184                                 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
185                                 }
186                         }
187                 break;
188
189         default:
190                 break;
191                 }
192         CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
193         return(ret);
194         }
195
196 int CRYPTO_mem_check_on(void)
197         {
198         int ret = 0;
199
200         if (mh_mode & CRYPTO_MEM_CHECK_ON)
201                 {
202                 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
203
204                 ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
205                         && disabling_thread != CRYPTO_thread_id();
206
207                 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
208                 }
209         return(ret);
210         }       
211
212
213 void CRYPTO_dbg_set_options(int bits)
214         {
215         options = bits;
216         }
217
218 int CRYPTO_dbg_get_options()
219         {
220         return options;
221         }
222
223 static int mem_cmp(MEM *a, MEM *b)
224         {
225         return(a->addr - b->addr);
226         }
227
228 static unsigned long mem_hash(MEM *a)
229         {
230         unsigned long ret;
231
232         ret=(unsigned long)a->addr;
233
234         ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
235         return(ret);
236         }
237
238 static int app_info_cmp(APP_INFO *a, APP_INFO *b)
239         {
240         return(a->thread - b->thread);
241         }
242
243 static unsigned long app_info_hash(APP_INFO *a)
244         {
245         unsigned long ret;
246
247         ret=(unsigned long)a->thread;
248
249         ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
250         return(ret);
251         }
252
253 static APP_INFO *remove_info()
254         {
255         APP_INFO tmp;
256         APP_INFO *ret = NULL;
257
258         if (amih != NULL)
259                 {
260                 tmp.thread=CRYPTO_thread_id();
261                 if ((ret=(APP_INFO *)lh_delete(amih,(char *)&tmp)) != NULL)
262                         {
263                         APP_INFO *next=ret->next;
264
265                         if (next != NULL)
266                                 {
267                                 next->references++;
268                                 lh_insert(amih,(char *)next);
269                                 }
270 #ifdef LEVITTE_DEBUG
271                         if (ret->thread != tmp.thread)
272                                 {
273                                 fprintf(stderr, "remove_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
274                                         ret->thread, tmp.thread);
275                                 abort();
276                                 }
277 #endif
278                         if (--(ret->references) <= 0)
279                                 {
280                                 ret->next = NULL;
281                                 if (next != NULL)
282                                         next->references--;
283                                 Free(ret);
284                                 }
285                         }
286                 }
287         return(ret);
288         }
289
290 int CRYPTO_add_info(const char *file, int line, const char *info)
291         {
292         APP_INFO *ami, *amim;
293         int ret=0;
294
295         if (is_MemCheck_on())
296                 {
297                 MemCheck_off();
298
299                 if ((ami = (APP_INFO *)Malloc(sizeof(APP_INFO))) == NULL)
300                         {
301                         ret=0;
302                         goto err;
303                         }
304                 if (amih == NULL)
305                         {
306                         if ((amih=lh_new(app_info_hash,app_info_cmp)) == NULL)
307                                 {
308                                 Free(ami);
309                                 ret=0;
310                                 goto err;
311                                 }
312                         }
313
314                 ami->thread=CRYPTO_thread_id();
315                 ami->file=file;
316                 ami->line=line;
317                 ami->info=info;
318                 ami->references=1;
319                 ami->next=NULL;
320
321                 if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL)
322                         {
323 #ifdef LEVITTE_DEBUG
324                         if (ami->thread != amim->thread)
325                                 {
326                                 fprintf(stderr, "CRYPTO_add_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
327                                         amim->thread, ami->thread);
328                                 abort();
329                                 }
330 #endif
331                         ami->next=amim;
332                         }
333  err:
334                 MemCheck_on();
335                 }
336
337         return(ret);
338         }
339
340 int CRYPTO_remove_info(void)
341         {
342         int ret=0;
343
344         if (is_MemCheck_on())
345                 {
346                 MemCheck_off();
347
348                 ret=(remove_info() != NULL);
349
350                 MemCheck_on();
351                 }
352         return(ret);
353         }
354
355 int CRYPTO_remove_all_info(void)
356         {
357         int ret=0;
358
359         if (is_MemCheck_on())
360                 {
361                 MemCheck_off();
362
363                 while(remove_info() != NULL)
364                         ret++;
365
366                 MemCheck_on();
367                 }
368         return(ret);
369         }
370
371
372 static unsigned long break_order_num=0;
373 void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
374         int before_p)
375         {
376         MEM *m,*mm;
377         APP_INFO tmp,*amim;
378
379         switch(before_p & 127)
380                 {
381         case 0:
382                 break;
383         case 1:
384                 if (addr == NULL)
385                         break;
386
387                 if (is_MemCheck_on())
388                         {
389                         MemCheck_off();
390                         if ((m=(MEM *)Malloc(sizeof(MEM))) == NULL)
391                                 {
392                                 Free(addr);
393                                 MemCheck_on();
394                                 return;
395                                 }
396                         if (mh == NULL)
397                                 {
398                                 if ((mh=lh_new(mem_hash,mem_cmp)) == NULL)
399                                         {
400                                         Free(addr);
401                                         Free(m);
402                                         addr=NULL;
403                                         goto err;
404                                         }
405                                 }
406
407                         m->addr=addr;
408                         m->file=file;
409                         m->line=line;
410                         m->num=num;
411                         if (options & V_CRYPTO_MDEBUG_THREAD)
412                                 m->thread=CRYPTO_thread_id();
413                         else
414                                 m->thread=0;
415
416                         if (order == break_order_num)
417                                 {
418                                 /* BREAK HERE */
419                                 m->order=order;
420                                 }
421                         m->order=order++;
422 #ifdef LEVITTE_DEBUG
423                         fprintf(stderr, "LEVITTE_DEBUG: [%5d] %c 0x%p (%d)\n",
424                                 m->order,
425                                 (before_p & 128) ? '*' : '+',
426                                 m->addr, m->num);
427 #endif
428                         if (options & V_CRYPTO_MDEBUG_TIME)
429                                 m->time=time(NULL);
430                         else
431                                 m->time=0;
432
433                         tmp.thread=CRYPTO_thread_id();
434                         m->app_info=NULL;
435                         if (amih != NULL
436                                 && (amim=(APP_INFO *)lh_retrieve(amih,(char *)&tmp)) != NULL)
437                                 {
438                                 m->app_info = amim;
439                                 amim->references++;
440                                 }
441
442                         if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL)
443                                 {
444                                 /* Not good, but don't sweat it */
445                                 if (mm->app_info != NULL)
446                                         {
447                                         mm->app_info->references--;
448                                         }
449                                 Free(mm);
450                                 }
451                 err:
452                         MemCheck_on();
453                         }
454                 break;
455                 }
456         return;
457         }
458
459 void CRYPTO_dbg_free(void *addr, int before_p)
460         {
461         MEM m,*mp;
462
463         switch(before_p)
464                 {
465         case 0:
466                 if (addr == NULL)
467                         break;
468
469                 if (is_MemCheck_on() && (mh != NULL))
470                         {
471                         MemCheck_off();
472
473                         m.addr=addr;
474                         mp=(MEM *)lh_delete(mh,(char *)&m);
475                         if (mp != NULL)
476                                 {
477 #ifdef LEVITTE_DEBUG
478                         fprintf(stderr, "LEVITTE_DEBUG: [%5d] - 0x%p (%d)\n",
479                                 mp->order, mp->addr, mp->num);
480 #endif
481                                 if (mp->app_info != NULL)
482                                         {
483                                         mp->app_info->references--;
484                                         }
485                                 Free(mp);
486                                 }
487
488                         MemCheck_on();
489                         }
490                 break;
491         case 1:
492                 break;
493                 }
494         }
495
496 void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
497         const char *file, int line, int before_p)
498         {
499         MEM m,*mp;
500
501 #ifdef LEVITTE_DEBUG
502         fprintf(stderr, "LEVITTE_DEBUG: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n",
503                 addr1, addr2, num, file, line, before_p);
504 #endif
505
506         switch(before_p)
507                 {
508         case 0:
509                 break;
510         case 1:
511                 if (addr2 == NULL)
512                         break;
513
514                 if (addr1 == NULL)
515                         {
516                         CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p);
517                         break;
518                         }
519
520                 if (is_MemCheck_on())
521                         {
522                         MemCheck_off();
523
524                         m.addr=addr1;
525                         mp=(MEM *)lh_delete(mh,(char *)&m);
526                         if (mp != NULL)
527                                 {
528 #ifdef LEVITTE_DEBUG
529                                 fprintf(stderr, "LEVITTE_DEBUG: [%5d] * 0x%p (%d) -> 0x%p (%d)\n",
530                                         mp->order,
531                                         mp->addr, mp->num,
532                                         addr2, num);
533 #endif
534                                 mp->addr=addr2;
535                                 mp->num=num;
536                                 lh_insert(mh,(char *)mp);
537                                 }
538
539                         MemCheck_on();
540                         }
541                 break;
542                 }
543         return;
544         }
545
546
547 typedef struct mem_leak_st
548         {
549         BIO *bio;
550         int chunks;
551         long bytes;
552         } MEM_LEAK;
553
554 static void print_leak(MEM *m, MEM_LEAK *l)
555         {
556         char buf[1024];
557         char *bufp = buf;
558         APP_INFO *amip;
559         int ami_cnt;
560         struct tm *lcl = NULL;
561         unsigned long ti;
562
563         if(m->addr == (char *)l->bio)
564             return;
565
566         if (options & V_CRYPTO_MDEBUG_TIME)
567                 {
568                 lcl = localtime(&m->time);
569         
570                 sprintf(bufp, "[%02d:%02d:%02d] ",
571                         lcl->tm_hour,lcl->tm_min,lcl->tm_sec);
572                 bufp += strlen(bufp);
573                 }
574
575         sprintf(bufp, "%5lu file=%s, line=%d, ",
576                 m->order,m->file,m->line);
577         bufp += strlen(bufp);
578
579         if (options & V_CRYPTO_MDEBUG_THREAD)
580                 {
581                 sprintf(bufp, "thread=%lu, ", m->thread);
582                 bufp += strlen(bufp);
583                 }
584
585         sprintf(bufp, "number=%d, address=%08lX\n",
586                 m->num,(unsigned long)m->addr);
587         bufp += strlen(bufp);
588
589         BIO_puts(l->bio,buf);
590         
591         l->chunks++;
592         l->bytes+=m->num;
593
594         amip=m->app_info;
595         ami_cnt=0;
596         if (amip)
597                 ti=amip->thread;
598         while(amip && amip->thread == ti)
599                 {
600                 int buf_len;
601                 int info_len;
602
603                 ami_cnt++;
604                 memset(buf,'>',ami_cnt);
605                 sprintf(buf + ami_cnt,
606                         "thread=%lu, file=%s, line=%d, info=\"",
607                         amip->thread, amip->file, amip->line);
608                 buf_len=strlen(buf);
609                 info_len=strlen(amip->info);
610                 if (128 - buf_len - 3 < info_len)
611                         {
612                         memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
613                         buf_len = 128 - 3;
614                         }
615                 else
616                         {
617                         strcpy(buf + buf_len, amip->info);
618                         buf_len = strlen(buf);
619                         }
620                 sprintf(buf + buf_len, "\"\n");
621                 
622                 BIO_puts(l->bio,buf);
623
624                 amip = amip->next;
625                 }
626 #ifdef LEVITTE_DEBUG
627         if (amip)
628                 {
629                 fprintf(stderr, "Thread switch detected i backtrace!!!!\n");
630                 abort();
631                 }
632 #endif
633         }
634
635 void CRYPTO_mem_leaks(BIO *b)
636         {
637         MEM_LEAK ml;
638         char buf[80];
639
640         if (mh == NULL) return;
641         ml.bio=b;
642         ml.bytes=0;
643         ml.chunks=0;
644         CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
645         lh_doall_arg(mh,(void (*)())print_leak,(char *)&ml);
646         CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
647         if (ml.chunks != 0)
648                 {
649                 sprintf(buf,"%ld bytes leaked in %d chunks\n",
650                         ml.bytes,ml.chunks);
651                 BIO_puts(b,buf);
652                 }
653
654 #if 0
655         lh_stats_bio(mh,b);
656         lh_node_stats_bio(mh,b);
657         lh_node_usage_stats_bio(mh,b);
658 #endif
659         }
660
661 static void (*mem_cb)()=NULL;
662
663 static void cb_leak(MEM *m, char *cb)
664         {
665         void (*mem_callback)()=(void (*)())cb;
666         mem_callback(m->order,m->file,m->line,m->num,m->addr);
667         }
668
669 void CRYPTO_mem_leaks_cb(void (*cb)())
670         {
671         if (mh == NULL) return;
672         CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
673         mem_cb=cb;
674         lh_doall_arg(mh,(void (*)())cb_leak,(char *)mem_cb);
675         mem_cb=NULL;
676         CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
677         }
678
679 #ifndef NO_FP_API
680 void CRYPTO_mem_leaks_fp(FILE *fp)
681         {
682         BIO *b;
683
684         if (mh == NULL) return;
685         if ((b=BIO_new(BIO_s_file())) == NULL)
686                 return;
687         BIO_set_fp(b,fp,BIO_NOCLOSE);
688         CRYPTO_mem_leaks(b);
689         BIO_free(b);
690         }
691 #endif
692