159191Skris/* crypto/mem_dbg.c */ 259191Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 359191Skris * All rights reserved. 459191Skris * 559191Skris * This package is an SSL implementation written 659191Skris * by Eric Young (eay@cryptsoft.com). 759191Skris * The implementation was written so as to conform with Netscapes SSL. 8280304Sjkim * 959191Skris * This library is free for commercial and non-commercial use as long as 1059191Skris * the following conditions are aheared to. The following conditions 1159191Skris * apply to all code found in this distribution, be it the RC4, RSA, 1259191Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1359191Skris * included with this distribution is covered by the same copyright terms 1459191Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15280304Sjkim * 1659191Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1759191Skris * the code are not to be removed. 1859191Skris * If this package is used in a product, Eric Young should be given attribution 1959191Skris * as the author of the parts of the library used. 2059191Skris * This can be in the form of a textual message at program startup or 2159191Skris * in documentation (online or textual) provided with the package. 22280304Sjkim * 2359191Skris * Redistribution and use in source and binary forms, with or without 2459191Skris * modification, are permitted provided that the following conditions 2559191Skris * are met: 2659191Skris * 1. Redistributions of source code must retain the copyright 2759191Skris * notice, this list of conditions and the following disclaimer. 2859191Skris * 2. Redistributions in binary form must reproduce the above copyright 2959191Skris * notice, this list of conditions and the following disclaimer in the 3059191Skris * documentation and/or other materials provided with the distribution. 3159191Skris * 3. All advertising materials mentioning features or use of this software 3259191Skris * must display the following acknowledgement: 3359191Skris * "This product includes cryptographic software written by 3459191Skris * Eric Young (eay@cryptsoft.com)" 3559191Skris * The word 'cryptographic' can be left out if the rouines from the library 3659191Skris * being used are not cryptographic related :-). 37280304Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from 3859191Skris * the apps directory (application code) you must include an acknowledgement: 3959191Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40280304Sjkim * 4159191Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4259191Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4359191Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4459191Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4559191Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4659191Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4759191Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4859191Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4959191Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5059191Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5159191Skris * SUCH DAMAGE. 52280304Sjkim * 5359191Skris * The licence and distribution terms for any publically available version or 5459191Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5559191Skris * copied and put under another distribution licence 5659191Skris * [including the GNU Public Licence.] 5759191Skris */ 58238405Sjkim/* ==================================================================== 59238405Sjkim * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. 60238405Sjkim * 61238405Sjkim * Redistribution and use in source and binary forms, with or without 62238405Sjkim * modification, are permitted provided that the following conditions 63238405Sjkim * are met: 64238405Sjkim * 65238405Sjkim * 1. Redistributions of source code must retain the above copyright 66280304Sjkim * notice, this list of conditions and the following disclaimer. 67238405Sjkim * 68238405Sjkim * 2. Redistributions in binary form must reproduce the above copyright 69238405Sjkim * notice, this list of conditions and the following disclaimer in 70238405Sjkim * the documentation and/or other materials provided with the 71238405Sjkim * distribution. 72238405Sjkim * 73238405Sjkim * 3. All advertising materials mentioning features or use of this 74238405Sjkim * software must display the following acknowledgment: 75238405Sjkim * "This product includes software developed by the OpenSSL Project 76238405Sjkim * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 77238405Sjkim * 78238405Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 79238405Sjkim * endorse or promote products derived from this software without 80238405Sjkim * prior written permission. For written permission, please contact 81238405Sjkim * openssl-core@openssl.org. 82238405Sjkim * 83238405Sjkim * 5. Products derived from this software may not be called "OpenSSL" 84238405Sjkim * nor may "OpenSSL" appear in their names without prior written 85238405Sjkim * permission of the OpenSSL Project. 86238405Sjkim * 87238405Sjkim * 6. Redistributions of any form whatsoever must retain the following 88238405Sjkim * acknowledgment: 89238405Sjkim * "This product includes software developed by the OpenSSL Project 90238405Sjkim * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 91238405Sjkim * 92238405Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 93238405Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 94238405Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 95238405Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 96238405Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 97238405Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 98238405Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 99238405Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 100238405Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 101238405Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 102238405Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 103238405Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 104238405Sjkim * ==================================================================== 105238405Sjkim * 106238405Sjkim * This product includes cryptographic software written by Eric Young 107238405Sjkim * (eay@cryptsoft.com). This product includes software written by Tim 108238405Sjkim * Hudson (tjh@cryptsoft.com). 109238405Sjkim * 110238405Sjkim */ 11159191Skris 11259191Skris#include <stdio.h> 11359191Skris#include <stdlib.h> 114280304Sjkim#include <time.h> 115160814Ssimon#include "cryptlib.h" 11659191Skris#include <openssl/crypto.h> 11759191Skris#include <openssl/buffer.h> 11859191Skris#include <openssl/bio.h> 11959191Skris#include <openssl/lhash.h> 12059191Skris 121280304Sjkimstatic int mh_mode = CRYPTO_MEM_CHECK_OFF; 122280304Sjkim/* 123280304Sjkim * The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE when 124280304Sjkim * the application asks for it (usually after library initialisation for 125280304Sjkim * which no book-keeping is desired). State CRYPTO_MEM_CHECK_ON exists only 126280304Sjkim * temporarily when the library thinks that certain allocations should not be 127280304Sjkim * checked (e.g. the data structures used for memory checking). It is not 128280304Sjkim * suitable as an initial state: the library will unexpectedly enable memory 129280304Sjkim * checking when it executes one of those sections that want to disable 130280304Sjkim * checking temporarily. State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes 131280304Sjkim * no sense whatsoever. 13259191Skris */ 13359191Skris 13459191Skrisstatic unsigned long order = 0; /* number of memory requests */ 13559191Skris 136238405SjkimDECLARE_LHASH_OF(MEM); 137280304Sjkimstatic LHASH_OF(MEM) *mh = NULL; /* hash-table of memory requests (address as 138280304Sjkim * key); access requires MALLOC2 lock */ 13959191Skris 14059191Skristypedef struct app_mem_info_st 141280304Sjkim/*- 142280304Sjkim * For application-defined information (static C-string `info') 14359191Skris * to be displayed in memory leak list. 14459191Skris * Each thread has its own stack. For applications, there is 14559191Skris * CRYPTO_push_info("...") to push an entry, 14659191Skris * CRYPTO_pop_info() to pop an entry, 14759191Skris * CRYPTO_remove_all_info() to pop all entries. 14859191Skris */ 149280304Sjkim{ 150280304Sjkim CRYPTO_THREADID threadid; 151280304Sjkim const char *file; 152280304Sjkim int line; 153280304Sjkim const char *info; 154280304Sjkim struct app_mem_info_st *next; /* tail of thread's stack */ 155280304Sjkim int references; 156280304Sjkim} APP_INFO; 15759191Skris 158109998Smarkmstatic void app_info_free(APP_INFO *); 159109998Smarkm 160238405SjkimDECLARE_LHASH_OF(APP_INFO); 161280304Sjkimstatic LHASH_OF(APP_INFO) *amih = NULL; /* hash-table with those 162280304Sjkim * app_mem_info_st's that are at the 163280304Sjkim * top of their thread's stack (with 164280304Sjkim * `thread' as key); access requires 165280304Sjkim * MALLOC2 lock */ 16659191Skris 16759191Skristypedef struct mem_st 16859191Skris/* memory-block description */ 169280304Sjkim{ 170280304Sjkim void *addr; 171280304Sjkim int num; 172280304Sjkim const char *file; 173280304Sjkim int line; 174280304Sjkim CRYPTO_THREADID threadid; 175280304Sjkim unsigned long order; 176280304Sjkim time_t time; 177280304Sjkim APP_INFO *app_info; 178280304Sjkim} MEM; 17959191Skris 180280304Sjkimstatic long options = /* extra information to be recorded */ 18159191Skris#if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL) 182280304Sjkim V_CRYPTO_MDEBUG_TIME | 18359191Skris#endif 18459191Skris#if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL) 185280304Sjkim V_CRYPTO_MDEBUG_THREAD | 18659191Skris#endif 187280304Sjkim 0; 18859191Skris 189280304Sjkimstatic unsigned int num_disable = 0; /* num_disable > 0 iff mh_mode == 190280304Sjkim * CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE) */ 19159191Skris 192280304Sjkim/* 193280304Sjkim * Valid iff num_disable > 0. CRYPTO_LOCK_MALLOC2 is locked exactly in this 194238405Sjkim * case (by the thread named in disabling_thread). 195238405Sjkim */ 196238405Sjkimstatic CRYPTO_THREADID disabling_threadid; 197238405Sjkim 198109998Smarkmstatic void app_info_free(APP_INFO *inf) 199280304Sjkim{ 200280304Sjkim if (--(inf->references) <= 0) { 201280304Sjkim if (inf->next != NULL) { 202280304Sjkim app_info_free(inf->next); 203280304Sjkim } 204280304Sjkim OPENSSL_free(inf); 205280304Sjkim } 206280304Sjkim} 207109998Smarkm 20859191Skrisint CRYPTO_mem_ctrl(int mode) 209280304Sjkim{ 210280304Sjkim int ret = mh_mode; 21159191Skris 212280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); 213280304Sjkim switch (mode) { 214280304Sjkim /* 215280304Sjkim * for applications (not to be called while multiple threads use the 216280304Sjkim * library): 217280304Sjkim */ 218280304Sjkim case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */ 219280304Sjkim mh_mode = CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE; 220280304Sjkim num_disable = 0; 221280304Sjkim break; 222280304Sjkim case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */ 223280304Sjkim mh_mode = 0; 224280304Sjkim num_disable = 0; /* should be true *before* MemCheck_stop is 225280304Sjkim * used, or there'll be a lot of confusion */ 226280304Sjkim break; 22759191Skris 228280304Sjkim /* switch off temporarily (for library-internal use): */ 229280304Sjkim case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */ 230280304Sjkim if (mh_mode & CRYPTO_MEM_CHECK_ON) { 231280304Sjkim CRYPTO_THREADID cur; 232280304Sjkim CRYPTO_THREADID_current(&cur); 233280304Sjkim /* see if we don't have the MALLOC2 lock already */ 234280304Sjkim if (!num_disable 235280304Sjkim || CRYPTO_THREADID_cmp(&disabling_threadid, &cur)) { 236280304Sjkim /* 237280304Sjkim * Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed 238280304Sjkim * while we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock 239280304Sjkim * if somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot 240280304Sjkim * release it because we block entry to this function). Give 241280304Sjkim * them a chance, first, and then claim the locks in 242280304Sjkim * appropriate order (long-time lock first). 243280304Sjkim */ 244280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); 245280304Sjkim /* 246280304Sjkim * Note that after we have waited for CRYPTO_LOCK_MALLOC2 and 247280304Sjkim * CRYPTO_LOCK_MALLOC, we'll still be in the right "case" and 248280304Sjkim * "if" branch because MemCheck_start and MemCheck_stop may 249280304Sjkim * never be used while there are multiple OpenSSL threads. 250280304Sjkim */ 251280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); 252280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); 253280304Sjkim mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE; 254280304Sjkim CRYPTO_THREADID_cpy(&disabling_threadid, &cur); 255280304Sjkim } 256280304Sjkim num_disable++; 257280304Sjkim } 258280304Sjkim break; 259280304Sjkim case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */ 260280304Sjkim if (mh_mode & CRYPTO_MEM_CHECK_ON) { 261280304Sjkim if (num_disable) { /* always true, or something is going wrong */ 262280304Sjkim num_disable--; 263280304Sjkim if (num_disable == 0) { 264280304Sjkim mh_mode |= CRYPTO_MEM_CHECK_ENABLE; 265280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); 266280304Sjkim } 267280304Sjkim } 268280304Sjkim } 269280304Sjkim break; 27059191Skris 271280304Sjkim default: 272280304Sjkim break; 273280304Sjkim } 274280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); 275280304Sjkim return (ret); 276280304Sjkim} 27759191Skris 27859191Skrisint CRYPTO_is_mem_check_on(void) 279280304Sjkim{ 280280304Sjkim int ret = 0; 28159191Skris 282280304Sjkim if (mh_mode & CRYPTO_MEM_CHECK_ON) { 283280304Sjkim CRYPTO_THREADID cur; 284280304Sjkim CRYPTO_THREADID_current(&cur); 285280304Sjkim CRYPTO_r_lock(CRYPTO_LOCK_MALLOC); 28659191Skris 287280304Sjkim ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE) 288280304Sjkim || CRYPTO_THREADID_cmp(&disabling_threadid, &cur); 28959191Skris 290280304Sjkim CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC); 291280304Sjkim } 292280304Sjkim return (ret); 293280304Sjkim} 29459191Skris 29559191Skrisvoid CRYPTO_dbg_set_options(long bits) 296280304Sjkim{ 297280304Sjkim options = bits; 298280304Sjkim} 29959191Skris 30059191Skrislong CRYPTO_dbg_get_options(void) 301280304Sjkim{ 302280304Sjkim return options; 303280304Sjkim} 30459191Skris 305238405Sjkimstatic int mem_cmp(const MEM *a, const MEM *b) 306280304Sjkim{ 307160814Ssimon#ifdef _WIN64 308280304Sjkim const char *ap = (const char *)a->addr, *bp = (const char *)b->addr; 309280304Sjkim if (ap == bp) 310280304Sjkim return 0; 311280304Sjkim else if (ap > bp) 312280304Sjkim return 1; 313280304Sjkim else 314280304Sjkim return -1; 315160814Ssimon#else 316280304Sjkim return (const char *)a->addr - (const char *)b->addr; 317160814Ssimon#endif 318280304Sjkim} 319280304Sjkim 320238405Sjkimstatic IMPLEMENT_LHASH_COMP_FN(mem, MEM) 32159191Skris 322238405Sjkimstatic unsigned long mem_hash(const MEM *a) 323280304Sjkim{ 324280304Sjkim unsigned long ret; 32559191Skris 326280304Sjkim ret = (unsigned long)a->addr; 32759191Skris 328280304Sjkim ret = ret * 17851 + (ret >> 14) * 7 + (ret >> 4) * 251; 329280304Sjkim return (ret); 330280304Sjkim} 331280304Sjkim 332238405Sjkimstatic IMPLEMENT_LHASH_HASH_FN(mem, MEM) 33359191Skris 334109998Smarkm/* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */ 335109998Smarkmstatic int app_info_cmp(const void *a_void, const void *b_void) 336280304Sjkim{ 337280304Sjkim return CRYPTO_THREADID_cmp(&((const APP_INFO *)a_void)->threadid, 338280304Sjkim &((const APP_INFO *)b_void)->threadid); 339280304Sjkim} 340280304Sjkim 341238405Sjkimstatic IMPLEMENT_LHASH_COMP_FN(app_info, APP_INFO) 34259191Skris 343238405Sjkimstatic unsigned long app_info_hash(const APP_INFO *a) 344280304Sjkim{ 345280304Sjkim unsigned long ret; 34659191Skris 347280304Sjkim ret = CRYPTO_THREADID_hash(&a->threadid); 348280304Sjkim /* This is left in as a "who am I to question legacy?" measure */ 349280304Sjkim ret = ret * 17851 + (ret >> 14) * 7 + (ret >> 4) * 251; 350280304Sjkim return (ret); 351280304Sjkim} 352280304Sjkim 353238405Sjkimstatic IMPLEMENT_LHASH_HASH_FN(app_info, APP_INFO) 35459191Skris 355109998Smarkmstatic APP_INFO *pop_info(void) 356280304Sjkim{ 357280304Sjkim APP_INFO tmp; 358280304Sjkim APP_INFO *ret = NULL; 35959191Skris 360280304Sjkim if (amih != NULL) { 361280304Sjkim CRYPTO_THREADID_current(&tmp.threadid); 362280304Sjkim if ((ret = lh_APP_INFO_delete(amih, &tmp)) != NULL) { 363280304Sjkim APP_INFO *next = ret->next; 36459191Skris 365280304Sjkim if (next != NULL) { 366280304Sjkim next->references++; 367280304Sjkim (void)lh_APP_INFO_insert(amih, next); 368280304Sjkim } 369109998Smarkm#ifdef LEVITTE_DEBUG_MEM 370280304Sjkim if (CRYPTO_THREADID_cmp(&ret->threadid, &tmp.threadid)) { 371280304Sjkim fprintf(stderr, 372280304Sjkim "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n", 373280304Sjkim CRYPTO_THREADID_hash(&ret->threadid), 374280304Sjkim CRYPTO_THREADID_hash(&tmp.threadid)); 375280304Sjkim abort(); 376280304Sjkim } 37759191Skris#endif 378280304Sjkim if (--(ret->references) <= 0) { 379280304Sjkim ret->next = NULL; 380280304Sjkim if (next != NULL) 381280304Sjkim next->references--; 382280304Sjkim OPENSSL_free(ret); 383280304Sjkim } 384280304Sjkim } 385280304Sjkim } 386280304Sjkim return (ret); 387280304Sjkim} 38859191Skris 389238405Sjkimint CRYPTO_push_info_(const char *info, const char *file, int line) 390280304Sjkim{ 391280304Sjkim APP_INFO *ami, *amim; 392280304Sjkim int ret = 0; 39359191Skris 394280304Sjkim if (is_MemCheck_on()) { 395280304Sjkim MemCheck_off(); /* obtain MALLOC2 lock */ 39659191Skris 397280304Sjkim if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL) { 398280304Sjkim ret = 0; 399280304Sjkim goto err; 400280304Sjkim } 401280304Sjkim if (amih == NULL) { 402280304Sjkim if ((amih = lh_APP_INFO_new()) == NULL) { 403280304Sjkim OPENSSL_free(ami); 404280304Sjkim ret = 0; 405280304Sjkim goto err; 406280304Sjkim } 407280304Sjkim } 40859191Skris 409280304Sjkim CRYPTO_THREADID_current(&ami->threadid); 410280304Sjkim ami->file = file; 411280304Sjkim ami->line = line; 412280304Sjkim ami->info = info; 413280304Sjkim ami->references = 1; 414280304Sjkim ami->next = NULL; 41559191Skris 416280304Sjkim if ((amim = lh_APP_INFO_insert(amih, ami)) != NULL) { 417109998Smarkm#ifdef LEVITTE_DEBUG_MEM 418280304Sjkim if (CRYPTO_THREADID_cmp(&ami->threadid, &amim->threadid)) { 419280304Sjkim fprintf(stderr, 420280304Sjkim "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n", 421280304Sjkim CRYPTO_THREADID_hash(&amim->threadid), 422280304Sjkim CRYPTO_THREADID_hash(&ami->threadid)); 423280304Sjkim abort(); 424280304Sjkim } 42559191Skris#endif 426280304Sjkim ami->next = amim; 427280304Sjkim } 42859191Skris err: 429280304Sjkim MemCheck_on(); /* release MALLOC2 lock */ 430280304Sjkim } 43159191Skris 432280304Sjkim return (ret); 433280304Sjkim} 43459191Skris 435238405Sjkimint CRYPTO_pop_info(void) 436280304Sjkim{ 437280304Sjkim int ret = 0; 43859191Skris 439280304Sjkim if (is_MemCheck_on()) { /* _must_ be true, or something went severely 440280304Sjkim * wrong */ 441280304Sjkim MemCheck_off(); /* obtain MALLOC2 lock */ 44259191Skris 443280304Sjkim ret = (pop_info() != NULL); 44459191Skris 445280304Sjkim MemCheck_on(); /* release MALLOC2 lock */ 446280304Sjkim } 447280304Sjkim return (ret); 448280304Sjkim} 44959191Skris 450238405Sjkimint CRYPTO_remove_all_info(void) 451280304Sjkim{ 452280304Sjkim int ret = 0; 45359191Skris 454280304Sjkim if (is_MemCheck_on()) { /* _must_ be true */ 455280304Sjkim MemCheck_off(); /* obtain MALLOC2 lock */ 45659191Skris 457280304Sjkim while (pop_info() != NULL) 458280304Sjkim ret++; 45959191Skris 460280304Sjkim MemCheck_on(); /* release MALLOC2 lock */ 461280304Sjkim } 462280304Sjkim return (ret); 463280304Sjkim} 46459191Skris 465280304Sjkimstatic unsigned long break_order_num = 0; 46659191Skrisvoid CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line, 467280304Sjkim int before_p) 468280304Sjkim{ 469280304Sjkim MEM *m, *mm; 470280304Sjkim APP_INFO tmp, *amim; 47159191Skris 472280304Sjkim switch (before_p & 127) { 473280304Sjkim case 0: 474280304Sjkim break; 475280304Sjkim case 1: 476280304Sjkim if (addr == NULL) 477280304Sjkim break; 47859191Skris 479280304Sjkim if (is_MemCheck_on()) { 480280304Sjkim MemCheck_off(); /* make sure we hold MALLOC2 lock */ 481280304Sjkim if ((m = (MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL) { 482280304Sjkim OPENSSL_free(addr); 483280304Sjkim MemCheck_on(); /* release MALLOC2 lock if num_disabled drops 484280304Sjkim * to 0 */ 485280304Sjkim return; 486280304Sjkim } 487280304Sjkim if (mh == NULL) { 488280304Sjkim if ((mh = lh_MEM_new()) == NULL) { 489280304Sjkim OPENSSL_free(addr); 490280304Sjkim OPENSSL_free(m); 491280304Sjkim addr = NULL; 492280304Sjkim goto err; 493280304Sjkim } 494280304Sjkim } 49559191Skris 496280304Sjkim m->addr = addr; 497280304Sjkim m->file = file; 498280304Sjkim m->line = line; 499280304Sjkim m->num = num; 500280304Sjkim if (options & V_CRYPTO_MDEBUG_THREAD) 501280304Sjkim CRYPTO_THREADID_current(&m->threadid); 502280304Sjkim else 503280304Sjkim memset(&m->threadid, 0, sizeof(m->threadid)); 50459191Skris 505280304Sjkim if (order == break_order_num) { 506280304Sjkim /* BREAK HERE */ 507280304Sjkim m->order = order; 508280304Sjkim } 509280304Sjkim m->order = order++; 510109998Smarkm#ifdef LEVITTE_DEBUG_MEM 511280304Sjkim fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] %c 0x%p (%d)\n", 512280304Sjkim m->order, (before_p & 128) ? '*' : '+', m->addr, m->num); 51359191Skris#endif 514280304Sjkim if (options & V_CRYPTO_MDEBUG_TIME) 515280304Sjkim m->time = time(NULL); 516280304Sjkim else 517280304Sjkim m->time = 0; 51859191Skris 519280304Sjkim CRYPTO_THREADID_current(&tmp.threadid); 520280304Sjkim m->app_info = NULL; 521280304Sjkim if (amih != NULL 522280304Sjkim && (amim = lh_APP_INFO_retrieve(amih, &tmp)) != NULL) { 523280304Sjkim m->app_info = amim; 524280304Sjkim amim->references++; 525280304Sjkim } 52659191Skris 527280304Sjkim if ((mm = lh_MEM_insert(mh, m)) != NULL) { 528280304Sjkim /* Not good, but don't sweat it */ 529280304Sjkim if (mm->app_info != NULL) { 530280304Sjkim mm->app_info->references--; 531280304Sjkim } 532280304Sjkim OPENSSL_free(mm); 533280304Sjkim } 534280304Sjkim err: 535280304Sjkim MemCheck_on(); /* release MALLOC2 lock if num_disabled drops 536280304Sjkim * to 0 */ 537280304Sjkim } 538280304Sjkim break; 539280304Sjkim } 540280304Sjkim return; 541280304Sjkim} 54259191Skris 54359191Skrisvoid CRYPTO_dbg_free(void *addr, int before_p) 544280304Sjkim{ 545280304Sjkim MEM m, *mp; 54659191Skris 547280304Sjkim switch (before_p) { 548280304Sjkim case 0: 549280304Sjkim if (addr == NULL) 550280304Sjkim break; 55159191Skris 552280304Sjkim if (is_MemCheck_on() && (mh != NULL)) { 553280304Sjkim MemCheck_off(); /* make sure we hold MALLOC2 lock */ 55459191Skris 555280304Sjkim m.addr = addr; 556280304Sjkim mp = lh_MEM_delete(mh, &m); 557280304Sjkim if (mp != NULL) { 558109998Smarkm#ifdef LEVITTE_DEBUG_MEM 559280304Sjkim fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] - 0x%p (%d)\n", 560280304Sjkim mp->order, mp->addr, mp->num); 56159191Skris#endif 562280304Sjkim if (mp->app_info != NULL) 563280304Sjkim app_info_free(mp->app_info); 564280304Sjkim OPENSSL_free(mp); 565280304Sjkim } 56659191Skris 567280304Sjkim MemCheck_on(); /* release MALLOC2 lock if num_disabled drops 568280304Sjkim * to 0 */ 569280304Sjkim } 570280304Sjkim break; 571280304Sjkim case 1: 572280304Sjkim break; 573280304Sjkim } 574280304Sjkim} 57559191Skris 57659191Skrisvoid CRYPTO_dbg_realloc(void *addr1, void *addr2, int num, 577280304Sjkim const char *file, int line, int before_p) 578280304Sjkim{ 579280304Sjkim MEM m, *mp; 58059191Skris 581109998Smarkm#ifdef LEVITTE_DEBUG_MEM 582280304Sjkim fprintf(stderr, 583280304Sjkim "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n", 584280304Sjkim addr1, addr2, num, file, line, before_p); 58559191Skris#endif 58659191Skris 587280304Sjkim switch (before_p) { 588280304Sjkim case 0: 589280304Sjkim break; 590280304Sjkim case 1: 591280304Sjkim if (addr2 == NULL) 592280304Sjkim break; 59359191Skris 594280304Sjkim if (addr1 == NULL) { 595280304Sjkim CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p); 596280304Sjkim break; 597280304Sjkim } 59859191Skris 599280304Sjkim if (is_MemCheck_on()) { 600280304Sjkim MemCheck_off(); /* make sure we hold MALLOC2 lock */ 60159191Skris 602280304Sjkim m.addr = addr1; 603280304Sjkim mp = lh_MEM_delete(mh, &m); 604280304Sjkim if (mp != NULL) { 605109998Smarkm#ifdef LEVITTE_DEBUG_MEM 606280304Sjkim fprintf(stderr, 607280304Sjkim "LEVITTE_DEBUG_MEM: [%5ld] * 0x%p (%d) -> 0x%p (%d)\n", 608280304Sjkim mp->order, mp->addr, mp->num, addr2, num); 60959191Skris#endif 610280304Sjkim mp->addr = addr2; 611280304Sjkim mp->num = num; 612280304Sjkim (void)lh_MEM_insert(mh, mp); 613280304Sjkim } 61459191Skris 615280304Sjkim MemCheck_on(); /* release MALLOC2 lock if num_disabled drops 616280304Sjkim * to 0 */ 617280304Sjkim } 618280304Sjkim break; 619280304Sjkim } 620280304Sjkim return; 621280304Sjkim} 62259191Skris 623280304Sjkimtypedef struct mem_leak_st { 624280304Sjkim BIO *bio; 625280304Sjkim int chunks; 626280304Sjkim long bytes; 627280304Sjkim} MEM_LEAK; 62859191Skris 629238405Sjkimstatic void print_leak_doall_arg(const MEM *m, MEM_LEAK *l) 630280304Sjkim{ 631280304Sjkim char buf[1024]; 632280304Sjkim char *bufp = buf; 633280304Sjkim APP_INFO *amip; 634280304Sjkim int ami_cnt; 635280304Sjkim struct tm *lcl = NULL; 636280304Sjkim CRYPTO_THREADID ti; 63759191Skris 638127128Snectar#define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf)) 639127128Snectar 640280304Sjkim if (m->addr == (char *)l->bio) 641280304Sjkim return; 64259191Skris 643280304Sjkim if (options & V_CRYPTO_MDEBUG_TIME) { 644280304Sjkim lcl = localtime(&m->time); 64559191Skris 646280304Sjkim BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ", 647280304Sjkim lcl->tm_hour, lcl->tm_min, lcl->tm_sec); 648280304Sjkim bufp += strlen(bufp); 649280304Sjkim } 65059191Skris 651280304Sjkim BIO_snprintf(bufp, BUF_REMAIN, "%5lu file=%s, line=%d, ", 652280304Sjkim m->order, m->file, m->line); 653280304Sjkim bufp += strlen(bufp); 65459191Skris 655280304Sjkim if (options & V_CRYPTO_MDEBUG_THREAD) { 656280304Sjkim BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ", 657280304Sjkim CRYPTO_THREADID_hash(&m->threadid)); 658280304Sjkim bufp += strlen(bufp); 659280304Sjkim } 66059191Skris 661280304Sjkim BIO_snprintf(bufp, BUF_REMAIN, "number=%d, address=%08lX\n", 662280304Sjkim m->num, (unsigned long)m->addr); 663280304Sjkim bufp += strlen(bufp); 66459191Skris 665280304Sjkim BIO_puts(l->bio, buf); 666238405Sjkim 667280304Sjkim l->chunks++; 668280304Sjkim l->bytes += m->num; 66959191Skris 670280304Sjkim amip = m->app_info; 671280304Sjkim ami_cnt = 0; 672280304Sjkim if (!amip) 673280304Sjkim return; 674280304Sjkim CRYPTO_THREADID_cpy(&ti, &amip->threadid); 67559191Skris 676280304Sjkim do { 677280304Sjkim int buf_len; 678280304Sjkim int info_len; 679238405Sjkim 680280304Sjkim ami_cnt++; 681280304Sjkim memset(buf, '>', ami_cnt); 682280304Sjkim BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt, 683280304Sjkim " thread=%lu, file=%s, line=%d, info=\"", 684280304Sjkim CRYPTO_THREADID_hash(&amip->threadid), amip->file, 685280304Sjkim amip->line); 686280304Sjkim buf_len = strlen(buf); 687280304Sjkim info_len = strlen(amip->info); 688280304Sjkim if (128 - buf_len - 3 < info_len) { 689280304Sjkim memcpy(buf + buf_len, amip->info, 128 - buf_len - 3); 690280304Sjkim buf_len = 128 - 3; 691280304Sjkim } else { 692280304Sjkim BUF_strlcpy(buf + buf_len, amip->info, sizeof buf - buf_len); 693280304Sjkim buf_len = strlen(buf); 694280304Sjkim } 695280304Sjkim BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n"); 696280304Sjkim 697280304Sjkim BIO_puts(l->bio, buf); 698280304Sjkim 699280304Sjkim amip = amip->next; 700280304Sjkim } 701280304Sjkim while (amip && !CRYPTO_THREADID_cmp(&amip->threadid, &ti)); 702280304Sjkim 703109998Smarkm#ifdef LEVITTE_DEBUG_MEM 704280304Sjkim if (amip) { 705280304Sjkim fprintf(stderr, "Thread switch detected in backtrace!!!!\n"); 706280304Sjkim abort(); 707280304Sjkim } 70859191Skris#endif 709280304Sjkim} 71059191Skris 711238405Sjkimstatic IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM, MEM_LEAK) 712109998Smarkm 71359191Skrisvoid CRYPTO_mem_leaks(BIO *b) 714280304Sjkim{ 715280304Sjkim MEM_LEAK ml; 71659191Skris 717280304Sjkim if (mh == NULL && amih == NULL) 718280304Sjkim return; 71976866Skris 720280304Sjkim MemCheck_off(); /* obtain MALLOC2 lock */ 72176866Skris 722280304Sjkim ml.bio = b; 723280304Sjkim ml.bytes = 0; 724280304Sjkim ml.chunks = 0; 725280304Sjkim if (mh != NULL) 726280304Sjkim lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak), MEM_LEAK, &ml); 727280304Sjkim if (ml.chunks != 0) { 728280304Sjkim BIO_printf(b, "%ld bytes leaked in %d chunks\n", ml.bytes, ml.chunks); 729238405Sjkim#ifdef CRYPTO_MDEBUG_ABORT 730280304Sjkim abort(); 731238405Sjkim#endif 732280304Sjkim } else { 733280304Sjkim /* 734280304Sjkim * Make sure that, if we found no leaks, memory-leak debugging itself 735280304Sjkim * does not introduce memory leaks (which might irritate external 736280304Sjkim * debugging tools). (When someone enables leak checking, but does not 737280304Sjkim * call this function, we declare it to be their fault.) XXX This 738280304Sjkim * should be in CRYPTO_mem_leaks_cb, and CRYPTO_mem_leaks should be 739280304Sjkim * implemented by using CRYPTO_mem_leaks_cb. (Also there should be a 740280304Sjkim * variant of lh_doall_arg that takes a function pointer instead of a 741280304Sjkim * void *; this would obviate the ugly and illegal void_fn_to_char 742280304Sjkim * kludge in CRYPTO_mem_leaks_cb. Otherwise the code police will come 743280304Sjkim * and get us.) 744280304Sjkim */ 745280304Sjkim int old_mh_mode; 74672613Skris 747280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); 74872613Skris 749280304Sjkim /* 750280304Sjkim * avoid deadlock when lh_free() uses CRYPTO_dbg_free(), which uses 751280304Sjkim * CRYPTO_is_mem_check_on 752280304Sjkim */ 753280304Sjkim old_mh_mode = mh_mode; 754280304Sjkim mh_mode = CRYPTO_MEM_CHECK_OFF; 75572613Skris 756280304Sjkim if (mh != NULL) { 757280304Sjkim lh_MEM_free(mh); 758280304Sjkim mh = NULL; 759280304Sjkim } 760280304Sjkim if (amih != NULL) { 761280304Sjkim if (lh_APP_INFO_num_items(amih) == 0) { 762280304Sjkim lh_APP_INFO_free(amih); 763280304Sjkim amih = NULL; 764280304Sjkim } 765280304Sjkim } 76672613Skris 767280304Sjkim mh_mode = old_mh_mode; 768280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); 769280304Sjkim } 770280304Sjkim MemCheck_on(); /* release MALLOC2 lock */ 771280304Sjkim} 77259191Skris 773109998Smarkm#ifndef OPENSSL_NO_FP_API 77459191Skrisvoid CRYPTO_mem_leaks_fp(FILE *fp) 775280304Sjkim{ 776280304Sjkim BIO *b; 77759191Skris 778280304Sjkim if (mh == NULL) 779280304Sjkim return; 780280304Sjkim /* 781280304Sjkim * Need to turn off memory checking when allocated BIOs ... especially as 782280304Sjkim * we're creating them at a time when we're trying to check we've not 783280304Sjkim * left anything un-free()'d!! 784280304Sjkim */ 785280304Sjkim MemCheck_off(); 786280304Sjkim b = BIO_new(BIO_s_file()); 787280304Sjkim MemCheck_on(); 788280304Sjkim if (!b) 789280304Sjkim return; 790280304Sjkim BIO_set_fp(b, fp, BIO_NOCLOSE); 791280304Sjkim CRYPTO_mem_leaks(b); 792280304Sjkim BIO_free(b); 793280304Sjkim} 79459191Skris#endif 79559191Skris 796280304Sjkim/* 797280304Sjkim * FIXME: We really don't allow much to the callback. For example, it has no 798280304Sjkim * chance of reaching the info stack for the item it processes. Should it 799280304Sjkim * really be this way? -- Richard Levitte 800280304Sjkim */ 801280304Sjkim/* 802280304Sjkim * NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside 803280304Sjkim * crypto.h If this code is restructured, remove the callback type if it is 804280304Sjkim * no longer needed. -- Geoff Thorpe 805280304Sjkim */ 80668651Skris 807280304Sjkim/* 808280304Sjkim * Can't pass CRYPTO_MEM_LEAK_CB directly to lh_MEM_doall_arg because it is a 809280304Sjkim * function pointer and conversion to void * is prohibited. Instead pass its 810280304Sjkim * address 811238405Sjkim */ 812238405Sjkim 813238405Sjkimtypedef CRYPTO_MEM_LEAK_CB *PCRYPTO_MEM_LEAK_CB; 814238405Sjkim 815238405Sjkimstatic void cb_leak_doall_arg(const MEM *m, PCRYPTO_MEM_LEAK_CB *cb) 816280304Sjkim{ 817280304Sjkim (*cb) (m->order, m->file, m->line, m->num, m->addr); 818280304Sjkim} 81968651Skris 820238405Sjkimstatic IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM, PCRYPTO_MEM_LEAK_CB) 821109998Smarkm 822109998Smarkmvoid CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb) 823280304Sjkim{ 824280304Sjkim if (mh == NULL) 825280304Sjkim return; 826280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); 827280304Sjkim lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), PCRYPTO_MEM_LEAK_CB, 828280304Sjkim &cb); 829280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); 830280304Sjkim} 831