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