1 /* crypto/mem_dbg.c */ 2 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay (at) 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 (at) 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 (at) 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 (at) 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 "cryptlib.h" 63 #include <openssl/crypto.h> 64 #include <openssl/buffer.h> 65 #include <openssl/bio.h> 66 #include <openssl/lhash.h> 67 68 static int mh_mode=CRYPTO_MEM_CHECK_OFF; 69 /* The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE 70 * when the application asks for it (usually after library initialisation 71 * for which no book-keeping is desired). 72 * 73 * State CRYPTO_MEM_CHECK_ON exists only temporarily when the library 74 * thinks that certain allocations should not be checked (e.g. the data 75 * structures used for memory checking). It is not suitable as an initial 76 * state: the library will unexpectedly enable memory checking when it 77 * executes one of those sections that want to disable checking 78 * temporarily. 79 * 80 * State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes no sense whatsoever. 81 */ 82 83 static unsigned long order = 0; /* number of memory requests */ 84 static LHASH *mh=NULL; /* hash-table of memory requests (address as key); 85 * access requires MALLOC2 lock */ 86 87 88 typedef struct app_mem_info_st 89 /* For application-defined information (static C-string `info') 90 * to be displayed in memory leak list. 91 * Each thread has its own stack. For applications, there is 92 * CRYPTO_push_info("...") to push an entry, 93 * CRYPTO_pop_info() to pop an entry, 94 * CRYPTO_remove_all_info() to pop all entries. 95 */ 96 { 97 unsigned long thread; 98 const char *file; 99 int line; 100 const char *info; 101 struct app_mem_info_st *next; /* tail of thread's stack */ 102 int references; 103 } APP_INFO; 104 105 static void app_info_free(APP_INFO *); 106 107 static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's 108 * that are at the top of their thread's stack 109 * (with `thread' as key); 110 * access requires MALLOC2 lock */ 111 112 typedef struct mem_st 113 /* memory-block description */ 114 { 115 void *addr; 116 int num; 117 const char *file; 118 int line; 119 unsigned long thread; 120 unsigned long order; 121 time_t time; 122 APP_INFO *app_info; 123 } MEM; 124 125 static long options = /* extra information to be recorded */ 126 #if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL) 127 V_CRYPTO_MDEBUG_TIME | 128 #endif 129 #if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL) 130 V_CRYPTO_MDEBUG_THREAD | 131 #endif 132 0; 133 134 135 static unsigned int num_disable = 0; /* num_disable > 0 136 * iff 137 * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE) 138 */ 139 static unsigned long disabling_thread = 0; /* Valid iff num_disable > 0. 140 * CRYPTO_LOCK_MALLOC2 is locked 141 * exactly in this case (by the 142 * thread named in disabling_thread). 143 */ 144 145 static void app_info_free(APP_INFO *inf) 146 { 147 if (--(inf->references) <= 0) 148 { 149 if (inf->next != NULL) 150 { 151 app_info_free(inf->next); 152 } 153 OPENSSL_free(inf); 154 } 155 } 156 157 int CRYPTO_mem_ctrl(int mode) 158 { 159 int ret=mh_mode; 160 161 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); 162 switch (mode) 163 { 164 /* for applications (not to be called while multiple threads 165 * use the library): */ 166 case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */ 167 mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE; 168 num_disable = 0; 169 break; 170 case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */ 171 mh_mode = 0; 172 num_disable = 0; /* should be true *before* MemCheck_stop is used, 173 or there'll be a lot of confusion */ 174 break; 175 176 /* switch off temporarily (for library-internal use): */ 177 case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */ 178 if (mh_mode & CRYPTO_MEM_CHECK_ON) 179 { 180 if (!num_disable || (disabling_thread != CRYPTO_thread_id())) /* otherwise we already have the MALLOC2 lock */ 181 { 182 /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while 183 * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if 184 * somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot release 185 * it because we block entry to this function). 186 * Give them a chance, first, and then claim the locks in 187 * appropriate order (long-time lock first). 188 */ 189 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); 190 /* Note that after we have waited for CRYPTO_LOCK_MALLOC2 191 * and CRYPTO_LOCK_MALLOC, we'll still be in the right 192 * "case" and "if" branch because MemCheck_start and 193 * MemCheck_stop may never be used while there are multiple 194 * OpenSSL threads. */ 195 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); 196 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); 197 mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE; 198 disabling_thread=CRYPTO_thread_id(); 199 } 200 num_disable++; 201 } 202 break; 203 case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */ 204 if (mh_mode & CRYPTO_MEM_CHECK_ON) 205 { 206 if (num_disable) /* always true, or something is going wrong */ 207 { 208 num_disable--; 209 if (num_disable == 0) 210 { 211 mh_mode|=CRYPTO_MEM_CHECK_ENABLE; 212 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); 213 } 214 } 215 } 216 break; 217 218 default: 219 break; 220 } 221 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); 222 return(ret); 223 } 224 225 int CRYPTO_is_mem_check_on(void) 226 { 227 int ret = 0; 228 229 if (mh_mode & CRYPTO_MEM_CHECK_ON) 230 { 231 CRYPTO_r_lock(CRYPTO_LOCK_MALLOC); 232 233 ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE) 234 || (disabling_thread != CRYPTO_thread_id()); 235 236 CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC); 237 } 238 return(ret); 239 } 240 241 242 void CRYPTO_dbg_set_options(long bits) 243 { 244 options = bits; 245 } 246 247 long CRYPTO_dbg_get_options(void) 248 { 249 return options; 250 } 251 252 /* static int mem_cmp(MEM *a, MEM *b) */ 253 static int mem_cmp(const void *a_void, const void *b_void) 254 { 255 #ifdef _WIN64 256 const char *a=(const char *)((const MEM *)a_void)->addr, 257 *b=(const char *)((const MEM *)b_void)->addr; 258 if (a==b) return 0; 259 else if (a>b) return 1; 260 else return -1; 261 #else 262 return((const char *)((const MEM *)a_void)->addr 263 - (const char *)((const MEM *)b_void)->addr); 264 #endif 265 } 266 267 /* static unsigned long mem_hash(MEM *a) */ 268 static unsigned long mem_hash(const void *a_void) 269 { 270 unsigned long ret; 271 272 ret=(unsigned long)((const MEM *)a_void)->addr; 273 274 ret=ret*17851+(ret>>14)*7+(ret>>4)*251; 275 return(ret); 276 } 277 278 /* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */ 279 static int app_info_cmp(const void *a_void, const void *b_void) 280 { 281 return(((const APP_INFO *)a_void)->thread 282 != ((const APP_INFO *)b_void)->thread); 283 } 284 285 /* static unsigned long app_info_hash(APP_INFO *a) */ 286 static unsigned long app_info_hash(const void *a_void) 287 { 288 unsigned long ret; 289 290 ret=(unsigned long)((const APP_INFO *)a_void)->thread; 291 292 ret=ret*17851+(ret>>14)*7+(ret>>4)*251; 293 return(ret); 294 } 295 296 static APP_INFO *pop_info(void) 297 { 298 APP_INFO tmp; 299 APP_INFO *ret = NULL; 300 301 if (amih != NULL) 302 { 303 tmp.thread=CRYPTO_thread_id(); 304 if ((ret=(APP_INFO *)lh_delete(amih,&tmp)) != NULL) 305 { 306 APP_INFO *next=ret->next; 307 308 if (next != NULL) 309 { 310 next->references++; 311 lh_insert(amih,(char *)next); 312 } 313 #ifdef LEVITTE_DEBUG_MEM 314 if (ret->thread != tmp.thread) 315 { 316 fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n", 317 ret->thread, tmp.thread); 318 abort(); 319 } 320 #endif 321 if (--(ret->references) <= 0) 322 { 323 ret->next = NULL; 324 if (next != NULL) 325 next->references--; 326 OPENSSL_free(ret); 327 } 328 } 329 } 330 return(ret); 331 } 332 333 int CRYPTO_dbg_push_info(const char *info, const char *file, int line) 334 { 335 APP_INFO *ami, *amim; 336 int ret=0; 337 338 if (is_MemCheck_on()) 339 { 340 MemCheck_off(); /* obtain MALLOC2 lock */ 341 342 if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL) 343 { 344 ret=0; 345 goto err; 346 } 347 if (amih == NULL) 348 { 349 if ((amih=lh_new(app_info_hash, app_info_cmp)) == NULL) 350 { 351 OPENSSL_free(ami); 352 ret=0; 353 goto err; 354 } 355 } 356 357 ami->thread=CRYPTO_thread_id(); 358 ami->file=file; 359 ami->line=line; 360 ami->info=info; 361 ami->references=1; 362 ami->next=NULL; 363 364 if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL) 365 { 366 #ifdef LEVITTE_DEBUG_MEM 367 if (ami->thread != amim->thread) 368 { 369 fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n", 370 amim->thread, ami->thread); 371 abort(); 372 } 373 #endif 374 ami->next=amim; 375 } 376 err: 377 MemCheck_on(); /* release MALLOC2 lock */ 378 } 379 380 return(ret); 381 } 382 383 int CRYPTO_dbg_pop_info(void) 384 { 385 int ret=0; 386 387 if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */ 388 { 389 MemCheck_off(); /* obtain MALLOC2 lock */ 390 391 ret=(pop_info() != NULL); 392 393 MemCheck_on(); /* release MALLOC2 lock */ 394 } 395 return(ret); 396 } 397 398 int CRYPTO_dbg_remove_all_info(void) 399 { 400 int ret=0; 401 402 if (is_MemCheck_on()) /* _must_ be true */ 403 { 404 MemCheck_off(); /* obtain MALLOC2 lock */ 405 406 while(pop_info() != NULL) 407 ret++; 408 409 MemCheck_on(); /* release MALLOC2 lock */ 410 } 411 return(ret); 412 } 413 414 415 static unsigned long break_order_num=0; 416 void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line, 417 int before_p) 418 { 419 MEM *m,*mm; 420 APP_INFO tmp,*amim; 421 422 switch(before_p & 127) 423 { 424 case 0: 425 break; 426 case 1: 427 if (addr == NULL) 428 break; 429 430 if (is_MemCheck_on()) 431 { 432 MemCheck_off(); /* make sure we hold MALLOC2 lock */ 433 if ((m=(MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL) 434 { 435 OPENSSL_free(addr); 436 MemCheck_on(); /* release MALLOC2 lock 437 * if num_disabled drops to 0 */ 438 return; 439 } 440 if (mh == NULL) 441 { 442 if ((mh=lh_new(mem_hash, mem_cmp)) == NULL) 443 { 444 OPENSSL_free(addr); 445 OPENSSL_free(m); 446 addr=NULL; 447 goto err; 448 } 449 } 450 451 m->addr=addr; 452 m->file=file; 453 m->line=line; 454 m->num=num; 455 if (options & V_CRYPTO_MDEBUG_THREAD) 456 m->thread=CRYPTO_thread_id(); 457 else 458 m->thread=0; 459 460 if (order == break_order_num) 461 { 462 /* BREAK HERE */ 463 m->order=order; 464 } 465 m->order=order++; 466 #ifdef LEVITTE_DEBUG_MEM 467 fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] %c 0x%p (%d)\n", 468 m->order, 469 (before_p & 128) ? '*' : '+', 470 m->addr, m->num); 471 #endif 472 if (options & V_CRYPTO_MDEBUG_TIME) 473 m->time=time(NULL); 474 else 475 m->time=0; 476 477 tmp.thread=CRYPTO_thread_id(); 478 m->app_info=NULL; 479 if (amih != NULL 480 && (amim=(APP_INFO *)lh_retrieve(amih,(char *)&tmp)) != NULL) 481 { 482 m->app_info = amim; 483 amim->references++; 484 } 485 486 if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL) 487 { 488 /* Not good, but don't sweat it */ 489 if (mm->app_info != NULL) 490 { 491 mm->app_info->references--; 492 } 493 OPENSSL_free(mm); 494 } 495 err: 496 MemCheck_on(); /* release MALLOC2 lock 497 * if num_disabled drops to 0 */ 498 } 499 break; 500 } 501 return; 502 } 503 504 void CRYPTO_dbg_free(void *addr, int before_p) 505 { 506 MEM m,*mp; 507 508 switch(before_p) 509 { 510 case 0: 511 if (addr == NULL) 512 break; 513 514 if (is_MemCheck_on() && (mh != NULL)) 515 { 516 MemCheck_off(); /* make sure we hold MALLOC2 lock */ 517 518 m.addr=addr; 519 mp=(MEM *)lh_delete(mh,(char *)&m); 520 if (mp != NULL) 521 { 522 #ifdef LEVITTE_DEBUG_MEM 523 fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] - 0x%p (%d)\n", 524 mp->order, mp->addr, mp->num); 525 #endif 526 if (mp->app_info != NULL) 527 app_info_free(mp->app_info); 528 OPENSSL_free(mp); 529 } 530 531 MemCheck_on(); /* release MALLOC2 lock 532 * if num_disabled drops to 0 */ 533 } 534 break; 535 case 1: 536 break; 537 } 538 } 539 540 void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num, 541 const char *file, int line, int before_p) 542 { 543 MEM m,*mp; 544 545 #ifdef LEVITTE_DEBUG_MEM 546 fprintf(stderr, "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n", 547 addr1, addr2, num, file, line, before_p); 548 #endif 549 550 switch(before_p) 551 { 552 case 0: 553 break; 554 case 1: 555 if (addr2 == NULL) 556 break; 557 558 if (addr1 == NULL) 559 { 560 CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p); 561 break; 562 } 563 564 if (is_MemCheck_on()) 565 { 566 MemCheck_off(); /* make sure we hold MALLOC2 lock */ 567 568 m.addr=addr1; 569 mp=(MEM *)lh_delete(mh,(char *)&m); 570 if (mp != NULL) 571 { 572 #ifdef LEVITTE_DEBUG_MEM 573 fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] * 0x%p (%d) -> 0x%p (%d)\n", 574 mp->order, 575 mp->addr, mp->num, 576 addr2, num); 577 #endif 578 mp->addr=addr2; 579 mp->num=num; 580 lh_insert(mh,(char *)mp); 581 } 582 583 MemCheck_on(); /* release MALLOC2 lock 584 * if num_disabled drops to 0 */ 585 } 586 break; 587 } 588 return; 589 } 590 591 592 typedef struct mem_leak_st 593 { 594 BIO *bio; 595 int chunks; 596 long bytes; 597 } MEM_LEAK; 598 599 static void print_leak(const MEM *m, MEM_LEAK *l) 600 { 601 char buf[1024]; 602 char *bufp = buf; 603 APP_INFO *amip; 604 int ami_cnt; 605 struct tm *lcl = NULL; 606 unsigned long ti; 607 608 #define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf)) 609 610 if(m->addr == (char *)l->bio) 611 return; 612 613 if (options & V_CRYPTO_MDEBUG_TIME) 614 { 615 lcl = localtime(&m->time); 616 617 BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ", 618 lcl->tm_hour,lcl->tm_min,lcl->tm_sec); 619 bufp += strlen(bufp); 620 } 621 622 BIO_snprintf(bufp, BUF_REMAIN, "%5lu file=%s, line=%d, ", 623 m->order,m->file,m->line); 624 bufp += strlen(bufp); 625 626 if (options & V_CRYPTO_MDEBUG_THREAD) 627 { 628 BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ", m->thread); 629 bufp += strlen(bufp); 630 } 631 632 BIO_snprintf(bufp, BUF_REMAIN, "number=%d, address=%08lX\n", 633 m->num,(unsigned long)m->addr); 634 bufp += strlen(bufp); 635 636 BIO_puts(l->bio,buf); 637 638 l->chunks++; 639 l->bytes+=m->num; 640 641 amip=m->app_info; 642 ami_cnt=0; 643 if (!amip) 644 return; 645 ti=amip->thread; 646 647 do 648 { 649 int buf_len; 650 int info_len; 651 652 ami_cnt++; 653 memset(buf,'>',ami_cnt); 654 BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt, 655 " thread=%lu, file=%s, line=%d, info=\"", 656 amip->thread, amip->file, amip->line); 657 buf_len=strlen(buf); 658 info_len=strlen(amip->info); 659 if (128 - buf_len - 3 < info_len) 660 { 661 memcpy(buf + buf_len, amip->info, 128 - buf_len - 3); 662 buf_len = 128 - 3; 663 } 664 else 665 { 666 BUF_strlcpy(buf + buf_len, amip->info, 667 sizeof buf - buf_len); 668 buf_len = strlen(buf); 669 } 670 BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n"); 671 672 BIO_puts(l->bio,buf); 673 674 amip = amip->next; 675 } 676 while(amip && amip->thread == ti); 677 678 #ifdef LEVITTE_DEBUG_MEM 679 if (amip) 680 { 681 fprintf(stderr, "Thread switch detected in backtrace!!!!\n"); 682 abort(); 683 } 684 #endif 685 } 686 687 static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM *, MEM_LEAK *) 688 689 void CRYPTO_mem_leaks(BIO *b) 690 { 691 MEM_LEAK ml; 692 693 if (mh == NULL && amih == NULL) 694 return; 695 696 MemCheck_off(); /* obtain MALLOC2 lock */ 697 698 ml.bio=b; 699 ml.bytes=0; 700 ml.chunks=0; 701 if (mh != NULL) 702 lh_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak), 703 (char *)&ml); 704 if (ml.chunks != 0) 705 { 706 BIO_printf(b,"%ld bytes leaked in %d chunks\n", 707 ml.bytes,ml.chunks); 708 } 709 else 710 { 711 /* Make sure that, if we found no leaks, memory-leak debugging itself 712 * does not introduce memory leaks (which might irritate 713 * external debugging tools). 714 * (When someone enables leak checking, but does not call 715 * this function, we declare it to be their fault.) 716 * 717 * XXX This should be in CRYPTO_mem_leaks_cb, 718 * and CRYPTO_mem_leaks should be implemented by 719 * using CRYPTO_mem_leaks_cb. 720 * (Also their should be a variant of lh_doall_arg 721 * that takes a function pointer instead of a void *; 722 * this would obviate the ugly and illegal 723 * void_fn_to_char kludge in CRYPTO_mem_leaks_cb. 724 * Otherwise the code police will come and get us.) 725 */ 726 int old_mh_mode; 727 728 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); 729 730 /* avoid deadlock when lh_free() uses CRYPTO_dbg_free(), 731 * which uses CRYPTO_is_mem_check_on */ 732 old_mh_mode = mh_mode; 733 mh_mode = CRYPTO_MEM_CHECK_OFF; 734 735 if (mh != NULL) 736 { 737 lh_free(mh); 738 mh = NULL; 739 } 740 if (amih != NULL) 741 { 742 if (lh_num_items(amih) == 0) 743 { 744 lh_free(amih); 745 amih = NULL; 746 } 747 } 748 749 mh_mode = old_mh_mode; 750 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); 751 } 752 MemCheck_on(); /* release MALLOC2 lock */ 753 } 754 755 #ifndef OPENSSL_NO_FP_API 756 void CRYPTO_mem_leaks_fp(FILE *fp) 757 { 758 BIO *b; 759 760 if (mh == NULL) return; 761 /* Need to turn off memory checking when allocated BIOs ... especially 762 * as we're creating them at a time when we're trying to check we've not 763 * left anything un-free()'d!! */ 764 MemCheck_off(); 765 b = BIO_new(BIO_s_file()); 766 MemCheck_on(); 767 if(!b) return; 768 BIO_set_fp(b,fp,BIO_NOCLOSE); 769 CRYPTO_mem_leaks(b); 770 BIO_free(b); 771 } 772 #endif 773 774 775 776 /* FIXME: We really don't allow much to the callback. For example, it has 777 no chance of reaching the info stack for the item it processes. Should 778 it really be this way? -- Richard Levitte */ 779 /* NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside crypto.h 780 * If this code is restructured, remove the callback type if it is no longer 781 * needed. -- Geoff Thorpe */ 782 static void cb_leak(const MEM *m, CRYPTO_MEM_LEAK_CB **cb) 783 { 784 (**cb)(m->order,m->file,m->line,m->num,m->addr); 785 } 786 787 static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM *, CRYPTO_MEM_LEAK_CB **) 788 789 void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb) 790 { 791 if (mh == NULL) return; 792 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); 793 lh_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), &cb); 794 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); 795 } 796 797 void CRYPTO_malloc_debug_init(void) 798 { 799 CRYPTO_set_mem_debug_functions( 800 CRYPTO_dbg_malloc, 801 CRYPTO_dbg_realloc, 802 CRYPTO_dbg_free, 803 CRYPTO_dbg_set_options, 804 CRYPTO_dbg_get_options); 805 CRYPTO_set_mem_info_functions( 806 CRYPTO_dbg_push_info, 807 CRYPTO_dbg_pop_info, 808 CRYPTO_dbg_remove_all_info); 809 } 810 811 char *CRYPTO_strdup(const char *str, const char *file, int line) 812 { 813 char *ret = CRYPTO_malloc(strlen(str)+1, file, line); 814 815 strcpy(ret, str); 816 return ret; 817 } 818