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