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