summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/mem.c')
-rw-r--r--src/lib/libcrypto/mem.c432
1 files changed, 132 insertions, 300 deletions
diff --git a/src/lib/libcrypto/mem.c b/src/lib/libcrypto/mem.c
index 61fc1e184e..5a661e5f45 100644
--- a/src/lib/libcrypto/mem.c
+++ b/src/lib/libcrypto/mem.c
@@ -59,371 +59,203 @@
59#include <stdio.h> 59#include <stdio.h>
60#include <stdlib.h> 60#include <stdlib.h>
61#include <openssl/crypto.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" 62#include "cryptlib.h"
69 63
70/* #ifdef CRYPTO_MDEBUG */
71/* static int mh_mode=CRYPTO_MEM_CHECK_ON; */
72/* #else */
73static int mh_mode=CRYPTO_MEM_CHECK_OFF;
74/* #endif */
75/* State CRYPTO_MEM_CHECK_ON exists only temporarily when the library
76 * thinks that certain allocations should not be checked (e.g. the data
77 * structures used for memory checking). It is not suitable as an initial
78 * state: the library will unexpectedly enable memory checking when it
79 * executes one of those sections that want to disable checking
80 * temporarily.
81 *
82 * State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes no sense whatsoever.
83 */
84
85static unsigned long order=0;
86
87static LHASH *mh=NULL;
88 64
89typedef struct mem_st 65static int allow_customize = 1; /* we provide flexible functions for */
90 { 66static int allow_customize_debug = 1;/* exchanging memory-related functions at
91 char *addr; 67 * run-time, but this must be done
92 int num; 68 * before any blocks are actually
93 const char *file; 69 * allocated; or we'll run into huge
94 int line; 70 * problems when malloc/free pairs
95#ifdef CRYPTO_MDEBUG_THREAD 71 * don't match etc. */
96 unsigned long thread; 72
73/* may be changed as long as `allow_customize' is set */
74static void *(*malloc_locked_func)(size_t) = malloc;
75static void (*free_locked_func)(void *) = free;
76static void *(*malloc_func)(size_t) = malloc;
77static void *(*realloc_func)(void *, size_t)= realloc;
78static void (*free_func)(void *) = free;
79
80/* may be changed as long as `allow_customize_debug' is set */
81/* XXX use correct function pointer types */
82#ifdef CRYPTO_MDEBUG
83 /* use default functions from mem_dbg.c */
84 static void (*malloc_debug_func)()= (void (*)())CRYPTO_dbg_malloc;
85 static void (*realloc_debug_func)()= (void (*)())CRYPTO_dbg_realloc;
86 static void (*free_debug_func)()= (void (*)())CRYPTO_dbg_free;
87 static void (*set_debug_options_func)()= (void (*)())CRYPTO_dbg_set_options;
88 static long (*get_debug_options_func)()= (long (*)())CRYPTO_dbg_get_options;
89#else
90 /* applications can use CRYPTO_malloc_debug_init() to select above case
91 * at run-time */
92 static void (*malloc_debug_func)()= NULL;
93 static void (*realloc_debug_func)()= NULL;
94 static void (*free_debug_func)()= NULL;
95 static void (*set_debug_options_func)()= NULL;
96 static long (*get_debug_options_func)()= NULL;
97#endif 97#endif
98 unsigned long order;
99#ifdef CRYPTO_MDEBUG_TIME
100 time_t time;
101#endif
102 } MEM;
103
104int CRYPTO_mem_ctrl(int mode)
105 {
106 int ret=mh_mode;
107
108 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
109 switch (mode)
110 {
111 /* for applications: */
112 case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */
113 mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
114 break;
115 case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
116 mh_mode = 0;
117 break;
118 98
119 /* switch off temporarily (for library-internal use): */
120 case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
121 mh_mode&= ~CRYPTO_MEM_CHECK_ENABLE;
122 break;
123 case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */
124 if (mh_mode&CRYPTO_MEM_CHECK_ON)
125 mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
126 break;
127 99
128 default: 100int CRYPTO_set_mem_functions(void *(*m)(size_t), void *(*r)(void *, size_t),
129 break; 101 void (*f)(void *))
130 }
131 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
132 return(ret);
133 }
134
135static int mem_cmp(MEM *a, MEM *b)
136 {
137 return(a->addr - b->addr);
138 }
139
140static unsigned long mem_hash(MEM *a)
141 { 102 {
142 unsigned long ret; 103 if (!allow_customize)
143 104 return 0;
144 ret=(unsigned long)a->addr; 105 if ((m == NULL) || (r == NULL) || (f == NULL))
145 106 return 0;
146 ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
147 return(ret);
148 }
149
150static char *(*malloc_locked_func)()=(char *(*)())malloc;
151static void (*free_locked_func)()=(void (*)())free;
152static char *(*malloc_func)()= (char *(*)())malloc;
153static char *(*realloc_func)()= (char *(*)())realloc;
154static void (*free_func)()= (void (*)())free;
155
156void CRYPTO_set_mem_functions(char *(*m)(), char *(*r)(), void (*f)())
157 {
158 if ((m == NULL) || (r == NULL) || (f == NULL)) return;
159 malloc_func=m; 107 malloc_func=m;
160 realloc_func=r; 108 realloc_func=r;
161 free_func=f; 109 free_func=f;
162 malloc_locked_func=m; 110 malloc_locked_func=m;
163 free_locked_func=f; 111 free_locked_func=f;
112 return 1;
164 } 113 }
165 114
166void CRYPTO_set_locked_mem_functions(char *(*m)(), void (*f)()) 115int CRYPTO_set_locked_mem_functions(void *(*m)(size_t), void (*f)(void *))
167 { 116 {
168 if ((m == NULL) || (f == NULL)) return; 117 if (!allow_customize)
118 return 0;
119 if ((m == NULL) || (f == NULL))
120 return 0;
169 malloc_locked_func=m; 121 malloc_locked_func=m;
170 free_locked_func=f; 122 free_locked_func=f;
123 return 1;
124 }
125
126int CRYPTO_set_mem_debug_functions(void (*m)(), void (*r)(), void (*f)(),void (*so)(),long (*go)())
127 {
128 if (!allow_customize_debug)
129 return 0;
130 malloc_debug_func=m;
131 realloc_debug_func=r;
132 free_debug_func=f;
133 set_debug_options_func=so;
134 get_debug_options_func=go;
135 return 1;
171 } 136 }
172 137
173void CRYPTO_get_mem_functions(char *(**m)(), char *(**r)(), void (**f)()) 138void CRYPTO_get_mem_functions(void *(**m)(size_t), void *(**r)(void *, size_t),
139 void (**f)(void *))
174 { 140 {
175 if (m != NULL) *m=malloc_func; 141 if (m != NULL) *m=malloc_func;
176 if (r != NULL) *r=realloc_func; 142 if (r != NULL) *r=realloc_func;
177 if (f != NULL) *f=free_func; 143 if (f != NULL) *f=free_func;
178 } 144 }
179 145
180void CRYPTO_get_locked_mem_functions(char *(**m)(), void (**f)()) 146void CRYPTO_get_locked_mem_functions(void *(**m)(size_t), void (**f)(void *))
181 { 147 {
182 if (m != NULL) *m=malloc_locked_func; 148 if (m != NULL) *m=malloc_locked_func;
183 if (f != NULL) *f=free_locked_func; 149 if (f != NULL) *f=free_locked_func;
184 } 150 }
185 151
186void *CRYPTO_malloc_locked(int num) 152void CRYPTO_get_mem_debug_functions(void (**m)(), void (**r)(), void (**f)(),void (**so)(),long (**go)())
187 { 153 {
188 return(malloc_locked_func(num)); 154 if (m != NULL) *m=malloc_debug_func;
155 if (r != NULL) *r=realloc_debug_func;
156 if (f != NULL) *f=free_debug_func;
157 if (so != NULL) *so=set_debug_options_func;
158 if (go != NULL) *go=get_debug_options_func;
189 } 159 }
190 160
191void CRYPTO_free_locked(void *str)
192 {
193 free_locked_func(str);
194 }
195 161
196void *CRYPTO_malloc(int num) 162void *CRYPTO_malloc_locked(int num, const char *file, int line)
197 { 163 {
198 return(malloc_func(num)); 164 char *ret = NULL;
199 }
200 165
201void *CRYPTO_realloc(void *str, int num) 166 allow_customize = 0;
202 { 167 if (malloc_debug_func != NULL)
203 return(realloc_func(str,num));
204 }
205
206void CRYPTO_free(void *str)
207 {
208 free_func(str);
209 }
210
211static unsigned long break_order_num=0;
212void *CRYPTO_dbg_malloc(int num, const char *file, int line)
213 {
214 char *ret;
215 MEM *m,*mm;
216
217 if ((ret=malloc_func(num)) == NULL)
218 return(NULL);
219
220 if (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
221 { 168 {
222 MemCheck_off(); 169 allow_customize_debug = 0;
223 if ((m=(MEM *)Malloc(sizeof(MEM))) == NULL) 170 malloc_debug_func(NULL, num, file, line, 0);
224 {
225 Free(ret);
226 MemCheck_on();
227 return(NULL);
228 }
229 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
230 if (mh == NULL)
231 {
232 if ((mh=lh_new(mem_hash,mem_cmp)) == NULL)
233 {
234 Free(ret);
235 Free(m);
236 ret=NULL;
237 goto err;
238 }
239 }
240
241 m->addr=ret;
242 m->file=file;
243 m->line=line;
244 m->num=num;
245#ifdef CRYPTO_MDEBUG_THREAD
246 m->thread=CRYPTO_thread_id();
247#endif
248 if (order == break_order_num)
249 {
250 /* BREAK HERE */
251 m->order=order;
252 }
253 m->order=order++;
254#ifdef CRYPTO_MDEBUG_TIME
255 m->time=time(NULL);
256#endif
257 if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL)
258 {
259 /* Not good, but don't sweat it */
260 Free(mm);
261 }
262err:
263 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
264 MemCheck_on();
265 } 171 }
266 return(ret); 172 ret = malloc_locked_func(num);
173#ifdef LEVITTE_DEBUG
174 fprintf(stderr, "LEVITTE_DEBUG: > 0x%p (%d)\n", ret, num);
175#endif
176 if (malloc_debug_func != NULL)
177 malloc_debug_func(ret, num, file, line, 1);
178
179 return ret;
267 } 180 }
268 181
269void CRYPTO_dbg_free(void *addr) 182void CRYPTO_free_locked(void *str)
270 { 183 {
271 MEM m,*mp; 184 if (free_debug_func != NULL)
272 185 free_debug_func(str, 0);
273 if ((mh_mode & CRYPTO_MEM_CHECK_ENABLE) && (mh != NULL)) 186#ifdef LEVITTE_DEBUG
274 { 187 fprintf(stderr, "LEVITTE_DEBUG: < 0x%p\n", str);
275 MemCheck_off(); 188#endif
276 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); 189 free_locked_func(str);
277 m.addr=addr; 190 if (free_debug_func != NULL)
278 mp=(MEM *)lh_delete(mh,(char *)&m); 191 free_debug_func(NULL, 1);
279 if (mp != NULL)
280 Free(mp);
281 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
282 MemCheck_on();
283 }
284 free_func(addr);
285 } 192 }
286 193
287void *CRYPTO_dbg_realloc(void *addr, int num, const char *file, int line) 194void *CRYPTO_malloc(int num, const char *file, int line)
288 { 195 {
289 char *ret; 196 char *ret = NULL;
290 MEM m,*mp;
291
292 ret=realloc_func(addr,num);
293 if (ret == addr) return(ret);
294 197
295 if (mh_mode & CRYPTO_MEM_CHECK_ENABLE) 198 allow_customize = 0;
199 if (malloc_debug_func != NULL)
296 { 200 {
297 MemCheck_off(); 201 allow_customize_debug = 0;
298 if (ret == NULL) return(NULL); 202 malloc_debug_func(NULL, num, file, line, 0);
299 m.addr=addr;
300 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
301 mp=(MEM *)lh_delete(mh,(char *)&m);
302 if (mp != NULL)
303 {
304 mp->addr=ret;
305 lh_insert(mh,(char *)mp);
306 }
307 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
308 MemCheck_on();
309 } 203 }
310 return(ret); 204 ret = malloc_func(num);
311 } 205#ifdef LEVITTE_DEBUG
312 206 fprintf(stderr, "LEVITTE_DEBUG: > 0x%p (%d)\n", ret, num);
313void *CRYPTO_remalloc(void *a, int n) 207#endif
314 { 208 if (malloc_debug_func != NULL)
315 if (a != NULL) Free(a); 209 malloc_debug_func(ret, num, file, line, 1);
316 a=(char *)Malloc(n);
317 return(a);
318 }
319 210
320void *CRYPTO_dbg_remalloc(void *a, int n, const char *file, int line) 211 return ret;
321 {
322 if (a != NULL) CRYPTO_dbg_free(a);
323 a=(char *)CRYPTO_dbg_malloc(n,file,line);
324 return(a);
325 } 212 }
326 213
327 214void *CRYPTO_realloc(void *str, int num, const char *file, int line)
328typedef struct mem_leak_st
329 { 215 {
330 BIO *bio; 216 char *ret = NULL;
331 int chunks;
332 long bytes;
333 } MEM_LEAK;
334 217
335static void print_leak(MEM *m, MEM_LEAK *l) 218 if (realloc_debug_func != NULL)
336 { 219 realloc_debug_func(str, NULL, num, file, line, 0);
337 char buf[128]; 220 ret = realloc_func(str,num);
338#ifdef CRYPTO_MDEBUG_TIME 221#ifdef LEVITTE_DEBUG
339 struct tm *lcl; 222 fprintf(stderr, "LEVITTE_DEBUG: | 0x%p -> 0x%p (%d)\n", str, ret, num);
340#endif 223#endif
224 if (realloc_debug_func != NULL)
225 realloc_debug_func(str, ret, num, file, line, 1);
341 226
342 if(m->addr == (char *)l->bio) 227 return ret;
343 return;
344
345#ifdef CRYPTO_MDEBUG_TIME
346 lcl = localtime(&m->time);
347#endif
348
349 sprintf(buf,
350#ifdef CRYPTO_MDEBUG_TIME
351 "[%02d:%02d:%02d] "
352#endif
353 "%5lu file=%s, line=%d, "
354#ifdef CRYPTO_MDEBUG_THREAD
355 "thread=%lu, "
356#endif
357 "number=%d, address=%08lX\n",
358#ifdef CRYPTO_MDEBUG_TIME
359 lcl->tm_hour,lcl->tm_min,lcl->tm_sec,
360#endif
361 m->order,m->file,m->line,
362#ifdef CRYPTO_MDEBUG_THREAD
363 m->thread,
364#endif
365 m->num,(unsigned long)m->addr);
366
367 BIO_puts(l->bio,buf);
368 l->chunks++;
369 l->bytes+=m->num;
370 } 228 }
371 229
372void CRYPTO_mem_leaks(BIO *b) 230void CRYPTO_free(void *str)
373 { 231 {
374 MEM_LEAK ml; 232 if (free_debug_func != NULL)
375 char buf[80]; 233 free_debug_func(str, 0);
376 234#ifdef LEVITTE_DEBUG
377 if (mh == NULL) return; 235 fprintf(stderr, "LEVITTE_DEBUG: < 0x%p\n", str);
378 ml.bio=b;
379 ml.bytes=0;
380 ml.chunks=0;
381 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
382 lh_doall_arg(mh,(void (*)())print_leak,(char *)&ml);
383 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
384 if (ml.chunks != 0)
385 {
386 sprintf(buf,"%ld bytes leaked in %d chunks\n",
387 ml.bytes,ml.chunks);
388 BIO_puts(b,buf);
389 }
390
391#if 0
392 lh_stats_bio(mh,b);
393 lh_node_stats_bio(mh,b);
394 lh_node_usage_stats_bio(mh,b);
395#endif 236#endif
237 free_func(str);
238 if (free_debug_func != NULL)
239 free_debug_func(NULL, 1);
396 } 240 }
397 241
398static void (*mem_cb)()=NULL; 242void *CRYPTO_remalloc(void *a, int num, const char *file, int line)
399
400static void cb_leak(MEM *m, char *cb)
401 { 243 {
402 void (*mem_callback)()=(void (*)())cb; 244 if (a != NULL) Free(a);
403 mem_callback(m->order,m->file,m->line,m->num,m->addr); 245 a=(char *)Malloc(num);
246 return(a);
404 } 247 }
405 248
406void CRYPTO_mem_leaks_cb(void (*cb)()) 249
250void CRYPTO_set_mem_debug_options(long bits)
407 { 251 {
408 if (mh == NULL) return; 252 if (set_debug_options_func != NULL)
409 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); 253 set_debug_options_func(bits);
410 mem_cb=cb;
411 lh_doall_arg(mh,(void (*)())cb_leak,(char *)mem_cb);
412 mem_cb=NULL;
413 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
414 } 254 }
415 255
416#ifndef NO_FP_API 256long CRYPTO_get_mem_debug_options(void)
417void CRYPTO_mem_leaks_fp(FILE *fp)
418 { 257 {
419 BIO *b; 258 if (get_debug_options_func != NULL)
420 259 return get_debug_options_func();
421 if (mh == NULL) return; 260 return 0;
422 if ((b=BIO_new(BIO_s_file())) == NULL)
423 return;
424 BIO_set_fp(b,fp,BIO_NOCLOSE);
425 CRYPTO_mem_leaks(b);
426 BIO_free(b);
427 } 261 }
428#endif
429