summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/mem_dbg.c
diff options
context:
space:
mode:
authormarkus <>2002-09-05 12:51:50 +0000
committermarkus <>2002-09-05 12:51:50 +0000
commit15b5d84f9da2ce4bfae8580e56e34a859f74ad71 (patch)
treebf939e82d7fd73cc8a01cf6959002209972091bc /src/lib/libcrypto/mem_dbg.c
parent027351f729b9e837200dae6e1520cda6577ab930 (diff)
downloadopenbsd-15b5d84f9da2ce4bfae8580e56e34a859f74ad71.tar.gz
openbsd-15b5d84f9da2ce4bfae8580e56e34a859f74ad71.tar.bz2
openbsd-15b5d84f9da2ce4bfae8580e56e34a859f74ad71.zip
import openssl-0.9.7-beta1
Diffstat (limited to 'src/lib/libcrypto/mem_dbg.c')
-rw-r--r--src/lib/libcrypto/mem_dbg.c263
1 files changed, 167 insertions, 96 deletions
diff --git a/src/lib/libcrypto/mem_dbg.c b/src/lib/libcrypto/mem_dbg.c
index 14770c0733..1c4e04f51f 100644
--- a/src/lib/libcrypto/mem_dbg.c
+++ b/src/lib/libcrypto/mem_dbg.c
@@ -81,7 +81,8 @@ static int mh_mode=CRYPTO_MEM_CHECK_OFF;
81 */ 81 */
82 82
83static unsigned long order = 0; /* number of memory requests */ 83static unsigned long order = 0; /* number of memory requests */
84static LHASH *mh=NULL; /* hash-table of memory requests (address as key) */ 84static LHASH *mh=NULL; /* hash-table of memory requests (address as key);
85 * access requires MALLOC2 lock */
85 86
86 87
87typedef struct app_mem_info_st 88typedef struct app_mem_info_st
@@ -103,12 +104,13 @@ typedef struct app_mem_info_st
103 104
104static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's 105static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's
105 * that are at the top of their thread's stack 106 * that are at the top of their thread's stack
106 * (with `thread' as key) */ 107 * (with `thread' as key);
108 * access requires MALLOC2 lock */
107 109
108typedef struct mem_st 110typedef struct mem_st
109/* memory-block description */ 111/* memory-block description */
110 { 112 {
111 char *addr; 113 void *addr;
112 int num; 114 int num;
113 const char *file; 115 const char *file;
114 int line; 116 int line;
@@ -128,7 +130,15 @@ static long options = /* extra information to be recorded */
128 0; 130 0;
129 131
130 132
131static unsigned long disabling_thread = 0; 133static unsigned int num_disable = 0; /* num_disable > 0
134 * iff
135 * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE)
136 */
137static 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).
141 */
132 142
133int CRYPTO_mem_ctrl(int mode) 143int CRYPTO_mem_ctrl(int mode)
134 { 144 {
@@ -137,22 +147,23 @@ int CRYPTO_mem_ctrl(int mode)
137 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); 147 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
138 switch (mode) 148 switch (mode)
139 { 149 {
140 /* for applications: */ 150 /* for applications (not to be called while multiple threads
151 * use the library): */
141 case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */ 152 case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */
142 mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE; 153 mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
143 disabling_thread = 0; 154 num_disable = 0;
144 break; 155 break;
145 case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */ 156 case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
146 mh_mode = 0; 157 mh_mode = 0;
147 disabling_thread = 0; 158 num_disable = 0; /* should be true *before* MemCheck_stop is used,
159 or there'll be a lot of confusion */
148 break; 160 break;
149 161
150 /* switch off temporarily (for library-internal use): */ 162 /* switch off temporarily (for library-internal use): */
151 case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */ 163 case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
152 if (mh_mode & CRYPTO_MEM_CHECK_ON) 164 if (mh_mode & CRYPTO_MEM_CHECK_ON)
153 { 165 {
154 mh_mode&= ~CRYPTO_MEM_CHECK_ENABLE; 166 if (!num_disable || (disabling_thread != CRYPTO_thread_id())) /* otherwise we already have the MALLOC2 lock */
155 if (disabling_thread != CRYPTO_thread_id()) /* otherwise we already have the MALLOC2 lock */
156 { 167 {
157 /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while 168 /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while
158 * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if 169 * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if
@@ -169,18 +180,23 @@ int CRYPTO_mem_ctrl(int mode)
169 * OpenSSL threads. */ 180 * OpenSSL threads. */
170 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); 181 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
171 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); 182 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
183 mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE;
172 disabling_thread=CRYPTO_thread_id(); 184 disabling_thread=CRYPTO_thread_id();
173 } 185 }
186 num_disable++;
174 } 187 }
175 break; 188 break;
176 case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */ 189 case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */
177 if (mh_mode & CRYPTO_MEM_CHECK_ON) 190 if (mh_mode & CRYPTO_MEM_CHECK_ON)
178 { 191 {
179 mh_mode|=CRYPTO_MEM_CHECK_ENABLE; 192 if (num_disable) /* always true, or something is going wrong */
180 if (disabling_thread != 0)
181 { 193 {
182 disabling_thread=0; 194 num_disable--;
183 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); 195 if (num_disable == 0)
196 {
197 mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
198 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
199 }
184 } 200 }
185 } 201 }
186 break; 202 break;
@@ -198,12 +214,12 @@ int CRYPTO_is_mem_check_on(void)
198 214
199 if (mh_mode & CRYPTO_MEM_CHECK_ON) 215 if (mh_mode & CRYPTO_MEM_CHECK_ON)
200 { 216 {
201 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); 217 CRYPTO_r_lock(CRYPTO_LOCK_MALLOC);
202 218
203 ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE) 219 ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
204 && disabling_thread != CRYPTO_thread_id(); 220 || (disabling_thread != CRYPTO_thread_id());
205 221
206 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); 222 CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC);
207 } 223 }
208 return(ret); 224 return(ret);
209 } 225 }
@@ -219,37 +235,43 @@ long CRYPTO_dbg_get_options(void)
219 return options; 235 return options;
220 } 236 }
221 237
222static int mem_cmp(MEM *a, MEM *b) 238/* static int mem_cmp(MEM *a, MEM *b) */
239static int mem_cmp(const void *a_void, const void *b_void)
223 { 240 {
224 return(a->addr - b->addr); 241 return((const char *)((const MEM *)a_void)->addr
242 - (const char *)((const MEM *)b_void)->addr);
225 } 243 }
226 244
227static unsigned long mem_hash(MEM *a) 245/* static unsigned long mem_hash(MEM *a) */
246static unsigned long mem_hash(const void *a_void)
228 { 247 {
229 unsigned long ret; 248 unsigned long ret;
230 249
231 ret=(unsigned long)a->addr; 250 ret=(unsigned long)((const MEM *)a_void)->addr;
232 251
233 ret=ret*17851+(ret>>14)*7+(ret>>4)*251; 252 ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
234 return(ret); 253 return(ret);
235 } 254 }
236 255
237static int app_info_cmp(APP_INFO *a, APP_INFO *b) 256/* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */
257static int app_info_cmp(const void *a_void, const void *b_void)
238 { 258 {
239 return(a->thread != b->thread); 259 return(((const APP_INFO *)a_void)->thread
260 != ((const APP_INFO *)b_void)->thread);
240 } 261 }
241 262
242static unsigned long app_info_hash(APP_INFO *a) 263/* static unsigned long app_info_hash(APP_INFO *a) */
264static unsigned long app_info_hash(const void *a_void)
243 { 265 {
244 unsigned long ret; 266 unsigned long ret;
245 267
246 ret=(unsigned long)a->thread; 268 ret=(unsigned long)((const APP_INFO *)a_void)->thread;
247 269
248 ret=ret*17851+(ret>>14)*7+(ret>>4)*251; 270 ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
249 return(ret); 271 return(ret);
250 } 272 }
251 273
252static APP_INFO *pop_info() 274static APP_INFO *pop_info(void)
253 { 275 {
254 APP_INFO tmp; 276 APP_INFO tmp;
255 APP_INFO *ret = NULL; 277 APP_INFO *ret = NULL;
@@ -266,7 +288,7 @@ static APP_INFO *pop_info()
266 next->references++; 288 next->references++;
267 lh_insert(amih,(char *)next); 289 lh_insert(amih,(char *)next);
268 } 290 }
269#ifdef LEVITTE_DEBUG 291#ifdef LEVITTE_DEBUG_MEM
270 if (ret->thread != tmp.thread) 292 if (ret->thread != tmp.thread)
271 { 293 {
272 fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n", 294 fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
@@ -279,7 +301,7 @@ static APP_INFO *pop_info()
279 ret->next = NULL; 301 ret->next = NULL;
280 if (next != NULL) 302 if (next != NULL)
281 next->references--; 303 next->references--;
282 Free(ret); 304 OPENSSL_free(ret);
283 } 305 }
284 } 306 }
285 } 307 }
@@ -293,18 +315,18 @@ int CRYPTO_push_info_(const char *info, const char *file, int line)
293 315
294 if (is_MemCheck_on()) 316 if (is_MemCheck_on())
295 { 317 {
296 MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ 318 MemCheck_off(); /* obtain MALLOC2 lock */
297 319
298 if ((ami = (APP_INFO *)Malloc(sizeof(APP_INFO))) == NULL) 320 if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL)
299 { 321 {
300 ret=0; 322 ret=0;
301 goto err; 323 goto err;
302 } 324 }
303 if (amih == NULL) 325 if (amih == NULL)
304 { 326 {
305 if ((amih=lh_new(app_info_hash,app_info_cmp)) == NULL) 327 if ((amih=lh_new(app_info_hash, app_info_cmp)) == NULL)
306 { 328 {
307 Free(ami); 329 OPENSSL_free(ami);
308 ret=0; 330 ret=0;
309 goto err; 331 goto err;
310 } 332 }
@@ -319,7 +341,7 @@ int CRYPTO_push_info_(const char *info, const char *file, int line)
319 341
320 if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL) 342 if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL)
321 { 343 {
322#ifdef LEVITTE_DEBUG 344#ifdef LEVITTE_DEBUG_MEM
323 if (ami->thread != amim->thread) 345 if (ami->thread != amim->thread)
324 { 346 {
325 fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n", 347 fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
@@ -330,7 +352,7 @@ int CRYPTO_push_info_(const char *info, const char *file, int line)
330 ami->next=amim; 352 ami->next=amim;
331 } 353 }
332 err: 354 err:
333 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ 355 MemCheck_on(); /* release MALLOC2 lock */
334 } 356 }
335 357
336 return(ret); 358 return(ret);
@@ -342,11 +364,11 @@ int CRYPTO_pop_info(void)
342 364
343 if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */ 365 if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */
344 { 366 {
345 MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ 367 MemCheck_off(); /* obtain MALLOC2 lock */
346 368
347 ret=(pop_info() != NULL); 369 ret=(pop_info() != NULL);
348 370
349 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ 371 MemCheck_on(); /* release MALLOC2 lock */
350 } 372 }
351 return(ret); 373 return(ret);
352 } 374 }
@@ -357,12 +379,12 @@ int CRYPTO_remove_all_info(void)
357 379
358 if (is_MemCheck_on()) /* _must_ be true */ 380 if (is_MemCheck_on()) /* _must_ be true */
359 { 381 {
360 MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ 382 MemCheck_off(); /* obtain MALLOC2 lock */
361 383
362 while(pop_info() != NULL) 384 while(pop_info() != NULL)
363 ret++; 385 ret++;
364 386
365 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ 387 MemCheck_on(); /* release MALLOC2 lock */
366 } 388 }
367 return(ret); 389 return(ret);
368 } 390 }
@@ -385,19 +407,20 @@ void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
385 407
386 if (is_MemCheck_on()) 408 if (is_MemCheck_on())
387 { 409 {
388 MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ 410 MemCheck_off(); /* make sure we hold MALLOC2 lock */
389 if ((m=(MEM *)Malloc(sizeof(MEM))) == NULL) 411 if ((m=(MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL)
390 { 412 {
391 Free(addr); 413 OPENSSL_free(addr);
392 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ 414 MemCheck_on(); /* release MALLOC2 lock
415 * if num_disabled drops to 0 */
393 return; 416 return;
394 } 417 }
395 if (mh == NULL) 418 if (mh == NULL)
396 { 419 {
397 if ((mh=lh_new(mem_hash,mem_cmp)) == NULL) 420 if ((mh=lh_new(mem_hash, mem_cmp)) == NULL)
398 { 421 {
399 Free(addr); 422 OPENSSL_free(addr);
400 Free(m); 423 OPENSSL_free(m);
401 addr=NULL; 424 addr=NULL;
402 goto err; 425 goto err;
403 } 426 }
@@ -418,8 +441,8 @@ void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
418 m->order=order; 441 m->order=order;
419 } 442 }
420 m->order=order++; 443 m->order=order++;
421#ifdef LEVITTE_DEBUG 444#ifdef LEVITTE_DEBUG_MEM
422 fprintf(stderr, "LEVITTE_DEBUG: [%5d] %c 0x%p (%d)\n", 445 fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] %c 0x%p (%d)\n",
423 m->order, 446 m->order,
424 (before_p & 128) ? '*' : '+', 447 (before_p & 128) ? '*' : '+',
425 m->addr, m->num); 448 m->addr, m->num);
@@ -445,10 +468,11 @@ void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
445 { 468 {
446 mm->app_info->references--; 469 mm->app_info->references--;
447 } 470 }
448 Free(mm); 471 OPENSSL_free(mm);
449 } 472 }
450 err: 473 err:
451 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ 474 MemCheck_on(); /* release MALLOC2 lock
475 * if num_disabled drops to 0 */
452 } 476 }
453 break; 477 break;
454 } 478 }
@@ -467,24 +491,25 @@ void CRYPTO_dbg_free(void *addr, int before_p)
467 491
468 if (is_MemCheck_on() && (mh != NULL)) 492 if (is_MemCheck_on() && (mh != NULL))
469 { 493 {
470 MemCheck_off(); 494 MemCheck_off(); /* make sure we hold MALLOC2 lock */
471 495
472 m.addr=addr; 496 m.addr=addr;
473 mp=(MEM *)lh_delete(mh,(char *)&m); 497 mp=(MEM *)lh_delete(mh,(char *)&m);
474 if (mp != NULL) 498 if (mp != NULL)
475 { 499 {
476#ifdef LEVITTE_DEBUG 500#ifdef LEVITTE_DEBUG_MEM
477 fprintf(stderr, "LEVITTE_DEBUG: [%5d] - 0x%p (%d)\n", 501 fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] - 0x%p (%d)\n",
478 mp->order, mp->addr, mp->num); 502 mp->order, mp->addr, mp->num);
479#endif 503#endif
480 if (mp->app_info != NULL) 504 if (mp->app_info != NULL)
481 { 505 {
482 mp->app_info->references--; 506 mp->app_info->references--;
483 } 507 }
484 Free(mp); 508 OPENSSL_free(mp);
485 } 509 }
486 510
487 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ 511 MemCheck_on(); /* release MALLOC2 lock
512 * if num_disabled drops to 0 */
488 } 513 }
489 break; 514 break;
490 case 1: 515 case 1:
@@ -497,8 +522,8 @@ void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
497 { 522 {
498 MEM m,*mp; 523 MEM m,*mp;
499 524
500#ifdef LEVITTE_DEBUG 525#ifdef LEVITTE_DEBUG_MEM
501 fprintf(stderr, "LEVITTE_DEBUG: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n", 526 fprintf(stderr, "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n",
502 addr1, addr2, num, file, line, before_p); 527 addr1, addr2, num, file, line, before_p);
503#endif 528#endif
504 529
@@ -518,14 +543,14 @@ void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
518 543
519 if (is_MemCheck_on()) 544 if (is_MemCheck_on())
520 { 545 {
521 MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ 546 MemCheck_off(); /* make sure we hold MALLOC2 lock */
522 547
523 m.addr=addr1; 548 m.addr=addr1;
524 mp=(MEM *)lh_delete(mh,(char *)&m); 549 mp=(MEM *)lh_delete(mh,(char *)&m);
525 if (mp != NULL) 550 if (mp != NULL)
526 { 551 {
527#ifdef LEVITTE_DEBUG 552#ifdef LEVITTE_DEBUG_MEM
528 fprintf(stderr, "LEVITTE_DEBUG: [%5d] * 0x%p (%d) -> 0x%p (%d)\n", 553 fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] * 0x%p (%d) -> 0x%p (%d)\n",
529 mp->order, 554 mp->order,
530 mp->addr, mp->num, 555 mp->addr, mp->num,
531 addr2, num); 556 addr2, num);
@@ -535,7 +560,8 @@ void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
535 lh_insert(mh,(char *)mp); 560 lh_insert(mh,(char *)mp);
536 } 561 }
537 562
538 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ 563 MemCheck_on(); /* release MALLOC2 lock
564 * if num_disabled drops to 0 */
539 } 565 }
540 break; 566 break;
541 } 567 }
@@ -550,7 +576,7 @@ typedef struct mem_leak_st
550 long bytes; 576 long bytes;
551 } MEM_LEAK; 577 } MEM_LEAK;
552 578
553static void print_leak(MEM *m, MEM_LEAK *l) 579static void print_leak(const MEM *m, MEM_LEAK *l)
554 { 580 {
555 char buf[1024]; 581 char buf[1024];
556 char *bufp = buf; 582 char *bufp = buf;
@@ -626,7 +652,7 @@ static void print_leak(MEM *m, MEM_LEAK *l)
626 } 652 }
627 while(amip && amip->thread == ti); 653 while(amip && amip->thread == ti);
628 654
629#ifdef LEVITTE_DEBUG 655#ifdef LEVITTE_DEBUG_MEM
630 if (amip) 656 if (amip)
631 { 657 {
632 fprintf(stderr, "Thread switch detected in backtrace!!!!\n"); 658 fprintf(stderr, "Thread switch detected in backtrace!!!!\n");
@@ -635,69 +661,114 @@ static void print_leak(MEM *m, MEM_LEAK *l)
635#endif 661#endif
636 } 662 }
637 663
664static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM *, MEM_LEAK *)
665
638void CRYPTO_mem_leaks(BIO *b) 666void CRYPTO_mem_leaks(BIO *b)
639 { 667 {
640 MEM_LEAK ml; 668 MEM_LEAK ml;
641 char buf[80]; 669 char buf[80];
642 670
643 if (mh == NULL) return; 671 if (mh == NULL && amih == NULL)
672 return;
673
674 MemCheck_off(); /* obtain MALLOC2 lock */
675
644 ml.bio=b; 676 ml.bio=b;
645 ml.bytes=0; 677 ml.bytes=0;
646 ml.chunks=0; 678 ml.chunks=0;
647 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); 679 if (mh != NULL)
648 lh_doall_arg(mh,(void (*)())print_leak,(char *)&ml); 680 lh_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak),
649 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); 681 (char *)&ml);
650 if (ml.chunks != 0) 682 if (ml.chunks != 0)
651 { 683 {
652 sprintf(buf,"%ld bytes leaked in %d chunks\n", 684 sprintf(buf,"%ld bytes leaked in %d chunks\n",
653 ml.bytes,ml.chunks); 685 ml.bytes,ml.chunks);
654 BIO_puts(b,buf); 686 BIO_puts(b,buf);
655 } 687 }
688 else
689 {
690 /* Make sure that, if we found no leaks, memory-leak debugging itself
691 * does not introduce memory leaks (which might irritate
692 * external debugging tools).
693 * (When someone enables leak checking, but does not call
694 * this function, we declare it to be their fault.)
695 *
696 * XXX This should be in CRYPTO_mem_leaks_cb,
697 * and CRYPTO_mem_leaks should be implemented by
698 * using CRYPTO_mem_leaks_cb.
699 * (Also their should be a variant of lh_doall_arg
700 * that takes a function pointer instead of a void *;
701 * this would obviate the ugly and illegal
702 * void_fn_to_char kludge in CRYPTO_mem_leaks_cb.
703 * Otherwise the code police will come and get us.)
704 */
705 int old_mh_mode;
656 706
657#if 0 707 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
658 lh_stats_bio(mh,b);
659 lh_node_stats_bio(mh,b);
660 lh_node_usage_stats_bio(mh,b);
661#endif
662 }
663
664union void_fn_to_char_u
665 {
666 char *char_p;
667 void (*fn_p)();
668 };
669
670static void cb_leak(MEM *m, char *cb)
671 {
672 union void_fn_to_char_u mem_callback;
673 708
674 mem_callback.char_p=cb; 709 /* avoid deadlock when lh_free() uses CRYPTO_dbg_free(),
675 mem_callback.fn_p(m->order,m->file,m->line,m->num,m->addr); 710 * which uses CRYPTO_is_mem_check_on */
676 } 711 old_mh_mode = mh_mode;
712 mh_mode = CRYPTO_MEM_CHECK_OFF;
677 713
678void CRYPTO_mem_leaks_cb(void (*cb)()) 714 if (mh != NULL)
679 { 715 {
680 union void_fn_to_char_u mem_cb; 716 lh_free(mh);
717 mh = NULL;
718 }
719 if (amih != NULL)
720 {
721 if (lh_num_items(amih) == 0)
722 {
723 lh_free(amih);
724 amih = NULL;
725 }
726 }
681 727
682 if (mh == NULL) return; 728 mh_mode = old_mh_mode;
683 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); 729 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
684 mem_cb.fn_p=cb; 730 }
685 lh_doall_arg(mh,(void (*)())cb_leak,mem_cb.char_p); 731 MemCheck_on(); /* release MALLOC2 lock */
686 mem_cb.char_p=NULL;
687 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
688 } 732 }
689 733
690#ifndef NO_FP_API 734#ifndef OPENSSL_NO_FP_API
691void CRYPTO_mem_leaks_fp(FILE *fp) 735void CRYPTO_mem_leaks_fp(FILE *fp)
692 { 736 {
693 BIO *b; 737 BIO *b;
694 738
695 if (mh == NULL) return; 739 if (mh == NULL) return;
696 if ((b=BIO_new(BIO_s_file())) == NULL) 740 /* Need to turn off memory checking when allocated BIOs ... especially
697 return; 741 * as we're creating them at a time when we're trying to check we've not
742 * left anything un-free()'d!! */
743 MemCheck_off();
744 b = BIO_new(BIO_s_file());
745 MemCheck_on();
746 if(!b) return;
698 BIO_set_fp(b,fp,BIO_NOCLOSE); 747 BIO_set_fp(b,fp,BIO_NOCLOSE);
699 CRYPTO_mem_leaks(b); 748 CRYPTO_mem_leaks(b);
700 BIO_free(b); 749 BIO_free(b);
701 } 750 }
702#endif 751#endif
703 752
753
754
755/* FIXME: We really don't allow much to the callback. For example, it has
756 no chance of reaching the info stack for the item it processes. Should
757 it really be this way? -- Richard Levitte */
758/* NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside crypto.h
759 * If this code is restructured, remove the callback type if it is no longer
760 * needed. -- Geoff Thorpe */
761static void cb_leak(const MEM *m, CRYPTO_MEM_LEAK_CB **cb)
762 {
763 (**cb)(m->order,m->file,m->line,m->num,m->addr);
764 }
765
766static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM *, CRYPTO_MEM_LEAK_CB **)
767
768void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
769 {
770 if (mh == NULL) return;
771 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
772 lh_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), &cb);
773 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
774 }