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