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. 859191Skris * 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). 1559191Skris * 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. 2259191Skris * 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 :-). 3759191Skris * 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)" 4059191Skris * 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. 5259191Skris * 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 66238405Sjkim * 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> 11459191Skris#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 12159191Skrisstatic int mh_mode=CRYPTO_MEM_CHECK_OFF; 12259191Skris/* The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE 12359191Skris * when the application asks for it (usually after library initialisation 12459191Skris * for which no book-keeping is desired). 12559191Skris * 12659191Skris * State CRYPTO_MEM_CHECK_ON exists only temporarily when the library 12759191Skris * thinks that certain allocations should not be checked (e.g. the data 12859191Skris * structures used for memory checking). It is not suitable as an initial 12959191Skris * state: the library will unexpectedly enable memory checking when it 13059191Skris * executes one of those sections that want to disable checking 13159191Skris * temporarily. 13259191Skris * 13359191Skris * State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes no sense whatsoever. 13459191Skris */ 13559191Skris 13659191Skrisstatic unsigned long order = 0; /* number of memory requests */ 13759191Skris 138238405SjkimDECLARE_LHASH_OF(MEM); 139238405Sjkimstatic LHASH_OF(MEM) *mh=NULL; /* hash-table of memory requests 140238405Sjkim * (address as key); access requires 141238405Sjkim * MALLOC2 lock */ 14259191Skris 143238405Sjkim 14459191Skristypedef struct app_mem_info_st 14559191Skris/* For application-defined information (static C-string `info') 14659191Skris * to be displayed in memory leak list. 14759191Skris * Each thread has its own stack. For applications, there is 14859191Skris * CRYPTO_push_info("...") to push an entry, 14959191Skris * CRYPTO_pop_info() to pop an entry, 15059191Skris * CRYPTO_remove_all_info() to pop all entries. 15159191Skris */ 152238405Sjkim { 153238405Sjkim CRYPTO_THREADID threadid; 15459191Skris const char *file; 15559191Skris int line; 15659191Skris const char *info; 15759191Skris struct app_mem_info_st *next; /* tail of thread's stack */ 15859191Skris int references; 15959191Skris } APP_INFO; 16059191Skris 161109998Smarkmstatic void app_info_free(APP_INFO *); 162109998Smarkm 163238405SjkimDECLARE_LHASH_OF(APP_INFO); 164238405Sjkimstatic LHASH_OF(APP_INFO) *amih=NULL; /* hash-table with those 165238405Sjkim * app_mem_info_st's that are at 166238405Sjkim * the top of their thread's 167238405Sjkim * stack (with `thread' as key); 168238405Sjkim * access requires MALLOC2 169238405Sjkim * lock */ 17059191Skris 17159191Skristypedef struct mem_st 17259191Skris/* memory-block description */ 17359191Skris { 17468651Skris void *addr; 17559191Skris int num; 17659191Skris const char *file; 17759191Skris int line; 178238405Sjkim CRYPTO_THREADID threadid; 17959191Skris unsigned long order; 18059191Skris time_t time; 18159191Skris APP_INFO *app_info; 18259191Skris } MEM; 18359191Skris 18459191Skrisstatic long options = /* extra information to be recorded */ 18559191Skris#if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL) 18659191Skris V_CRYPTO_MDEBUG_TIME | 18759191Skris#endif 18859191Skris#if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL) 18959191Skris V_CRYPTO_MDEBUG_THREAD | 19059191Skris#endif 19159191Skris 0; 19259191Skris 19359191Skris 19476866Skrisstatic unsigned int num_disable = 0; /* num_disable > 0 19576866Skris * iff 19676866Skris * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE) 19776866Skris */ 19859191Skris 199238405Sjkim/* Valid iff num_disable > 0. CRYPTO_LOCK_MALLOC2 is locked exactly in this 200238405Sjkim * case (by the thread named in disabling_thread). 201238405Sjkim */ 202238405Sjkimstatic CRYPTO_THREADID disabling_threadid; 203238405Sjkim 204109998Smarkmstatic void app_info_free(APP_INFO *inf) 205109998Smarkm { 206109998Smarkm if (--(inf->references) <= 0) 207109998Smarkm { 208109998Smarkm if (inf->next != NULL) 209109998Smarkm { 210109998Smarkm app_info_free(inf->next); 211109998Smarkm } 212109998Smarkm OPENSSL_free(inf); 213109998Smarkm } 214109998Smarkm } 215109998Smarkm 21659191Skrisint CRYPTO_mem_ctrl(int mode) 21759191Skris { 21859191Skris int ret=mh_mode; 21959191Skris 22059191Skris CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); 22159191Skris switch (mode) 22259191Skris { 22376866Skris /* for applications (not to be called while multiple threads 22476866Skris * use the library): */ 22559191Skris case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */ 22659191Skris mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE; 22776866Skris num_disable = 0; 22859191Skris break; 22959191Skris case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */ 23059191Skris mh_mode = 0; 23176866Skris num_disable = 0; /* should be true *before* MemCheck_stop is used, 23276866Skris or there'll be a lot of confusion */ 23359191Skris break; 23459191Skris 23559191Skris /* switch off temporarily (for library-internal use): */ 23659191Skris case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */ 23759191Skris if (mh_mode & CRYPTO_MEM_CHECK_ON) 23859191Skris { 239238405Sjkim CRYPTO_THREADID cur; 240238405Sjkim CRYPTO_THREADID_current(&cur); 241238405Sjkim if (!num_disable || CRYPTO_THREADID_cmp(&disabling_threadid, &cur)) /* otherwise we already have the MALLOC2 lock */ 24259191Skris { 24359191Skris /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while 24459191Skris * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if 24559191Skris * somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot release 24659191Skris * it because we block entry to this function). 24759191Skris * Give them a chance, first, and then claim the locks in 24859191Skris * appropriate order (long-time lock first). 24959191Skris */ 25059191Skris CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); 25159191Skris /* Note that after we have waited for CRYPTO_LOCK_MALLOC2 25259191Skris * and CRYPTO_LOCK_MALLOC, we'll still be in the right 25359191Skris * "case" and "if" branch because MemCheck_start and 25459191Skris * MemCheck_stop may never be used while there are multiple 25559191Skris * OpenSSL threads. */ 25659191Skris CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); 25759191Skris CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); 25876866Skris mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE; 259238405Sjkim CRYPTO_THREADID_cpy(&disabling_threadid, &cur); 26059191Skris } 26176866Skris num_disable++; 26259191Skris } 26359191Skris break; 26459191Skris case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */ 26559191Skris if (mh_mode & CRYPTO_MEM_CHECK_ON) 26659191Skris { 26776866Skris if (num_disable) /* always true, or something is going wrong */ 26859191Skris { 26976866Skris num_disable--; 27076866Skris if (num_disable == 0) 27176866Skris { 27276866Skris mh_mode|=CRYPTO_MEM_CHECK_ENABLE; 27376866Skris CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); 27476866Skris } 27559191Skris } 27659191Skris } 27759191Skris break; 27859191Skris 27959191Skris default: 28059191Skris break; 28159191Skris } 28259191Skris CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); 28359191Skris return(ret); 28459191Skris } 28559191Skris 28659191Skrisint CRYPTO_is_mem_check_on(void) 28759191Skris { 28859191Skris int ret = 0; 28959191Skris 29059191Skris if (mh_mode & CRYPTO_MEM_CHECK_ON) 29159191Skris { 292238405Sjkim CRYPTO_THREADID cur; 293238405Sjkim CRYPTO_THREADID_current(&cur); 29476866Skris CRYPTO_r_lock(CRYPTO_LOCK_MALLOC); 29559191Skris 29659191Skris ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE) 297238405Sjkim || CRYPTO_THREADID_cmp(&disabling_threadid, &cur); 29859191Skris 29976866Skris CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC); 30059191Skris } 30159191Skris return(ret); 30259191Skris } 30359191Skris 30459191Skris 30559191Skrisvoid CRYPTO_dbg_set_options(long bits) 30659191Skris { 30759191Skris options = bits; 30859191Skris } 30959191Skris 31059191Skrislong CRYPTO_dbg_get_options(void) 31159191Skris { 31259191Skris return options; 31359191Skris } 31459191Skris 315238405Sjkimstatic int mem_cmp(const MEM *a, const MEM *b) 31659191Skris { 317160814Ssimon#ifdef _WIN64 318238405Sjkim const char *ap=(const char *)a->addr, 319238405Sjkim *bp=(const char *)b->addr; 320238405Sjkim if (ap==bp) return 0; 321238405Sjkim else if (ap>bp) return 1; 322160814Ssimon else return -1; 323160814Ssimon#else 324238405Sjkim return (const char *)a->addr - (const char *)b->addr; 325160814Ssimon#endif 32659191Skris } 327238405Sjkimstatic IMPLEMENT_LHASH_COMP_FN(mem, MEM) 32859191Skris 329238405Sjkimstatic unsigned long mem_hash(const MEM *a) 33059191Skris { 33159191Skris unsigned long ret; 33259191Skris 333238405Sjkim ret=(unsigned long)a->addr; 33459191Skris 33559191Skris ret=ret*17851+(ret>>14)*7+(ret>>4)*251; 33659191Skris return(ret); 33759191Skris } 338238405Sjkimstatic IMPLEMENT_LHASH_HASH_FN(mem, MEM) 33959191Skris 340109998Smarkm/* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */ 341109998Smarkmstatic int app_info_cmp(const void *a_void, const void *b_void) 34259191Skris { 343238405Sjkim return CRYPTO_THREADID_cmp(&((const APP_INFO *)a_void)->threadid, 344238405Sjkim &((const APP_INFO *)b_void)->threadid); 34559191Skris } 346238405Sjkimstatic IMPLEMENT_LHASH_COMP_FN(app_info, APP_INFO) 34759191Skris 348238405Sjkimstatic unsigned long app_info_hash(const APP_INFO *a) 34959191Skris { 35059191Skris unsigned long ret; 35159191Skris 352238405Sjkim ret = CRYPTO_THREADID_hash(&a->threadid); 353238405Sjkim /* This is left in as a "who am I to question legacy?" measure */ 35459191Skris ret=ret*17851+(ret>>14)*7+(ret>>4)*251; 35559191Skris return(ret); 35659191Skris } 357238405Sjkimstatic IMPLEMENT_LHASH_HASH_FN(app_info, APP_INFO) 35859191Skris 359109998Smarkmstatic APP_INFO *pop_info(void) 36059191Skris { 36159191Skris APP_INFO tmp; 36259191Skris APP_INFO *ret = NULL; 36359191Skris 36459191Skris if (amih != NULL) 36559191Skris { 366238405Sjkim CRYPTO_THREADID_current(&tmp.threadid); 367238405Sjkim if ((ret=lh_APP_INFO_delete(amih,&tmp)) != NULL) 36859191Skris { 36959191Skris APP_INFO *next=ret->next; 37059191Skris 37159191Skris if (next != NULL) 37259191Skris { 37359191Skris next->references++; 374238405Sjkim (void)lh_APP_INFO_insert(amih,next); 37559191Skris } 376109998Smarkm#ifdef LEVITTE_DEBUG_MEM 377238405Sjkim if (CRYPTO_THREADID_cmp(&ret->threadid, &tmp.threadid)) 37859191Skris { 37959191Skris fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n", 380238405Sjkim CRYPTO_THREADID_hash(&ret->threadid), 381238405Sjkim CRYPTO_THREADID_hash(&tmp.threadid)); 38259191Skris abort(); 38359191Skris } 38459191Skris#endif 38559191Skris if (--(ret->references) <= 0) 38659191Skris { 38759191Skris ret->next = NULL; 38859191Skris if (next != NULL) 38959191Skris next->references--; 39068651Skris OPENSSL_free(ret); 39159191Skris } 39259191Skris } 39359191Skris } 39459191Skris return(ret); 39559191Skris } 39659191Skris 397238405Sjkimint CRYPTO_push_info_(const char *info, const char *file, int line) 39859191Skris { 39959191Skris APP_INFO *ami, *amim; 40059191Skris int ret=0; 40159191Skris 40259191Skris if (is_MemCheck_on()) 40359191Skris { 40476866Skris MemCheck_off(); /* obtain MALLOC2 lock */ 40559191Skris 40668651Skris if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL) 40759191Skris { 40859191Skris ret=0; 40959191Skris goto err; 41059191Skris } 41159191Skris if (amih == NULL) 41259191Skris { 413238405Sjkim if ((amih=lh_APP_INFO_new()) == NULL) 41459191Skris { 41568651Skris OPENSSL_free(ami); 41659191Skris ret=0; 41759191Skris goto err; 41859191Skris } 41959191Skris } 42059191Skris 421238405Sjkim CRYPTO_THREADID_current(&ami->threadid); 42259191Skris ami->file=file; 42359191Skris ami->line=line; 42459191Skris ami->info=info; 42559191Skris ami->references=1; 42659191Skris ami->next=NULL; 42759191Skris 428238405Sjkim if ((amim=lh_APP_INFO_insert(amih,ami)) != NULL) 42959191Skris { 430109998Smarkm#ifdef LEVITTE_DEBUG_MEM 431238405Sjkim if (CRYPTO_THREADID_cmp(&ami->threadid, &amim->threadid)) 43259191Skris { 43359191Skris fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n", 434238405Sjkim CRYPTO_THREADID_hash(&amim->threadid), 435238405Sjkim CRYPTO_THREADID_hash(&ami->threadid)); 43659191Skris abort(); 43759191Skris } 43859191Skris#endif 43959191Skris ami->next=amim; 44059191Skris } 44159191Skris err: 44276866Skris MemCheck_on(); /* release MALLOC2 lock */ 44359191Skris } 44459191Skris 44559191Skris return(ret); 44659191Skris } 44759191Skris 448238405Sjkimint CRYPTO_pop_info(void) 44959191Skris { 45059191Skris int ret=0; 45159191Skris 45259191Skris if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */ 45359191Skris { 45476866Skris MemCheck_off(); /* obtain MALLOC2 lock */ 45559191Skris 45659191Skris ret=(pop_info() != NULL); 45759191Skris 45876866Skris MemCheck_on(); /* release MALLOC2 lock */ 45959191Skris } 46059191Skris return(ret); 46159191Skris } 46259191Skris 463238405Sjkimint CRYPTO_remove_all_info(void) 46459191Skris { 46559191Skris int ret=0; 46659191Skris 46759191Skris if (is_MemCheck_on()) /* _must_ be true */ 46859191Skris { 46976866Skris MemCheck_off(); /* obtain MALLOC2 lock */ 47059191Skris 47159191Skris while(pop_info() != NULL) 47259191Skris ret++; 47359191Skris 47476866Skris MemCheck_on(); /* release MALLOC2 lock */ 47559191Skris } 47659191Skris return(ret); 47759191Skris } 47859191Skris 47959191Skris 48059191Skrisstatic unsigned long break_order_num=0; 48159191Skrisvoid CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line, 48259191Skris int before_p) 48359191Skris { 48459191Skris MEM *m,*mm; 48559191Skris APP_INFO tmp,*amim; 48659191Skris 48759191Skris switch(before_p & 127) 48859191Skris { 48959191Skris case 0: 49059191Skris break; 49159191Skris case 1: 49259191Skris if (addr == NULL) 49359191Skris break; 49459191Skris 49559191Skris if (is_MemCheck_on()) 49659191Skris { 49776866Skris MemCheck_off(); /* make sure we hold MALLOC2 lock */ 49868651Skris if ((m=(MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL) 49959191Skris { 50068651Skris OPENSSL_free(addr); 50176866Skris MemCheck_on(); /* release MALLOC2 lock 50276866Skris * if num_disabled drops to 0 */ 50359191Skris return; 50459191Skris } 50559191Skris if (mh == NULL) 50659191Skris { 507238405Sjkim if ((mh=lh_MEM_new()) == NULL) 50859191Skris { 50968651Skris OPENSSL_free(addr); 51068651Skris OPENSSL_free(m); 51159191Skris addr=NULL; 51259191Skris goto err; 51359191Skris } 51459191Skris } 51559191Skris 51659191Skris m->addr=addr; 51759191Skris m->file=file; 51859191Skris m->line=line; 51959191Skris m->num=num; 52059191Skris if (options & V_CRYPTO_MDEBUG_THREAD) 521238405Sjkim CRYPTO_THREADID_current(&m->threadid); 52259191Skris else 523238405Sjkim memset(&m->threadid, 0, sizeof(m->threadid)); 52459191Skris 52559191Skris if (order == break_order_num) 52659191Skris { 52759191Skris /* BREAK HERE */ 52859191Skris m->order=order; 52959191Skris } 53059191Skris m->order=order++; 531109998Smarkm#ifdef LEVITTE_DEBUG_MEM 532238405Sjkim fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] %c 0x%p (%d)\n", 53359191Skris m->order, 53459191Skris (before_p & 128) ? '*' : '+', 53559191Skris m->addr, m->num); 53659191Skris#endif 53759191Skris if (options & V_CRYPTO_MDEBUG_TIME) 53859191Skris m->time=time(NULL); 53959191Skris else 54059191Skris m->time=0; 54159191Skris 542238405Sjkim CRYPTO_THREADID_current(&tmp.threadid); 54359191Skris m->app_info=NULL; 54459191Skris if (amih != NULL 545238405Sjkim && (amim=lh_APP_INFO_retrieve(amih,&tmp)) != NULL) 54659191Skris { 54759191Skris m->app_info = amim; 54859191Skris amim->references++; 54959191Skris } 55059191Skris 551238405Sjkim if ((mm=lh_MEM_insert(mh, m)) != NULL) 55259191Skris { 55359191Skris /* Not good, but don't sweat it */ 55459191Skris if (mm->app_info != NULL) 55559191Skris { 55659191Skris mm->app_info->references--; 55759191Skris } 55868651Skris OPENSSL_free(mm); 55959191Skris } 56059191Skris err: 56176866Skris MemCheck_on(); /* release MALLOC2 lock 56276866Skris * if num_disabled drops to 0 */ 56359191Skris } 56459191Skris break; 56559191Skris } 56659191Skris return; 56759191Skris } 56859191Skris 56959191Skrisvoid CRYPTO_dbg_free(void *addr, int before_p) 57059191Skris { 57159191Skris MEM m,*mp; 57259191Skris 57359191Skris switch(before_p) 57459191Skris { 57559191Skris case 0: 57659191Skris if (addr == NULL) 57759191Skris break; 57859191Skris 57959191Skris if (is_MemCheck_on() && (mh != NULL)) 58059191Skris { 58176866Skris MemCheck_off(); /* make sure we hold MALLOC2 lock */ 58259191Skris 58359191Skris m.addr=addr; 584238405Sjkim mp=lh_MEM_delete(mh,&m); 58559191Skris if (mp != NULL) 58659191Skris { 587109998Smarkm#ifdef LEVITTE_DEBUG_MEM 588238405Sjkim fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] - 0x%p (%d)\n", 58959191Skris mp->order, mp->addr, mp->num); 59059191Skris#endif 59159191Skris if (mp->app_info != NULL) 592109998Smarkm app_info_free(mp->app_info); 59368651Skris OPENSSL_free(mp); 59459191Skris } 59559191Skris 59676866Skris MemCheck_on(); /* release MALLOC2 lock 59776866Skris * if num_disabled drops to 0 */ 59859191Skris } 59959191Skris break; 60059191Skris case 1: 60159191Skris break; 60259191Skris } 60359191Skris } 60459191Skris 60559191Skrisvoid CRYPTO_dbg_realloc(void *addr1, void *addr2, int num, 60659191Skris const char *file, int line, int before_p) 60759191Skris { 60859191Skris MEM m,*mp; 60959191Skris 610109998Smarkm#ifdef LEVITTE_DEBUG_MEM 611109998Smarkm fprintf(stderr, "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n", 61259191Skris addr1, addr2, num, file, line, before_p); 61359191Skris#endif 61459191Skris 61559191Skris switch(before_p) 61659191Skris { 61759191Skris case 0: 61859191Skris break; 61959191Skris case 1: 62059191Skris if (addr2 == NULL) 62159191Skris break; 62259191Skris 62359191Skris if (addr1 == NULL) 62459191Skris { 62559191Skris CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p); 62659191Skris break; 62759191Skris } 62859191Skris 62959191Skris if (is_MemCheck_on()) 63059191Skris { 63176866Skris MemCheck_off(); /* make sure we hold MALLOC2 lock */ 63259191Skris 63359191Skris m.addr=addr1; 634238405Sjkim mp=lh_MEM_delete(mh,&m); 63559191Skris if (mp != NULL) 63659191Skris { 637109998Smarkm#ifdef LEVITTE_DEBUG_MEM 638238405Sjkim fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] * 0x%p (%d) -> 0x%p (%d)\n", 63959191Skris mp->order, 64059191Skris mp->addr, mp->num, 64159191Skris addr2, num); 64259191Skris#endif 64359191Skris mp->addr=addr2; 64459191Skris mp->num=num; 645238405Sjkim (void)lh_MEM_insert(mh,mp); 64659191Skris } 64759191Skris 64876866Skris MemCheck_on(); /* release MALLOC2 lock 64976866Skris * if num_disabled drops to 0 */ 65059191Skris } 65159191Skris break; 65259191Skris } 65359191Skris return; 65459191Skris } 65559191Skris 65659191Skris 65759191Skristypedef struct mem_leak_st 65859191Skris { 65959191Skris BIO *bio; 66059191Skris int chunks; 66159191Skris long bytes; 66259191Skris } MEM_LEAK; 66359191Skris 664238405Sjkimstatic void print_leak_doall_arg(const MEM *m, MEM_LEAK *l) 66559191Skris { 66659191Skris char buf[1024]; 66759191Skris char *bufp = buf; 66859191Skris APP_INFO *amip; 66959191Skris int ami_cnt; 67059191Skris struct tm *lcl = NULL; 671238405Sjkim CRYPTO_THREADID ti; 67259191Skris 673127128Snectar#define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf)) 674127128Snectar 67559191Skris if(m->addr == (char *)l->bio) 67659191Skris return; 67759191Skris 67859191Skris if (options & V_CRYPTO_MDEBUG_TIME) 67959191Skris { 68059191Skris lcl = localtime(&m->time); 68159191Skris 682127128Snectar BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ", 68359191Skris lcl->tm_hour,lcl->tm_min,lcl->tm_sec); 68459191Skris bufp += strlen(bufp); 68559191Skris } 68659191Skris 687127128Snectar BIO_snprintf(bufp, BUF_REMAIN, "%5lu file=%s, line=%d, ", 68859191Skris m->order,m->file,m->line); 68959191Skris bufp += strlen(bufp); 69059191Skris 69159191Skris if (options & V_CRYPTO_MDEBUG_THREAD) 69259191Skris { 693238405Sjkim BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ", 694238405Sjkim CRYPTO_THREADID_hash(&m->threadid)); 69559191Skris bufp += strlen(bufp); 69659191Skris } 69759191Skris 698127128Snectar BIO_snprintf(bufp, BUF_REMAIN, "number=%d, address=%08lX\n", 69959191Skris m->num,(unsigned long)m->addr); 70059191Skris bufp += strlen(bufp); 70159191Skris 70259191Skris BIO_puts(l->bio,buf); 70359191Skris 70459191Skris l->chunks++; 70559191Skris l->bytes+=m->num; 70659191Skris 70759191Skris amip=m->app_info; 70859191Skris ami_cnt=0; 70959191Skris if (!amip) 71059191Skris return; 711238405Sjkim CRYPTO_THREADID_cpy(&ti, &amip->threadid); 712238405Sjkim 71359191Skris do 71459191Skris { 71559191Skris int buf_len; 71659191Skris int info_len; 71759191Skris 71859191Skris ami_cnt++; 71959191Skris memset(buf,'>',ami_cnt); 720127128Snectar BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt, 72159191Skris " thread=%lu, file=%s, line=%d, info=\"", 722238405Sjkim CRYPTO_THREADID_hash(&amip->threadid), amip->file, 723238405Sjkim amip->line); 72459191Skris buf_len=strlen(buf); 72559191Skris info_len=strlen(amip->info); 72659191Skris if (128 - buf_len - 3 < info_len) 72759191Skris { 72859191Skris memcpy(buf + buf_len, amip->info, 128 - buf_len - 3); 72959191Skris buf_len = 128 - 3; 73059191Skris } 73159191Skris else 73259191Skris { 733127128Snectar BUF_strlcpy(buf + buf_len, amip->info, 734127128Snectar sizeof buf - buf_len); 73559191Skris buf_len = strlen(buf); 73659191Skris } 737127128Snectar BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n"); 73859191Skris 73959191Skris BIO_puts(l->bio,buf); 74059191Skris 74159191Skris amip = amip->next; 74259191Skris } 743238405Sjkim while(amip && !CRYPTO_THREADID_cmp(&amip->threadid, &ti)); 744238405Sjkim 745109998Smarkm#ifdef LEVITTE_DEBUG_MEM 74659191Skris if (amip) 74759191Skris { 74859191Skris fprintf(stderr, "Thread switch detected in backtrace!!!!\n"); 74959191Skris abort(); 75059191Skris } 75159191Skris#endif 75259191Skris } 75359191Skris 754238405Sjkimstatic IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM, MEM_LEAK) 755109998Smarkm 75659191Skrisvoid CRYPTO_mem_leaks(BIO *b) 75759191Skris { 75859191Skris MEM_LEAK ml; 75959191Skris 76059191Skris if (mh == NULL && amih == NULL) 76159191Skris return; 76276866Skris 76376866Skris MemCheck_off(); /* obtain MALLOC2 lock */ 76476866Skris 76559191Skris ml.bio=b; 76659191Skris ml.bytes=0; 76759191Skris ml.chunks=0; 76859191Skris if (mh != NULL) 769238405Sjkim lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak), MEM_LEAK, 770238405Sjkim &ml); 77159191Skris if (ml.chunks != 0) 77259191Skris { 773109998Smarkm BIO_printf(b,"%ld bytes leaked in %d chunks\n", 774109998Smarkm ml.bytes,ml.chunks); 775238405Sjkim#ifdef CRYPTO_MDEBUG_ABORT 776238405Sjkim abort(); 777238405Sjkim#endif 77859191Skris } 77959191Skris else 78059191Skris { 78159191Skris /* Make sure that, if we found no leaks, memory-leak debugging itself 78259191Skris * does not introduce memory leaks (which might irritate 78359191Skris * external debugging tools). 78459191Skris * (When someone enables leak checking, but does not call 78559191Skris * this function, we declare it to be their fault.) 78659191Skris * 78759191Skris * XXX This should be in CRYPTO_mem_leaks_cb, 78859191Skris * and CRYPTO_mem_leaks should be implemented by 78959191Skris * using CRYPTO_mem_leaks_cb. 790238405Sjkim * (Also there should be a variant of lh_doall_arg 79159191Skris * that takes a function pointer instead of a void *; 79259191Skris * this would obviate the ugly and illegal 79359191Skris * void_fn_to_char kludge in CRYPTO_mem_leaks_cb. 79459191Skris * Otherwise the code police will come and get us.) 79559191Skris */ 79672613Skris int old_mh_mode; 79772613Skris 79859191Skris CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); 79972613Skris 80072613Skris /* avoid deadlock when lh_free() uses CRYPTO_dbg_free(), 80172613Skris * which uses CRYPTO_is_mem_check_on */ 80272613Skris old_mh_mode = mh_mode; 80372613Skris mh_mode = CRYPTO_MEM_CHECK_OFF; 80472613Skris 80559191Skris if (mh != NULL) 80659191Skris { 807238405Sjkim lh_MEM_free(mh); 80859191Skris mh = NULL; 80959191Skris } 81059191Skris if (amih != NULL) 81159191Skris { 812238405Sjkim if (lh_APP_INFO_num_items(amih) == 0) 81359191Skris { 814238405Sjkim lh_APP_INFO_free(amih); 81559191Skris amih = NULL; 81659191Skris } 81759191Skris } 81872613Skris 81972613Skris mh_mode = old_mh_mode; 82059191Skris CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); 82159191Skris } 82276866Skris MemCheck_on(); /* release MALLOC2 lock */ 82359191Skris } 82459191Skris 825109998Smarkm#ifndef OPENSSL_NO_FP_API 82659191Skrisvoid CRYPTO_mem_leaks_fp(FILE *fp) 82759191Skris { 82859191Skris BIO *b; 82959191Skris 83059191Skris if (mh == NULL) return; 831109998Smarkm /* Need to turn off memory checking when allocated BIOs ... especially 832109998Smarkm * as we're creating them at a time when we're trying to check we've not 833109998Smarkm * left anything un-free()'d!! */ 834109998Smarkm MemCheck_off(); 835109998Smarkm b = BIO_new(BIO_s_file()); 836109998Smarkm MemCheck_on(); 837109998Smarkm if(!b) return; 83859191Skris BIO_set_fp(b,fp,BIO_NOCLOSE); 83959191Skris CRYPTO_mem_leaks(b); 84059191Skris BIO_free(b); 84159191Skris } 84259191Skris#endif 84359191Skris 84468651Skris 84568651Skris 84668651Skris/* FIXME: We really don't allow much to the callback. For example, it has 84768651Skris no chance of reaching the info stack for the item it processes. Should 84868651Skris it really be this way? -- Richard Levitte */ 849109998Smarkm/* NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside crypto.h 850109998Smarkm * If this code is restructured, remove the callback type if it is no longer 851109998Smarkm * needed. -- Geoff Thorpe */ 852238405Sjkim 853238405Sjkim/* Can't pass CRYPTO_MEM_LEAK_CB directly to lh_MEM_doall_arg because it 854238405Sjkim * is a function pointer and conversion to void * is prohibited. Instead 855238405Sjkim * pass its address 856238405Sjkim */ 857238405Sjkim 858238405Sjkimtypedef CRYPTO_MEM_LEAK_CB *PCRYPTO_MEM_LEAK_CB; 859238405Sjkim 860238405Sjkimstatic void cb_leak_doall_arg(const MEM *m, PCRYPTO_MEM_LEAK_CB *cb) 86168651Skris { 862238405Sjkim (*cb)(m->order,m->file,m->line,m->num,m->addr); 86368651Skris } 86468651Skris 865238405Sjkimstatic IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM, PCRYPTO_MEM_LEAK_CB) 866109998Smarkm 867109998Smarkmvoid CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb) 86868651Skris { 86968651Skris if (mh == NULL) return; 87068651Skris CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); 871238405Sjkim lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), PCRYPTO_MEM_LEAK_CB, 872238405Sjkim &cb); 87368651Skris CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); 87468651Skris } 875