xref: /onnv-gate/usr/src/common/openssl/crypto/mem_dbg.c (revision 2139:6243c3338933)
10Sstevel@tonic-gate /* crypto/mem_dbg.c */
20Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
30Sstevel@tonic-gate  * All rights reserved.
40Sstevel@tonic-gate  *
50Sstevel@tonic-gate  * This package is an SSL implementation written
60Sstevel@tonic-gate  * by Eric Young (eay@cryptsoft.com).
70Sstevel@tonic-gate  * The implementation was written so as to conform with Netscapes SSL.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * This library is free for commercial and non-commercial use as long as
100Sstevel@tonic-gate  * the following conditions are aheared to.  The following conditions
110Sstevel@tonic-gate  * apply to all code found in this distribution, be it the RC4, RSA,
120Sstevel@tonic-gate  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
130Sstevel@tonic-gate  * included with this distribution is covered by the same copyright terms
140Sstevel@tonic-gate  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
150Sstevel@tonic-gate  *
160Sstevel@tonic-gate  * Copyright remains Eric Young's, and as such any Copyright notices in
170Sstevel@tonic-gate  * the code are not to be removed.
180Sstevel@tonic-gate  * If this package is used in a product, Eric Young should be given attribution
190Sstevel@tonic-gate  * as the author of the parts of the library used.
200Sstevel@tonic-gate  * This can be in the form of a textual message at program startup or
210Sstevel@tonic-gate  * in documentation (online or textual) provided with the package.
220Sstevel@tonic-gate  *
230Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
240Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
250Sstevel@tonic-gate  * are met:
260Sstevel@tonic-gate  * 1. Redistributions of source code must retain the copyright
270Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
280Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
290Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
300Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
310Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
320Sstevel@tonic-gate  *    must display the following acknowledgement:
330Sstevel@tonic-gate  *    "This product includes cryptographic software written by
340Sstevel@tonic-gate  *     Eric Young (eay@cryptsoft.com)"
350Sstevel@tonic-gate  *    The word 'cryptographic' can be left out if the rouines from the library
360Sstevel@tonic-gate  *    being used are not cryptographic related :-).
370Sstevel@tonic-gate  * 4. If you include any Windows specific code (or a derivative thereof) from
380Sstevel@tonic-gate  *    the apps directory (application code) you must include an acknowledgement:
390Sstevel@tonic-gate  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
400Sstevel@tonic-gate  *
410Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
420Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
430Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
440Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
450Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
460Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
470Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
480Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
490Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
500Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
510Sstevel@tonic-gate  * SUCH DAMAGE.
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * The licence and distribution terms for any publically available version or
540Sstevel@tonic-gate  * derivative of this code cannot be changed.  i.e. this code cannot simply be
550Sstevel@tonic-gate  * copied and put under another distribution licence
560Sstevel@tonic-gate  * [including the GNU Public Licence.]
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate 
590Sstevel@tonic-gate #include <stdio.h>
600Sstevel@tonic-gate #include <stdlib.h>
610Sstevel@tonic-gate #include <time.h>
62*2139Sjp161948 #include "cryptlib.h"
630Sstevel@tonic-gate #include <openssl/crypto.h>
640Sstevel@tonic-gate #include <openssl/buffer.h>
650Sstevel@tonic-gate #include <openssl/bio.h>
660Sstevel@tonic-gate #include <openssl/lhash.h>
670Sstevel@tonic-gate 
680Sstevel@tonic-gate static int mh_mode=CRYPTO_MEM_CHECK_OFF;
690Sstevel@tonic-gate /* The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE
700Sstevel@tonic-gate  * when the application asks for it (usually after library initialisation
710Sstevel@tonic-gate  * for which no book-keeping is desired).
720Sstevel@tonic-gate  *
730Sstevel@tonic-gate  * State CRYPTO_MEM_CHECK_ON exists only temporarily when the library
740Sstevel@tonic-gate  * thinks that certain allocations should not be checked (e.g. the data
750Sstevel@tonic-gate  * structures used for memory checking).  It is not suitable as an initial
760Sstevel@tonic-gate  * state: the library will unexpectedly enable memory checking when it
770Sstevel@tonic-gate  * executes one of those sections that want to disable checking
780Sstevel@tonic-gate  * temporarily.
790Sstevel@tonic-gate  *
800Sstevel@tonic-gate  * State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes no sense whatsoever.
810Sstevel@tonic-gate  */
820Sstevel@tonic-gate 
830Sstevel@tonic-gate static unsigned long order = 0; /* number of memory requests */
840Sstevel@tonic-gate static LHASH *mh=NULL; /* hash-table of memory requests (address as key);
850Sstevel@tonic-gate                         * access requires MALLOC2 lock */
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 
880Sstevel@tonic-gate typedef struct app_mem_info_st
890Sstevel@tonic-gate /* For application-defined information (static C-string `info')
900Sstevel@tonic-gate  * to be displayed in memory leak list.
910Sstevel@tonic-gate  * Each thread has its own stack.  For applications, there is
920Sstevel@tonic-gate  *   CRYPTO_push_info("...")     to push an entry,
930Sstevel@tonic-gate  *   CRYPTO_pop_info()           to pop an entry,
940Sstevel@tonic-gate  *   CRYPTO_remove_all_info()    to pop all entries.
950Sstevel@tonic-gate  */
960Sstevel@tonic-gate 	{
970Sstevel@tonic-gate 	unsigned long thread;
980Sstevel@tonic-gate 	const char *file;
990Sstevel@tonic-gate 	int line;
1000Sstevel@tonic-gate 	const char *info;
1010Sstevel@tonic-gate 	struct app_mem_info_st *next; /* tail of thread's stack */
1020Sstevel@tonic-gate 	int references;
1030Sstevel@tonic-gate 	} APP_INFO;
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate static void app_info_free(APP_INFO *);
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's
1080Sstevel@tonic-gate                           * that are at the top of their thread's stack
1090Sstevel@tonic-gate                           * (with `thread' as key);
1100Sstevel@tonic-gate                           * access requires MALLOC2 lock */
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate typedef struct mem_st
1130Sstevel@tonic-gate /* memory-block description */
1140Sstevel@tonic-gate 	{
1150Sstevel@tonic-gate 	void *addr;
1160Sstevel@tonic-gate 	int num;
1170Sstevel@tonic-gate 	const char *file;
1180Sstevel@tonic-gate 	int line;
1190Sstevel@tonic-gate 	unsigned long thread;
1200Sstevel@tonic-gate 	unsigned long order;
1210Sstevel@tonic-gate 	time_t time;
1220Sstevel@tonic-gate 	APP_INFO *app_info;
1230Sstevel@tonic-gate 	} MEM;
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate static long options =             /* extra information to be recorded */
1260Sstevel@tonic-gate #if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL)
1270Sstevel@tonic-gate 	V_CRYPTO_MDEBUG_TIME |
1280Sstevel@tonic-gate #endif
1290Sstevel@tonic-gate #if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL)
1300Sstevel@tonic-gate 	V_CRYPTO_MDEBUG_THREAD |
1310Sstevel@tonic-gate #endif
1320Sstevel@tonic-gate 	0;
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate static unsigned int num_disable = 0; /* num_disable > 0
1360Sstevel@tonic-gate                                       *     iff
1370Sstevel@tonic-gate                                       * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE)
1380Sstevel@tonic-gate                                       */
1390Sstevel@tonic-gate static unsigned long disabling_thread = 0; /* Valid iff num_disable > 0.
1400Sstevel@tonic-gate                                             * CRYPTO_LOCK_MALLOC2 is locked
1410Sstevel@tonic-gate                                             * exactly in this case (by the
1420Sstevel@tonic-gate                                             * thread named in disabling_thread).
1430Sstevel@tonic-gate                                             */
1440Sstevel@tonic-gate 
app_info_free(APP_INFO * inf)1450Sstevel@tonic-gate static void app_info_free(APP_INFO *inf)
1460Sstevel@tonic-gate 	{
1470Sstevel@tonic-gate 	if (--(inf->references) <= 0)
1480Sstevel@tonic-gate 		{
1490Sstevel@tonic-gate 		if (inf->next != NULL)
1500Sstevel@tonic-gate 			{
1510Sstevel@tonic-gate 			app_info_free(inf->next);
1520Sstevel@tonic-gate 			}
1530Sstevel@tonic-gate 		OPENSSL_free(inf);
1540Sstevel@tonic-gate 		}
1550Sstevel@tonic-gate 	}
1560Sstevel@tonic-gate 
CRYPTO_mem_ctrl(int mode)1570Sstevel@tonic-gate int CRYPTO_mem_ctrl(int mode)
1580Sstevel@tonic-gate 	{
1590Sstevel@tonic-gate 	int ret=mh_mode;
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
1620Sstevel@tonic-gate 	switch (mode)
1630Sstevel@tonic-gate 		{
1640Sstevel@tonic-gate 	/* for applications (not to be called while multiple threads
1650Sstevel@tonic-gate 	 * use the library): */
1660Sstevel@tonic-gate 	case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */
1670Sstevel@tonic-gate 		mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
1680Sstevel@tonic-gate 		num_disable = 0;
1690Sstevel@tonic-gate 		break;
1700Sstevel@tonic-gate 	case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
1710Sstevel@tonic-gate 		mh_mode = 0;
1720Sstevel@tonic-gate 		num_disable = 0; /* should be true *before* MemCheck_stop is used,
1730Sstevel@tonic-gate 		                    or there'll be a lot of confusion */
1740Sstevel@tonic-gate 		break;
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	/* switch off temporarily (for library-internal use): */
1770Sstevel@tonic-gate 	case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
1780Sstevel@tonic-gate 		if (mh_mode & CRYPTO_MEM_CHECK_ON)
1790Sstevel@tonic-gate 			{
1800Sstevel@tonic-gate 			if (!num_disable || (disabling_thread != CRYPTO_thread_id())) /* otherwise we already have the MALLOC2 lock */
1810Sstevel@tonic-gate 				{
1820Sstevel@tonic-gate 				/* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while
1830Sstevel@tonic-gate 				 * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if
1840Sstevel@tonic-gate 				 * somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot release
1850Sstevel@tonic-gate 				 * it because we block entry to this function).
1860Sstevel@tonic-gate 				 * Give them a chance, first, and then claim the locks in
1870Sstevel@tonic-gate 				 * appropriate order (long-time lock first).
1880Sstevel@tonic-gate 				 */
1890Sstevel@tonic-gate 				CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
1900Sstevel@tonic-gate 				/* Note that after we have waited for CRYPTO_LOCK_MALLOC2
1910Sstevel@tonic-gate 				 * and CRYPTO_LOCK_MALLOC, we'll still be in the right
1920Sstevel@tonic-gate 				 * "case" and "if" branch because MemCheck_start and
1930Sstevel@tonic-gate 				 * MemCheck_stop may never be used while there are multiple
1940Sstevel@tonic-gate 				 * OpenSSL threads. */
1950Sstevel@tonic-gate 				CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
1960Sstevel@tonic-gate 				CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
1970Sstevel@tonic-gate 				mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE;
1980Sstevel@tonic-gate 				disabling_thread=CRYPTO_thread_id();
1990Sstevel@tonic-gate 				}
2000Sstevel@tonic-gate 			num_disable++;
2010Sstevel@tonic-gate 			}
2020Sstevel@tonic-gate 		break;
2030Sstevel@tonic-gate 	case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */
2040Sstevel@tonic-gate 		if (mh_mode & CRYPTO_MEM_CHECK_ON)
2050Sstevel@tonic-gate 			{
2060Sstevel@tonic-gate 			if (num_disable) /* always true, or something is going wrong */
2070Sstevel@tonic-gate 				{
2080Sstevel@tonic-gate 				num_disable--;
2090Sstevel@tonic-gate 				if (num_disable == 0)
2100Sstevel@tonic-gate 					{
2110Sstevel@tonic-gate 					mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
2120Sstevel@tonic-gate 					CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
2130Sstevel@tonic-gate 					}
2140Sstevel@tonic-gate 				}
2150Sstevel@tonic-gate 			}
2160Sstevel@tonic-gate 		break;
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	default:
2190Sstevel@tonic-gate 		break;
2200Sstevel@tonic-gate 		}
2210Sstevel@tonic-gate 	CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
2220Sstevel@tonic-gate 	return(ret);
2230Sstevel@tonic-gate 	}
2240Sstevel@tonic-gate 
CRYPTO_is_mem_check_on(void)2250Sstevel@tonic-gate int CRYPTO_is_mem_check_on(void)
2260Sstevel@tonic-gate 	{
2270Sstevel@tonic-gate 	int ret = 0;
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 	if (mh_mode & CRYPTO_MEM_CHECK_ON)
2300Sstevel@tonic-gate 		{
2310Sstevel@tonic-gate 		CRYPTO_r_lock(CRYPTO_LOCK_MALLOC);
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 		ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
2340Sstevel@tonic-gate 			|| (disabling_thread != CRYPTO_thread_id());
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 		CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC);
2370Sstevel@tonic-gate 		}
2380Sstevel@tonic-gate 	return(ret);
2390Sstevel@tonic-gate 	}
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 
CRYPTO_dbg_set_options(long bits)2420Sstevel@tonic-gate void CRYPTO_dbg_set_options(long bits)
2430Sstevel@tonic-gate 	{
2440Sstevel@tonic-gate 	options = bits;
2450Sstevel@tonic-gate 	}
2460Sstevel@tonic-gate 
CRYPTO_dbg_get_options(void)2470Sstevel@tonic-gate long CRYPTO_dbg_get_options(void)
2480Sstevel@tonic-gate 	{
2490Sstevel@tonic-gate 	return options;
2500Sstevel@tonic-gate 	}
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate /* static int mem_cmp(MEM *a, MEM *b) */
mem_cmp(const void * a_void,const void * b_void)2530Sstevel@tonic-gate static int mem_cmp(const void *a_void, const void *b_void)
2540Sstevel@tonic-gate 	{
255*2139Sjp161948 #ifdef _WIN64
256*2139Sjp161948 	const char *a=(const char *)((const MEM *)a_void)->addr,
257*2139Sjp161948 		   *b=(const char *)((const MEM *)b_void)->addr;
258*2139Sjp161948 	if (a==b)	return 0;
259*2139Sjp161948 	else if (a>b)	return 1;
260*2139Sjp161948 	else		return -1;
261*2139Sjp161948 #else
2620Sstevel@tonic-gate 	return((const char *)((const MEM *)a_void)->addr
2630Sstevel@tonic-gate 		- (const char *)((const MEM *)b_void)->addr);
264*2139Sjp161948 #endif
2650Sstevel@tonic-gate 	}
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate /* static unsigned long mem_hash(MEM *a) */
mem_hash(const void * a_void)2680Sstevel@tonic-gate static unsigned long mem_hash(const void *a_void)
2690Sstevel@tonic-gate 	{
2700Sstevel@tonic-gate 	unsigned long ret;
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 	ret=(unsigned long)((const MEM *)a_void)->addr;
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
2750Sstevel@tonic-gate 	return(ret);
2760Sstevel@tonic-gate 	}
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate /* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */
app_info_cmp(const void * a_void,const void * b_void)2790Sstevel@tonic-gate static int app_info_cmp(const void *a_void, const void *b_void)
2800Sstevel@tonic-gate 	{
2810Sstevel@tonic-gate 	return(((const APP_INFO *)a_void)->thread
2820Sstevel@tonic-gate 		!= ((const APP_INFO *)b_void)->thread);
2830Sstevel@tonic-gate 	}
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate /* static unsigned long app_info_hash(APP_INFO *a) */
app_info_hash(const void * a_void)2860Sstevel@tonic-gate static unsigned long app_info_hash(const void *a_void)
2870Sstevel@tonic-gate 	{
2880Sstevel@tonic-gate 	unsigned long ret;
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 	ret=(unsigned long)((const APP_INFO *)a_void)->thread;
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
2930Sstevel@tonic-gate 	return(ret);
2940Sstevel@tonic-gate 	}
2950Sstevel@tonic-gate 
pop_info(void)2960Sstevel@tonic-gate static APP_INFO *pop_info(void)
2970Sstevel@tonic-gate 	{
2980Sstevel@tonic-gate 	APP_INFO tmp;
2990Sstevel@tonic-gate 	APP_INFO *ret = NULL;
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate 	if (amih != NULL)
3020Sstevel@tonic-gate 		{
3030Sstevel@tonic-gate 		tmp.thread=CRYPTO_thread_id();
3040Sstevel@tonic-gate 		if ((ret=(APP_INFO *)lh_delete(amih,&tmp)) != NULL)
3050Sstevel@tonic-gate 			{
3060Sstevel@tonic-gate 			APP_INFO *next=ret->next;
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 			if (next != NULL)
3090Sstevel@tonic-gate 				{
3100Sstevel@tonic-gate 				next->references++;
3110Sstevel@tonic-gate 				lh_insert(amih,(char *)next);
3120Sstevel@tonic-gate 				}
3130Sstevel@tonic-gate #ifdef LEVITTE_DEBUG_MEM
3140Sstevel@tonic-gate 			if (ret->thread != tmp.thread)
3150Sstevel@tonic-gate 				{
3160Sstevel@tonic-gate 				fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
3170Sstevel@tonic-gate 					ret->thread, tmp.thread);
3180Sstevel@tonic-gate 				abort();
3190Sstevel@tonic-gate 				}
3200Sstevel@tonic-gate #endif
3210Sstevel@tonic-gate 			if (--(ret->references) <= 0)
3220Sstevel@tonic-gate 				{
3230Sstevel@tonic-gate 				ret->next = NULL;
3240Sstevel@tonic-gate 				if (next != NULL)
3250Sstevel@tonic-gate 					next->references--;
3260Sstevel@tonic-gate 				OPENSSL_free(ret);
3270Sstevel@tonic-gate 				}
3280Sstevel@tonic-gate 			}
3290Sstevel@tonic-gate 		}
3300Sstevel@tonic-gate 	return(ret);
3310Sstevel@tonic-gate 	}
3320Sstevel@tonic-gate 
CRYPTO_push_info_(const char * info,const char * file,int line)3330Sstevel@tonic-gate int CRYPTO_push_info_(const char *info, const char *file, int line)
3340Sstevel@tonic-gate 	{
3350Sstevel@tonic-gate 	APP_INFO *ami, *amim;
3360Sstevel@tonic-gate 	int ret=0;
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 	if (is_MemCheck_on())
3390Sstevel@tonic-gate 		{
3400Sstevel@tonic-gate 		MemCheck_off(); /* obtain MALLOC2 lock */
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate 		if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL)
3430Sstevel@tonic-gate 			{
3440Sstevel@tonic-gate 			ret=0;
3450Sstevel@tonic-gate 			goto err;
3460Sstevel@tonic-gate 			}
3470Sstevel@tonic-gate 		if (amih == NULL)
3480Sstevel@tonic-gate 			{
3490Sstevel@tonic-gate 			if ((amih=lh_new(app_info_hash, app_info_cmp)) == NULL)
3500Sstevel@tonic-gate 				{
3510Sstevel@tonic-gate 				OPENSSL_free(ami);
3520Sstevel@tonic-gate 				ret=0;
3530Sstevel@tonic-gate 				goto err;
3540Sstevel@tonic-gate 				}
3550Sstevel@tonic-gate 			}
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 		ami->thread=CRYPTO_thread_id();
3580Sstevel@tonic-gate 		ami->file=file;
3590Sstevel@tonic-gate 		ami->line=line;
3600Sstevel@tonic-gate 		ami->info=info;
3610Sstevel@tonic-gate 		ami->references=1;
3620Sstevel@tonic-gate 		ami->next=NULL;
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate 		if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL)
3650Sstevel@tonic-gate 			{
3660Sstevel@tonic-gate #ifdef LEVITTE_DEBUG_MEM
3670Sstevel@tonic-gate 			if (ami->thread != amim->thread)
3680Sstevel@tonic-gate 				{
3690Sstevel@tonic-gate 				fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
3700Sstevel@tonic-gate 					amim->thread, ami->thread);
3710Sstevel@tonic-gate 				abort();
3720Sstevel@tonic-gate 				}
3730Sstevel@tonic-gate #endif
3740Sstevel@tonic-gate 			ami->next=amim;
3750Sstevel@tonic-gate 			}
3760Sstevel@tonic-gate  err:
3770Sstevel@tonic-gate 		MemCheck_on(); /* release MALLOC2 lock */
3780Sstevel@tonic-gate 		}
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate 	return(ret);
3810Sstevel@tonic-gate 	}
3820Sstevel@tonic-gate 
CRYPTO_pop_info(void)3830Sstevel@tonic-gate int CRYPTO_pop_info(void)
3840Sstevel@tonic-gate 	{
3850Sstevel@tonic-gate 	int ret=0;
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 	if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */
3880Sstevel@tonic-gate 		{
3890Sstevel@tonic-gate 		MemCheck_off(); /* obtain MALLOC2 lock */
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate 		ret=(pop_info() != NULL);
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate 		MemCheck_on(); /* release MALLOC2 lock */
3940Sstevel@tonic-gate 		}
3950Sstevel@tonic-gate 	return(ret);
3960Sstevel@tonic-gate 	}
3970Sstevel@tonic-gate 
CRYPTO_remove_all_info(void)3980Sstevel@tonic-gate int CRYPTO_remove_all_info(void)
3990Sstevel@tonic-gate 	{
4000Sstevel@tonic-gate 	int ret=0;
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 	if (is_MemCheck_on()) /* _must_ be true */
4030Sstevel@tonic-gate 		{
4040Sstevel@tonic-gate 		MemCheck_off(); /* obtain MALLOC2 lock */
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 		while(pop_info() != NULL)
4070Sstevel@tonic-gate 			ret++;
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 		MemCheck_on(); /* release MALLOC2 lock */
4100Sstevel@tonic-gate 		}
4110Sstevel@tonic-gate 	return(ret);
4120Sstevel@tonic-gate 	}
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate static unsigned long break_order_num=0;
CRYPTO_dbg_malloc(void * addr,int num,const char * file,int line,int before_p)4160Sstevel@tonic-gate void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
4170Sstevel@tonic-gate 	int before_p)
4180Sstevel@tonic-gate 	{
4190Sstevel@tonic-gate 	MEM *m,*mm;
4200Sstevel@tonic-gate 	APP_INFO tmp,*amim;
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate 	switch(before_p & 127)
4230Sstevel@tonic-gate 		{
4240Sstevel@tonic-gate 	case 0:
4250Sstevel@tonic-gate 		break;
4260Sstevel@tonic-gate 	case 1:
4270Sstevel@tonic-gate 		if (addr == NULL)
4280Sstevel@tonic-gate 			break;
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate 		if (is_MemCheck_on())
4310Sstevel@tonic-gate 			{
4320Sstevel@tonic-gate 			MemCheck_off(); /* make sure we hold MALLOC2 lock */
4330Sstevel@tonic-gate 			if ((m=(MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL)
4340Sstevel@tonic-gate 				{
4350Sstevel@tonic-gate 				OPENSSL_free(addr);
4360Sstevel@tonic-gate 				MemCheck_on(); /* release MALLOC2 lock
4370Sstevel@tonic-gate 				                * if num_disabled drops to 0 */
4380Sstevel@tonic-gate 				return;
4390Sstevel@tonic-gate 				}
4400Sstevel@tonic-gate 			if (mh == NULL)
4410Sstevel@tonic-gate 				{
4420Sstevel@tonic-gate 				if ((mh=lh_new(mem_hash, mem_cmp)) == NULL)
4430Sstevel@tonic-gate 					{
4440Sstevel@tonic-gate 					OPENSSL_free(addr);
4450Sstevel@tonic-gate 					OPENSSL_free(m);
4460Sstevel@tonic-gate 					addr=NULL;
4470Sstevel@tonic-gate 					goto err;
4480Sstevel@tonic-gate 					}
4490Sstevel@tonic-gate 				}
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 			m->addr=addr;
4520Sstevel@tonic-gate 			m->file=file;
4530Sstevel@tonic-gate 			m->line=line;
4540Sstevel@tonic-gate 			m->num=num;
4550Sstevel@tonic-gate 			if (options & V_CRYPTO_MDEBUG_THREAD)
4560Sstevel@tonic-gate 				m->thread=CRYPTO_thread_id();
4570Sstevel@tonic-gate 			else
4580Sstevel@tonic-gate 				m->thread=0;
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 			if (order == break_order_num)
4610Sstevel@tonic-gate 				{
4620Sstevel@tonic-gate 				/* BREAK HERE */
4630Sstevel@tonic-gate 				m->order=order;
4640Sstevel@tonic-gate 				}
4650Sstevel@tonic-gate 			m->order=order++;
4660Sstevel@tonic-gate #ifdef LEVITTE_DEBUG_MEM
4670Sstevel@tonic-gate 			fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] %c 0x%p (%d)\n",
4680Sstevel@tonic-gate 				m->order,
4690Sstevel@tonic-gate 				(before_p & 128) ? '*' : '+',
4700Sstevel@tonic-gate 				m->addr, m->num);
4710Sstevel@tonic-gate #endif
4720Sstevel@tonic-gate 			if (options & V_CRYPTO_MDEBUG_TIME)
4730Sstevel@tonic-gate 				m->time=time(NULL);
4740Sstevel@tonic-gate 			else
4750Sstevel@tonic-gate 				m->time=0;
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate 			tmp.thread=CRYPTO_thread_id();
4780Sstevel@tonic-gate 			m->app_info=NULL;
4790Sstevel@tonic-gate 			if (amih != NULL
4800Sstevel@tonic-gate 				&& (amim=(APP_INFO *)lh_retrieve(amih,(char *)&tmp)) != NULL)
4810Sstevel@tonic-gate 				{
4820Sstevel@tonic-gate 				m->app_info = amim;
4830Sstevel@tonic-gate 				amim->references++;
4840Sstevel@tonic-gate 				}
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 			if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL)
4870Sstevel@tonic-gate 				{
4880Sstevel@tonic-gate 				/* Not good, but don't sweat it */
4890Sstevel@tonic-gate 				if (mm->app_info != NULL)
4900Sstevel@tonic-gate 					{
4910Sstevel@tonic-gate 					mm->app_info->references--;
4920Sstevel@tonic-gate 					}
4930Sstevel@tonic-gate 				OPENSSL_free(mm);
4940Sstevel@tonic-gate 				}
4950Sstevel@tonic-gate 		err:
4960Sstevel@tonic-gate 			MemCheck_on(); /* release MALLOC2 lock
4970Sstevel@tonic-gate 			                * if num_disabled drops to 0 */
4980Sstevel@tonic-gate 			}
4990Sstevel@tonic-gate 		break;
5000Sstevel@tonic-gate 		}
5010Sstevel@tonic-gate 	return;
5020Sstevel@tonic-gate 	}
5030Sstevel@tonic-gate 
CRYPTO_dbg_free(void * addr,int before_p)5040Sstevel@tonic-gate void CRYPTO_dbg_free(void *addr, int before_p)
5050Sstevel@tonic-gate 	{
5060Sstevel@tonic-gate 	MEM m,*mp;
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 	switch(before_p)
5090Sstevel@tonic-gate 		{
5100Sstevel@tonic-gate 	case 0:
5110Sstevel@tonic-gate 		if (addr == NULL)
5120Sstevel@tonic-gate 			break;
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 		if (is_MemCheck_on() && (mh != NULL))
5150Sstevel@tonic-gate 			{
5160Sstevel@tonic-gate 			MemCheck_off(); /* make sure we hold MALLOC2 lock */
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 			m.addr=addr;
5190Sstevel@tonic-gate 			mp=(MEM *)lh_delete(mh,(char *)&m);
5200Sstevel@tonic-gate 			if (mp != NULL)
5210Sstevel@tonic-gate 				{
5220Sstevel@tonic-gate #ifdef LEVITTE_DEBUG_MEM
5230Sstevel@tonic-gate 			fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] - 0x%p (%d)\n",
5240Sstevel@tonic-gate 				mp->order, mp->addr, mp->num);
5250Sstevel@tonic-gate #endif
5260Sstevel@tonic-gate 				if (mp->app_info != NULL)
5270Sstevel@tonic-gate 					app_info_free(mp->app_info);
5280Sstevel@tonic-gate 				OPENSSL_free(mp);
5290Sstevel@tonic-gate 				}
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 			MemCheck_on(); /* release MALLOC2 lock
5320Sstevel@tonic-gate 			                * if num_disabled drops to 0 */
5330Sstevel@tonic-gate 			}
5340Sstevel@tonic-gate 		break;
5350Sstevel@tonic-gate 	case 1:
5360Sstevel@tonic-gate 		break;
5370Sstevel@tonic-gate 		}
5380Sstevel@tonic-gate 	}
5390Sstevel@tonic-gate 
CRYPTO_dbg_realloc(void * addr1,void * addr2,int num,const char * file,int line,int before_p)5400Sstevel@tonic-gate void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
5410Sstevel@tonic-gate 	const char *file, int line, int before_p)
5420Sstevel@tonic-gate 	{
5430Sstevel@tonic-gate 	MEM m,*mp;
5440Sstevel@tonic-gate 
5450Sstevel@tonic-gate #ifdef LEVITTE_DEBUG_MEM
5460Sstevel@tonic-gate 	fprintf(stderr, "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n",
5470Sstevel@tonic-gate 		addr1, addr2, num, file, line, before_p);
5480Sstevel@tonic-gate #endif
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 	switch(before_p)
5510Sstevel@tonic-gate 		{
5520Sstevel@tonic-gate 	case 0:
5530Sstevel@tonic-gate 		break;
5540Sstevel@tonic-gate 	case 1:
5550Sstevel@tonic-gate 		if (addr2 == NULL)
5560Sstevel@tonic-gate 			break;
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate 		if (addr1 == NULL)
5590Sstevel@tonic-gate 			{
5600Sstevel@tonic-gate 			CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p);
5610Sstevel@tonic-gate 			break;
5620Sstevel@tonic-gate 			}
5630Sstevel@tonic-gate 
5640Sstevel@tonic-gate 		if (is_MemCheck_on())
5650Sstevel@tonic-gate 			{
5660Sstevel@tonic-gate 			MemCheck_off(); /* make sure we hold MALLOC2 lock */
5670Sstevel@tonic-gate 
5680Sstevel@tonic-gate 			m.addr=addr1;
5690Sstevel@tonic-gate 			mp=(MEM *)lh_delete(mh,(char *)&m);
5700Sstevel@tonic-gate 			if (mp != NULL)
5710Sstevel@tonic-gate 				{
5720Sstevel@tonic-gate #ifdef LEVITTE_DEBUG_MEM
5730Sstevel@tonic-gate 				fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] * 0x%p (%d) -> 0x%p (%d)\n",
5740Sstevel@tonic-gate 					mp->order,
5750Sstevel@tonic-gate 					mp->addr, mp->num,
5760Sstevel@tonic-gate 					addr2, num);
5770Sstevel@tonic-gate #endif
5780Sstevel@tonic-gate 				mp->addr=addr2;
5790Sstevel@tonic-gate 				mp->num=num;
5800Sstevel@tonic-gate 				lh_insert(mh,(char *)mp);
5810Sstevel@tonic-gate 				}
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate 			MemCheck_on(); /* release MALLOC2 lock
5840Sstevel@tonic-gate 			                * if num_disabled drops to 0 */
5850Sstevel@tonic-gate 			}
5860Sstevel@tonic-gate 		break;
5870Sstevel@tonic-gate 		}
5880Sstevel@tonic-gate 	return;
5890Sstevel@tonic-gate 	}
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate typedef struct mem_leak_st
5930Sstevel@tonic-gate 	{
5940Sstevel@tonic-gate 	BIO *bio;
5950Sstevel@tonic-gate 	int chunks;
5960Sstevel@tonic-gate 	long bytes;
5970Sstevel@tonic-gate 	} MEM_LEAK;
5980Sstevel@tonic-gate 
print_leak(const MEM * m,MEM_LEAK * l)5990Sstevel@tonic-gate static void print_leak(const MEM *m, MEM_LEAK *l)
6000Sstevel@tonic-gate 	{
6010Sstevel@tonic-gate 	char buf[1024];
6020Sstevel@tonic-gate 	char *bufp = buf;
6030Sstevel@tonic-gate 	APP_INFO *amip;
6040Sstevel@tonic-gate 	int ami_cnt;
6050Sstevel@tonic-gate 	struct tm *lcl = NULL;
6060Sstevel@tonic-gate 	unsigned long ti;
6070Sstevel@tonic-gate 
6080Sstevel@tonic-gate #define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf))
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate 	if(m->addr == (char *)l->bio)
6110Sstevel@tonic-gate 	    return;
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate 	if (options & V_CRYPTO_MDEBUG_TIME)
6140Sstevel@tonic-gate 		{
6150Sstevel@tonic-gate 		lcl = localtime(&m->time);
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate 		BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ",
6180Sstevel@tonic-gate 			lcl->tm_hour,lcl->tm_min,lcl->tm_sec);
6190Sstevel@tonic-gate 		bufp += strlen(bufp);
6200Sstevel@tonic-gate 		}
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 	BIO_snprintf(bufp, BUF_REMAIN, "%5lu file=%s, line=%d, ",
6230Sstevel@tonic-gate 		m->order,m->file,m->line);
6240Sstevel@tonic-gate 	bufp += strlen(bufp);
6250Sstevel@tonic-gate 
6260Sstevel@tonic-gate 	if (options & V_CRYPTO_MDEBUG_THREAD)
6270Sstevel@tonic-gate 		{
6280Sstevel@tonic-gate 		BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ", m->thread);
6290Sstevel@tonic-gate 		bufp += strlen(bufp);
6300Sstevel@tonic-gate 		}
6310Sstevel@tonic-gate 
6320Sstevel@tonic-gate 	BIO_snprintf(bufp, BUF_REMAIN, "number=%d, address=%08lX\n",
6330Sstevel@tonic-gate 		m->num,(unsigned long)m->addr);
6340Sstevel@tonic-gate 	bufp += strlen(bufp);
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate 	BIO_puts(l->bio,buf);
6370Sstevel@tonic-gate 
6380Sstevel@tonic-gate 	l->chunks++;
6390Sstevel@tonic-gate 	l->bytes+=m->num;
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate 	amip=m->app_info;
6420Sstevel@tonic-gate 	ami_cnt=0;
6430Sstevel@tonic-gate 	if (!amip)
6440Sstevel@tonic-gate 		return;
6450Sstevel@tonic-gate 	ti=amip->thread;
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate 	do
6480Sstevel@tonic-gate 		{
6490Sstevel@tonic-gate 		int buf_len;
6500Sstevel@tonic-gate 		int info_len;
6510Sstevel@tonic-gate 
6520Sstevel@tonic-gate 		ami_cnt++;
6530Sstevel@tonic-gate 		memset(buf,'>',ami_cnt);
6540Sstevel@tonic-gate 		BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt,
6550Sstevel@tonic-gate 			" thread=%lu, file=%s, line=%d, info=\"",
6560Sstevel@tonic-gate 			amip->thread, amip->file, amip->line);
6570Sstevel@tonic-gate 		buf_len=strlen(buf);
6580Sstevel@tonic-gate 		info_len=strlen(amip->info);
6590Sstevel@tonic-gate 		if (128 - buf_len - 3 < info_len)
6600Sstevel@tonic-gate 			{
6610Sstevel@tonic-gate 			memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
6620Sstevel@tonic-gate 			buf_len = 128 - 3;
6630Sstevel@tonic-gate 			}
6640Sstevel@tonic-gate 		else
6650Sstevel@tonic-gate 			{
6660Sstevel@tonic-gate 			BUF_strlcpy(buf + buf_len, amip->info,
6670Sstevel@tonic-gate 				    sizeof buf - buf_len);
6680Sstevel@tonic-gate 			buf_len = strlen(buf);
6690Sstevel@tonic-gate 			}
6700Sstevel@tonic-gate 		BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n");
6710Sstevel@tonic-gate 
6720Sstevel@tonic-gate 		BIO_puts(l->bio,buf);
6730Sstevel@tonic-gate 
6740Sstevel@tonic-gate 		amip = amip->next;
6750Sstevel@tonic-gate 		}
6760Sstevel@tonic-gate 	while(amip && amip->thread == ti);
6770Sstevel@tonic-gate 
6780Sstevel@tonic-gate #ifdef LEVITTE_DEBUG_MEM
6790Sstevel@tonic-gate 	if (amip)
6800Sstevel@tonic-gate 		{
6810Sstevel@tonic-gate 		fprintf(stderr, "Thread switch detected in backtrace!!!!\n");
6820Sstevel@tonic-gate 		abort();
6830Sstevel@tonic-gate 		}
6840Sstevel@tonic-gate #endif
6850Sstevel@tonic-gate 	}
6860Sstevel@tonic-gate 
IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak,const MEM *,MEM_LEAK *)6870Sstevel@tonic-gate static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM *, MEM_LEAK *)
6880Sstevel@tonic-gate 
6890Sstevel@tonic-gate void CRYPTO_mem_leaks(BIO *b)
6900Sstevel@tonic-gate 	{
6910Sstevel@tonic-gate 	MEM_LEAK ml;
6920Sstevel@tonic-gate 
6930Sstevel@tonic-gate 	if (mh == NULL && amih == NULL)
6940Sstevel@tonic-gate 		return;
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 	MemCheck_off(); /* obtain MALLOC2 lock */
6970Sstevel@tonic-gate 
6980Sstevel@tonic-gate 	ml.bio=b;
6990Sstevel@tonic-gate 	ml.bytes=0;
7000Sstevel@tonic-gate 	ml.chunks=0;
7010Sstevel@tonic-gate 	if (mh != NULL)
7020Sstevel@tonic-gate 		lh_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak),
7030Sstevel@tonic-gate 				(char *)&ml);
7040Sstevel@tonic-gate 	if (ml.chunks != 0)
7050Sstevel@tonic-gate 		{
7060Sstevel@tonic-gate 		BIO_printf(b,"%ld bytes leaked in %d chunks\n",
7070Sstevel@tonic-gate 			   ml.bytes,ml.chunks);
7080Sstevel@tonic-gate 		}
7090Sstevel@tonic-gate 	else
7100Sstevel@tonic-gate 		{
7110Sstevel@tonic-gate 		/* Make sure that, if we found no leaks, memory-leak debugging itself
7120Sstevel@tonic-gate 		 * does not introduce memory leaks (which might irritate
7130Sstevel@tonic-gate 		 * external debugging tools).
7140Sstevel@tonic-gate 		 * (When someone enables leak checking, but does not call
7150Sstevel@tonic-gate 		 * this function, we declare it to be their fault.)
7160Sstevel@tonic-gate 		 *
7170Sstevel@tonic-gate 		 * XXX    This should be in CRYPTO_mem_leaks_cb,
7180Sstevel@tonic-gate 		 * and CRYPTO_mem_leaks should be implemented by
7190Sstevel@tonic-gate 		 * using CRYPTO_mem_leaks_cb.
7200Sstevel@tonic-gate 		 * (Also their should be a variant of lh_doall_arg
7210Sstevel@tonic-gate 		 * that takes a function pointer instead of a void *;
7220Sstevel@tonic-gate 		 * this would obviate the ugly and illegal
7230Sstevel@tonic-gate 		 * void_fn_to_char kludge in CRYPTO_mem_leaks_cb.
7240Sstevel@tonic-gate 		 * Otherwise the code police will come and get us.)
7250Sstevel@tonic-gate 		 */
7260Sstevel@tonic-gate 		int old_mh_mode;
7270Sstevel@tonic-gate 
7280Sstevel@tonic-gate 		CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
7290Sstevel@tonic-gate 
7300Sstevel@tonic-gate 		/* avoid deadlock when lh_free() uses CRYPTO_dbg_free(),
7310Sstevel@tonic-gate 		 * which uses CRYPTO_is_mem_check_on */
7320Sstevel@tonic-gate 		old_mh_mode = mh_mode;
7330Sstevel@tonic-gate 		mh_mode = CRYPTO_MEM_CHECK_OFF;
7340Sstevel@tonic-gate 
7350Sstevel@tonic-gate 		if (mh != NULL)
7360Sstevel@tonic-gate 			{
7370Sstevel@tonic-gate 			lh_free(mh);
7380Sstevel@tonic-gate 			mh = NULL;
7390Sstevel@tonic-gate 			}
7400Sstevel@tonic-gate 		if (amih != NULL)
7410Sstevel@tonic-gate 			{
7420Sstevel@tonic-gate 			if (lh_num_items(amih) == 0)
7430Sstevel@tonic-gate 				{
7440Sstevel@tonic-gate 				lh_free(amih);
7450Sstevel@tonic-gate 				amih = NULL;
7460Sstevel@tonic-gate 				}
7470Sstevel@tonic-gate 			}
7480Sstevel@tonic-gate 
7490Sstevel@tonic-gate 		mh_mode = old_mh_mode;
7500Sstevel@tonic-gate 		CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
7510Sstevel@tonic-gate 		}
7520Sstevel@tonic-gate 	MemCheck_on(); /* release MALLOC2 lock */
7530Sstevel@tonic-gate 	}
7540Sstevel@tonic-gate 
7550Sstevel@tonic-gate #ifndef OPENSSL_NO_FP_API
CRYPTO_mem_leaks_fp(FILE * fp)7560Sstevel@tonic-gate void CRYPTO_mem_leaks_fp(FILE *fp)
7570Sstevel@tonic-gate 	{
7580Sstevel@tonic-gate 	BIO *b;
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate 	if (mh == NULL) return;
7610Sstevel@tonic-gate 	/* Need to turn off memory checking when allocated BIOs ... especially
7620Sstevel@tonic-gate 	 * as we're creating them at a time when we're trying to check we've not
7630Sstevel@tonic-gate 	 * left anything un-free()'d!! */
7640Sstevel@tonic-gate 	MemCheck_off();
7650Sstevel@tonic-gate 	b = BIO_new(BIO_s_file());
7660Sstevel@tonic-gate 	MemCheck_on();
7670Sstevel@tonic-gate 	if(!b) return;
7680Sstevel@tonic-gate 	BIO_set_fp(b,fp,BIO_NOCLOSE);
7690Sstevel@tonic-gate 	CRYPTO_mem_leaks(b);
7700Sstevel@tonic-gate 	BIO_free(b);
7710Sstevel@tonic-gate 	}
7720Sstevel@tonic-gate #endif
7730Sstevel@tonic-gate 
7740Sstevel@tonic-gate 
7750Sstevel@tonic-gate 
7760Sstevel@tonic-gate /* FIXME: We really don't allow much to the callback.  For example, it has
7770Sstevel@tonic-gate    no chance of reaching the info stack for the item it processes.  Should
7780Sstevel@tonic-gate    it really be this way?  -- Richard Levitte */
7790Sstevel@tonic-gate /* NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside crypto.h
7800Sstevel@tonic-gate  * If this code is restructured, remove the callback type if it is no longer
7810Sstevel@tonic-gate  * needed. -- Geoff Thorpe */
cb_leak(const MEM * m,CRYPTO_MEM_LEAK_CB ** cb)7820Sstevel@tonic-gate static void cb_leak(const MEM *m, CRYPTO_MEM_LEAK_CB **cb)
7830Sstevel@tonic-gate 	{
7840Sstevel@tonic-gate 	(**cb)(m->order,m->file,m->line,m->num,m->addr);
7850Sstevel@tonic-gate 	}
7860Sstevel@tonic-gate 
IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak,const MEM *,CRYPTO_MEM_LEAK_CB **)7870Sstevel@tonic-gate static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM *, CRYPTO_MEM_LEAK_CB **)
7880Sstevel@tonic-gate 
7890Sstevel@tonic-gate void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
7900Sstevel@tonic-gate 	{
7910Sstevel@tonic-gate 	if (mh == NULL) return;
7920Sstevel@tonic-gate 	CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
7930Sstevel@tonic-gate 	lh_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), &cb);
7940Sstevel@tonic-gate 	CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
7950Sstevel@tonic-gate 	}
796