Did a 'make errors' to update asn1 error codes now typo is fixed
[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 "buffer.h"
62 #include "bio.h"
63 #include "lhash.h"
64 #include "cryptlib.h"
65
66 #ifdef CRYPTO_MDEBUG
67 static int mh_mode=CRYPTO_MEM_CHECK_ON;
68 #else
69 static int mh_mode=CRYPTO_MEM_CHECK_OFF;
70 #endif
71 static unsigned long order=0;
72
73 static LHASH *mh=NULL;
74
75 typedef struct mem_st
76         {
77         char *addr;
78         int num;
79         char *file;
80         int line;
81         unsigned long order;
82         } MEM;
83
84 int CRYPTO_mem_ctrl(mode)
85 int mode;
86         {
87         int ret=mh_mode;
88
89         CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
90         switch (mode)
91                 {
92         case CRYPTO_MEM_CHECK_ON:
93                 mh_mode|=CRYPTO_MEM_CHECK_ON;
94                 break;
95         case CRYPTO_MEM_CHECK_OFF:
96                 mh_mode&= ~CRYPTO_MEM_CHECK_ON;
97                 break;
98         case CRYPTO_MEM_CHECK_DISABLE:
99                 mh_mode&= ~CRYPTO_MEM_CHECK_ENABLE;
100                 break;
101         case CRYPTO_MEM_CHECK_ENABLE:
102                 if (mh_mode&CRYPTO_MEM_CHECK_ON)
103                         mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
104                 break;
105         default:
106                 break;
107                 }
108         CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
109         return(ret);
110         }
111
112 static int mem_cmp(a,b)
113 MEM *a,*b;
114         {
115         return(a->addr - b->addr);
116         }
117
118 static unsigned long mem_hash(a)
119 MEM *a;
120         {
121         unsigned long ret;
122
123         ret=(unsigned long)a->addr;
124
125         ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
126         return(ret);
127         }
128
129 static char *(*malloc_locked_func)()=(char *(*)())malloc;
130 static void (*free_locked_func)()=(void (*)())free;
131 static char *(*malloc_func)()=  (char *(*)())malloc;
132 static char *(*realloc_func)()= (char *(*)())realloc;
133 static void (*free_func)()=     (void (*)())free;
134
135 void CRYPTO_set_mem_functions(m,r,f)
136 char *(*m)();
137 char *(*r)();
138 void (*f)();
139         {
140         if ((m == NULL) || (r == NULL) || (f == NULL)) return;
141         malloc_func=m;
142         realloc_func=r;
143         free_func=f;
144         malloc_locked_func=m;
145         free_locked_func=f;
146         }
147
148 void CRYPTO_set_locked_mem_functions(m,f)
149 char *(*m)();
150 void (*f)();
151         {
152         if ((m == NULL) || (f == NULL)) return;
153         malloc_locked_func=m;
154         free_locked_func=f;
155         }
156
157 void CRYPTO_get_mem_functions(m,r,f)
158 char *(**m)();
159 char *(**r)();
160 void (**f)();
161         {
162         if (m != NULL) *m=malloc_func;
163         if (r != NULL) *r=realloc_func;
164         if (f != NULL) *f=free_func;
165         }
166
167 void CRYPTO_get_locked_mem_functions(m,f)
168 char *(**m)();
169 void (**f)();
170         {
171         if (m != NULL) *m=malloc_locked_func;
172         if (f != NULL) *f=free_locked_func;
173         }
174
175 char *CRYPTO_malloc_locked(num)
176 int num;
177         {
178         return(malloc_locked_func(num));
179         }
180
181 void CRYPTO_free_locked(str)
182 char *str;
183         {
184         free_locked_func(str);
185         }
186
187 char *CRYPTO_malloc(num)
188 int num;
189         {
190         return(malloc_func(num));
191         }
192
193 char *CRYPTO_realloc(str,num)
194 char *str;
195 int num;
196         {
197         return(realloc_func(str,num));
198         }
199
200 void CRYPTO_free(str)
201 char *str;
202         {
203         free_func(str);
204         }
205
206 static unsigned long break_order_num=0;
207 char *CRYPTO_dbg_malloc(num,file,line)
208 int num;
209 char *file;
210 int line;
211         {
212         char *ret;
213         MEM *m,*mm;
214
215         if ((ret=malloc_func(num)) == NULL)
216                 return(NULL);
217
218         if (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
219                 {
220                 MemCheck_off();
221                 if ((m=(MEM *)Malloc(sizeof(MEM))) == NULL)
222                         {
223                         Free(ret);
224                         MemCheck_on();
225                         return(NULL);
226                         }
227                 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
228                 if (mh == NULL)
229                         {
230                         if ((mh=lh_new(mem_hash,mem_cmp)) == NULL)
231                                 {
232                                 Free(ret);
233                                 Free(m);
234                                 ret=NULL;
235                                 goto err;
236                                 }
237                         }
238
239                 m->addr=ret;
240                 m->file=file;
241                 m->line=line;
242                 m->num=num;
243                 if (order == break_order_num)
244                         {
245                         /* BREAK HERE */
246                         m->order=order;
247                         }
248                 m->order=order++;
249                 if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL)
250                         {
251                         /* Not good, but don't sweat it */
252                         Free(mm);
253                         }
254 err:
255                 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
256                 MemCheck_on();
257                 }
258         return(ret);
259         }
260
261 void CRYPTO_dbg_free(addr)
262 char *addr;
263         {
264         MEM m,*mp;
265
266         if ((mh_mode & CRYPTO_MEM_CHECK_ENABLE) && (mh != NULL))
267                 {
268                 MemCheck_off();
269                 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
270                 m.addr=addr;
271                 mp=(MEM *)lh_delete(mh,(char *)&m);
272                 if (mp != NULL)
273                         Free(mp);
274                 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
275                 MemCheck_on();
276                 }
277         free_func(addr);
278         }
279
280 char *CRYPTO_dbg_realloc(addr,num,file,line)
281 char *addr;
282 int num;
283 char *file;
284 int line;
285         {
286         char *ret;
287         MEM m,*mp;
288
289         ret=realloc_func(addr,num);
290         if (ret == addr) return(ret);
291
292         if (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
293                 {
294                 MemCheck_off();
295                 if (ret == NULL) return(NULL);
296                 m.addr=addr;
297                 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
298                 mp=(MEM *)lh_delete(mh,(char *)&m);
299                 if (mp != NULL)
300                         {
301                         mp->addr=ret;
302                         lh_insert(mh,(char *)mp);
303                         }
304                 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
305                 MemCheck_on();
306                 }
307         return(ret);
308         }
309
310 char *CRYPTO_remalloc(a,n)
311 char *a;
312 int n;
313         {
314         if (a != NULL) Free(a);
315         a=(char *)Malloc(n);
316         return(a);
317         }
318
319 char *CRYPTO_dbg_remalloc(a,n,file,line)
320 char *a;
321 int n;
322 char *file;
323 int line;
324         {
325         if (a != NULL) CRYPTO_dbg_free(a);
326         a=(char *)CRYPTO_dbg_malloc(n,file,line);
327         return(a);
328         }
329
330
331 typedef struct mem_leak_st
332         {
333         BIO *bio;
334         int chunks;
335         long bytes;
336         } MEM_LEAK;
337
338 static void print_leak(m,l)
339 MEM *m;
340 MEM_LEAK *l;
341         {
342         char buf[128];
343
344         if(m->addr == (char *)l->bio)
345             return;
346         sprintf(buf,"%5ld file=%s, line=%d, number=%d, address=%08lX\n",
347                 m->order,m->file,m->line,m->num,(long)m->addr);
348         BIO_puts(l->bio,buf);
349         l->chunks++;
350         l->bytes+=m->num;
351         }
352
353 void CRYPTO_mem_leaks(b)
354 BIO *b;
355         {
356         MEM_LEAK ml;
357         char buf[80];
358
359         if (mh == NULL) return;
360         ml.bio=b;
361         ml.bytes=0;
362         ml.chunks=0;
363         CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
364         lh_doall_arg(mh,(void (*)())print_leak,(char *)&ml);
365         CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
366         if (ml.chunks != 0)
367                 {
368                 sprintf(buf,"%ld bytes leaked in %d chunks\n",
369                         ml.bytes,ml.chunks);
370                 BIO_puts(b,buf);
371                 }
372
373 #if 0
374         lh_stats_bio(mh,b);
375         lh_node_stats_bio(mh,b);
376         lh_node_usage_stats_bio(mh,b);
377 #endif
378         }
379
380 static void (*mem_cb)()=NULL;
381
382 static void cb_leak(m,cb)
383 MEM *m;
384 char *cb;
385         {
386         void (*mem_callback)()=(void (*)())cb;
387         mem_callback(m->order,m->file,m->line,m->num,m->addr);
388         }
389
390 void CRYPTO_mem_leaks_cb(cb)
391 void (*cb)();
392         {
393         if (mh == NULL) return;
394         CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
395         mem_cb=cb;
396         lh_doall_arg(mh,(void (*)())cb_leak,(char *)mem_cb);
397         mem_cb=NULL;
398         CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
399         }
400
401 #ifndef NO_FP_API
402 void CRYPTO_mem_leaks_fp(fp)
403 FILE *fp;
404         {
405         BIO *b;
406
407         if (mh == NULL) return;
408         if ((b=BIO_new(BIO_s_file())) == NULL)
409                 return;
410         BIO_set_fp(b,fp,BIO_NOCLOSE);
411         CRYPTO_mem_leaks(b);
412         BIO_free(b);
413         }
414 #endif
415