Commit 9ac42ed8 authored by Richard Levitte's avatar Richard Levitte
Browse files

Rebuild of the OpenSSL memory allocation and deallocation routines.

With this change, the following is provided and present at all times
(meaning CRYPTO_MDEBUG is no longer required to get this functionality):

  - hooks to provide your own allocation and deallocation routines.
    They have to have the same interface as malloc(), realloc() and
    free().  They are registered by calling CRYPTO_set_mem_functions()
    with the function pointers.

  - hooks to provide your own memory debugging routines.  The have to
    have the same interface as as the CRYPTO_dbg_*() routines.  They
    are registered by calling CRYPTO_set_mem_debug_functions() with
    the function pointers.

I moved everything that was already built into OpenSSL and did memory
debugging to a separate file (mem_dbg.c), to make it clear what is
what.

With this, the relevance of the CRYPTO_MDEBUG has changed.  The only
thing in crypto/crypto.h that it affects is the definition of the
MemCheck_start and MemCheck_stop macros.
parent 1ad9bdf2
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -4,6 +4,16 @@

 Changes between 0.9.4 and 0.9.5  [xx XXX 1999]

  *) Rebuild of the memory allocation routines used by OpenSSL code and
     possibly others as well.  The purpose is to make an interface that
     provide hooks so anyone can build a separate set of allocation and
     deallocation routines to be used by OpenSSL, for example if memory
     pool implementations, or something else.  The same is provided for
     memory debugging code.  OpenSSL already comes with code that finds
     memory leaks, but this gives people a chance to debug other memory
     problems.
     [Richard Levitte]

  *) Some S/MIME fixes. The OID for SMIMECapabilities was wrong, the
     ordering of SMIMECapabilities wasn't in "strength order" and there
     was a missing NULL in the AlgorithmIdentifier for the SHA1 signature
+9 −4
Original line number Diff line number Diff line
@@ -34,8 +34,8 @@ SDIRS= md2 md5 sha mdc2 hmac ripemd \
GENERAL=Makefile README crypto-lib.com install.com

LIB= $(TOP)/libcrypto.a
LIBSRC=	cryptlib.c mem.c cversion.c ex_data.c tmdiff.c cpt_err.c
LIBOBJ= cryptlib.o mem.o cversion.o ex_data.o tmdiff.o cpt_err.o
LIBSRC=	cryptlib.c mem.c mem_dbg.c cversion.c ex_data.c tmdiff.c cpt_err.c
LIBOBJ= cryptlib.o mem.o mem_dbg.o cversion.o ex_data.o tmdiff.o cpt_err.o

SRC= $(LIBSRC)

@@ -174,8 +174,13 @@ ex_data.o: ../include/openssl/opensslv.h ../include/openssl/stack.h cryptlib.h
mem.o: ../include/openssl/bio.h ../include/openssl/buffer.h
mem.o: ../include/openssl/crypto.h ../include/openssl/e_os.h
mem.o: ../include/openssl/e_os2.h ../include/openssl/err.h
mem.o: ../include/openssl/lhash.h ../include/openssl/opensslconf.h
mem.o: ../include/openssl/opensslv.h ../include/openssl/stack.h cryptlib.h
mem.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
mem.o: ../include/openssl/stack.h cryptlib.h
mem_dbg.o: ../include/openssl/bio.h ../include/openssl/buffer.h
mem_dbg.o: ../include/openssl/crypto.h ../include/openssl/e_os.h
mem_dbg.o: ../include/openssl/e_os2.h ../include/openssl/err.h
mem_dbg.o: ../include/openssl/lhash.h ../include/openssl/opensslconf.h
mem_dbg.o: ../include/openssl/opensslv.h ../include/openssl/stack.h cryptlib.h
tmdiff.o: ../include/openssl/bio.h ../include/openssl/buffer.h
tmdiff.o: ../include/openssl/crypto.h ../include/openssl/e_os.h
tmdiff.o: ../include/openssl/e_os2.h ../include/openssl/err.h
+1 −1
Original line number Diff line number Diff line
@@ -174,7 +174,7 @@ $!
$ APPS_DES = "DES/DES,CBC3_ENC"
$ APPS_PKCS7 = "ENC/ENC;DEC/DEC;SIGN/SIGN;VERIFY/VERIFY,EXAMPLE"
$
$ LIB_ = "cryptlib,mem,cversion,ex_data,tmdiff,cpt_err"
$ LIB_ = "cryptlib,mem,mem_dbg,cversion,ex_data,tmdiff,cpt_err"
$ LIB_MD2 = "md2_dgst,md2_one"
$ LIB_MD5 = "md5_dgst,md5_one"
$ LIB_SHA = "sha_dgst,sha1dgst,sha_one,sha1_one"
+69 −37
Original line number Diff line number Diff line
@@ -196,12 +196,14 @@ typedef struct crypto_ex_data_func_st
#define CRYPTO_EX_INDEX_X509_STORE	4
#define CRYPTO_EX_INDEX_X509_STORE_CTX	5

/* Use this for win32 DLL's */
/* This is the default callbacks, but we can have others as well */
#define CRYPTO_malloc_init()	CRYPTO_set_mem_functions(\
	(char *(*)())malloc,\
	(char *(*)())realloc,\
	(void (*)())free)



#ifdef CRYPTO_MDEBUG_ALL
# ifndef CRYPTO_MDEBUG_TIME
#  define CRYPTO_MDEBUG_TIME
@@ -211,6 +213,28 @@ typedef struct crypto_ex_data_func_st
# endif
#endif

/* Magic to make sure we get correct values */
#ifdef CRYPTO_MDEBUG_TIME
#define V_CRYPTO_MDEBUG_TIME 1
#else
#define V_CRYPTO_MDEBUG_TIME 0
#endif
#ifdef CRYPTO_MDEBUG_THREAD
#define V_CRYPTO_MDEBUG_THREAD 2
#else
#define V_CRYPTO_MDEBUG_THREAD 0
#endif

#define CRYPTO_malloc_debug_init()	do {\
	CRYPTO_set_mem_debug_functions(\
		(void (*)())CRYPTO_dbg_malloc,\
		(void (*)())CRYPTO_dbg_realloc,\
		(void (*)())CRYPTO_dbg_free,\
		(void (*)())CRYPTO_dbg_set_options,\
		(void (*)())CRYPTO_dbg_get_options);\
	CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_TIME|V_CRYPTO_MDEBUG_THREAD);\
	} while(0);

#if defined CRYPTO_MDEBUG_TIME || defined CRYPTO_MDEBUG_THREAD
# ifndef CRYPTO_MDEBUG /* avoid duplicate #define */
#  define CRYPTO_MDEBUG
@@ -220,39 +244,25 @@ typedef struct crypto_ex_data_func_st
#ifdef CRYPTO_MDEBUG
#define MemCheck_start() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON)
#define MemCheck_stop()	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF)
#else
#define MemCheck_start()
#define MemCheck_stop()
#endif
#define MemCheck_on()	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE)
#define MemCheck_off()	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE)
#define Malloc(num)	CRYPTO_dbg_malloc((int)num,__FILE__,__LINE__)
#define is_MemCheck_on() CRYPTO_mem_check_on()

#define Malloc(num)	CRYPTO_malloc((int)num,__FILE__,__LINE__)
#define Realloc(addr,num) \
	CRYPTO_dbg_realloc((char *)addr,(int)num,__FILE__,__LINE__)
	CRYPTO_realloc((char *)addr,(int)num,__FILE__,__LINE__)
#define Remalloc(addr,num) \
	CRYPTO_dbg_remalloc((char **)addr,(int)num,__FILE__,__LINE__)
#define FreeFunc	CRYPTO_dbg_free
#define Free(addr)	CRYPTO_dbg_free(addr)
#define Malloc_locked(num) CRYPTO_malloc_locked((int)num)
#define Free_locked(addr) CRYPTO_free_locked(addr)
#else
#define MemCheck_start()
#define MemCheck_stop()
#define MemCheck_on()
#define MemCheck_off()
#define Remalloc	CRYPTO_remalloc
#if defined(WIN32) || defined(MFUNC)
#define Malloc		CRYPTO_malloc
#define Realloc(a,n)	CRYPTO_realloc(a,(n))
	CRYPTO_remalloc((char **)addr,(int)num,__FILE__,__LINE__)
#define FreeFunc	CRYPTO_free
#define Free(addr)	CRYPTO_free(addr)
#define Malloc_locked	CRYPTO_malloc_locked

#define Malloc_locked(num) CRYPTO_malloc_locked((int)num,__FILE__,__LINE__)
#define Free_locked(addr) CRYPTO_free_locked(addr)
#else
#define Malloc		malloc
#define Realloc		realloc
#define FreeFunc	free
#define Free(addr)	free(addr)
#define Malloc_locked	malloc
#define Free_locked(addr) free(addr)
#endif /* WIN32 || MFUNC */
#endif /* MDEBUG */


/* Case insensiteve linking causes problems.... */
#if defined(WIN16) || defined(VMS)
@@ -272,6 +282,7 @@ void CRYPTO_free_ex_data(STACK *meth,char *obj,CRYPTO_EX_DATA *ad);
void CRYPTO_new_ex_data(STACK *meth, char *obj, CRYPTO_EX_DATA *ad);

int CRYPTO_mem_ctrl(int mode);
int CRYPTO_mem_check_on(void);
int CRYPTO_get_new_lockid(char *name);

int CRYPTO_num_locks(void); /* return CRYPTO_NUM_LOCKS (shared libs!) */
@@ -291,25 +302,46 @@ const char *CRYPTO_get_lock_name(int type);
int CRYPTO_add_lock(int *pointer,int amount,int type, const char *file,
		    int line);

void CRYPTO_set_mem_functions(char *(*m)(),char *(*r)(), void (*free_func)());
void CRYPTO_set_mem_functions(char *(*m)(),char *(*r)(), void (*f)());
void CRYPTO_set_mem_debug_functions(void (*m)(),void (*r)(),void (*f)(),void (*so)(),int (*go)());
void CRYPTO_set_mem_debug_options(int bits);
void CRYPTO_get_mem_functions(char *(**m)(),char *(**r)(), void (**f)());
void CRYPTO_get_mem_debug_functions(void (**m)(),void (**r)(),void (**f)(),void (**so)(),int (**go)());
int CRYPTO_get_mem_debug_options();
void CRYPTO_set_locked_mem_functions(char *(*m)(), void (*free_func)());
void CRYPTO_get_locked_mem_functions(char *(**m)(), void (**f)());

void *CRYPTO_malloc_locked(int num);
void *CRYPTO_malloc_locked(int num, char *file, int line);
void CRYPTO_free_locked(void *);
void *CRYPTO_malloc(int num);
void *CRYPTO_malloc(int num, char *file, int line);
void CRYPTO_free(void *);
void *CRYPTO_realloc(void *addr,int num);
void *CRYPTO_remalloc(void *addr,int num);
void *CRYPTO_realloc(void *addr,int num, char *file, int line);
void *CRYPTO_remalloc(void *addr,int num, char *file, int line);

int CRYPTO_add_info(const char *file, int line, const char *info);
int CRYPTO_remove_info();
int CRYPTO_remove_info(void);
int CRYPTO_remove_all_info(void);

/* The last argument has the following significance:
 *
 * 0:	called before the actual memory allocation has taken place
 * 1:	called after the actual memory allocation has taken place
 */
void CRYPTO_dbg_malloc(void *addr,int num,const char *file,int line,int before_p);
void CRYPTO_dbg_realloc(void *addr1,void *addr2,int num,const char *file,int line,int before_p);
void CRYPTO_dbg_free(void *,int before_p);

/* Tell the debugging code about options.  By default, the following values
 * apply:
 *
 * 0:	Clear all options.
 * 1:	Set the "Show Time" option.
 * 2:	Set the "Show Thread Number" option.
 * 3:	1 + 2
 */
void CRYPTO_dbg_set_options(int num);
int CRYPTO_dbg_get_options();

void *CRYPTO_dbg_malloc(int num,const char *file,int line);
void *CRYPTO_dbg_realloc(void *addr,int num,const char *file,int line);
void CRYPTO_dbg_free(void *);
void *CRYPTO_dbg_remalloc(void *addr,int num,const char *file,int line);
#ifndef NO_FP_API
void CRYPTO_mem_leaks_fp(FILE *);
#endif
+72 −538
Original line number Diff line number Diff line
@@ -59,271 +59,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <openssl/crypto.h>
#ifdef CRYPTO_MDEBUG_TIME
# include <time.h>	
#endif
#include <openssl/buffer.h>
#include <openssl/bio.h>
#include <openssl/lhash.h>
#include "cryptlib.h"

/* #ifdef CRYPTO_MDEBUG */
/* static int mh_mode=CRYPTO_MEM_CHECK_ON; */
/* #else */
static int mh_mode=CRYPTO_MEM_CHECK_OFF;
static unsigned long disabling_thread = 0;
/* #endif */
/* State CRYPTO_MEM_CHECK_ON exists only temporarily when the library
 * thinks that certain allocations should not be checked (e.g. the data
 * structures used for memory checking).  It is not suitable as an initial
 * state: the library will unexpectedly enable memory checking when it
 * executes one of those sections that want to disable checking
 * temporarily.
 *
 * State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes no sense whatsoever.
 */

static unsigned long order=0;

static LHASH *amih=NULL;

typedef struct app_mem_info_st
	{	
	unsigned long thread;
	const char *file;
	int line;
	const char *info;
	struct app_mem_info_st *next;
	int references;
	} APP_INFO;

static LHASH *mh=NULL;

typedef struct mem_st
	{
	char *addr;
	int num;
	const char *file;
	int line;
#ifdef CRYPTO_MDEBUG_THREAD
	unsigned long thread;
#endif
	unsigned long order;
#ifdef CRYPTO_MDEBUG_TIME
	time_t time;
#endif
	APP_INFO *app_info;
	} MEM;

int CRYPTO_mem_ctrl(int mode)
	{
	int ret=mh_mode;

	CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
	switch (mode)
		{
	/* for applications: */
	case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */
		mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
		disabling_thread = 0;
		break;
	case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
		mh_mode = 0;
		disabling_thread = 0;
		break;

	/* switch off temporarily (for library-internal use): */
	case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
		if (mh_mode & CRYPTO_MEM_CHECK_ON)
			{
			mh_mode&= ~CRYPTO_MEM_CHECK_ENABLE;
			if (disabling_thread != CRYPTO_thread_id()) /* otherwise we already have the MALLOC2 lock */
				{
				/* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while
				 * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if
				 * somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot release it
				 * because we block entry to this function).
				 * Give them a chance, first, and then claim the locks in
				 * appropriate order (long-time lock first).
				 */
				CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
				/* Note that after we have waited for CRYPTO_LOCK_MALLOC2
				 * and CRYPTO_LOCK_MALLOC, we'll still be in the right
				 * "case" and "if" branch because MemCheck_start and
				 * MemCheck_stop may never be used while there are multiple
				 * OpenSSL threads. */
				CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
				CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
				disabling_thread=CRYPTO_thread_id();
				}
			}
		break;
	case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */
		if (mh_mode & CRYPTO_MEM_CHECK_ON)
			{
			mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
			if (disabling_thread != 0)
				{
				disabling_thread=0;
				CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
				}
			}
		break;

	default:
		break;
		}
	CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
	return(ret);
	}

static int is_MemCheck_On()
	{
	int ret = 0;

	if (mh_mode & CRYPTO_MEM_CHECK_ON)
		{
		CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);

		ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
			&& disabling_thread != CRYPTO_thread_id();

		CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
		}
	return(ret);
	}	

static int mem_cmp(MEM *a, MEM *b)
	{
	return(a->addr - b->addr);
	}

static unsigned long mem_hash(MEM *a)
	{
	unsigned long ret;

	ret=(unsigned long)a->addr;

	ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
	return(ret);
	}

static int app_info_cmp(APP_INFO *a, APP_INFO *b)
	{
	return(a->thread - b->thread);
	}

static unsigned long app_info_hash(APP_INFO *a)
	{
	unsigned long ret;

	ret=(unsigned long)a->thread;

	ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
	return(ret);
	}

static APP_INFO *remove_info()
	{
	APP_INFO tmp;
	APP_INFO *ret = NULL;

	if (amih != NULL)
		{
		tmp.thread=CRYPTO_thread_id();
		if ((ret=(APP_INFO *)lh_delete(amih,(char *)&tmp)) != NULL)
			{
			APP_INFO *next=ret->next;

			if (next != NULL)
				{
				next->references++;
				lh_insert(amih,(char *)next);
				}
#ifdef LEVITTE_DEBUG
			if (ret->thread != tmp.thread)
				{
				fprintf(stderr, "remove_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
					ret->thread, tmp.thread);
				abort();
				}
#endif
			if (--(ret->references) <= 0)
				{
				ret->next = NULL;
				if (next != NULL)
					next->references--;
				Free(ret);
				}
			}
		}
	return(ret);
	}

int CRYPTO_add_info(const char *file, int line, const char *info)
	{
	APP_INFO *ami, *amim;
	int ret=0;

	if (is_MemCheck_On())
		{
		MemCheck_off();

		if ((ami = (APP_INFO *)Malloc(sizeof(APP_INFO))) == NULL)
			{
			ret=0;
			goto err;
			}
		if (amih == NULL)
			{
			if ((amih=lh_new(app_info_hash,app_info_cmp)) == NULL)
				{
				Free(ami);
				ret=0;
				goto err;
				}
			}

		ami->thread=CRYPTO_thread_id();
		ami->file=file;
		ami->line=line;
		ami->info=info;
		ami->references=1;
		ami->next=NULL;

		if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL)
			{
#ifdef LEVITTE_DEBUG
			if (ami->thread != amim->thread)
				{
				fprintf(stderr, "CRYPTO_add_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
					amim->thread, ami->thread);
				abort();
				}
#endif
			ami->next=amim;
			}
 err:
		MemCheck_on();
		}

	return(ret);
	}

int CRYPTO_remove_info()
	{
	int ret=0;

	if (is_MemCheck_On())
		{
		MemCheck_off();

		ret=(remove_info() != NULL);

		MemCheck_on();
		}
	return(ret);
	}

static char *(*malloc_locked_func)()=(char *(*)())malloc;
static void (*free_locked_func)()=(void (*)())free;
@@ -331,6 +68,12 @@ static char *(*malloc_func)()= (char *(*)())malloc;
static char *(*realloc_func)()=	(char *(*)())realloc;
static void (*free_func)()=	(void (*)())free;

static void (*malloc_debug_func)()= (void (*)())CRYPTO_dbg_malloc;
static void (*realloc_debug_func)()= (void (*)())CRYPTO_dbg_realloc;
static void (*free_debug_func)()= (void (*)())CRYPTO_dbg_free;
static void (*set_debug_options_func)()= (void (*)())CRYPTO_dbg_set_options;
static int (*get_debug_options_func)()= (int (*)())CRYPTO_dbg_get_options;

void CRYPTO_set_mem_functions(char *(*m)(), char *(*r)(), void (*f)())
	{
	if ((m == NULL) || (r == NULL) || (f == NULL)) return;
@@ -341,6 +84,17 @@ void CRYPTO_set_mem_functions(char *(*m)(), char *(*r)(), void (*f)())
	free_locked_func=f;
	}

void CRYPTO_set_mem_debug_functions(void (*m)(), void (*r)(), void (*f)(),void (*so)(),int (*go)())
	{
	if ((m == NULL) || (r == NULL) || (f == NULL) || (so == NULL) || (go == NULL))
		return;
	malloc_debug_func=m;
	realloc_debug_func=r;
	free_debug_func=f;
	set_debug_options_func=so;
	get_debug_options_func=go;
	}

void CRYPTO_set_locked_mem_functions(char *(*m)(), void (*f)())
	{
	if ((m == NULL) || (f == NULL)) return;
@@ -355,317 +109,97 @@ void CRYPTO_get_mem_functions(char *(**m)(), char *(**r)(), void (**f)())
	if (f != NULL) *f=free_func;
	}

void CRYPTO_get_locked_mem_functions(char *(**m)(), void (**f)())
void CRYPTO_get_mem_debug_functions(void (**m)(), void (**r)(), void (**f)(),void (**so)(),int (**go)())
	{
	if (m != NULL) *m=malloc_locked_func;
	if (f != NULL) *f=free_locked_func;
	if (m != NULL) *m=malloc_debug_func;
	if (r != NULL) *r=realloc_debug_func;
	if (f != NULL) *f=free_debug_func;
	if (so != NULL) *so=set_debug_options_func;
	if (go != NULL) *go=get_debug_options_func;
	}

void *CRYPTO_malloc_locked(int num)
	{
	return(malloc_locked_func(num));
	}

void CRYPTO_free_locked(void *str)
	{
	free_locked_func(str);
	}

void *CRYPTO_malloc(int num)
	{
	return(malloc_func(num));
	}

void *CRYPTO_realloc(void *str, int num)
	{
	return(realloc_func(str,num));
	}

void CRYPTO_free(void *str)
void CRYPTO_get_locked_mem_functions(char *(**m)(), void (**f)())
	{
	free_func(str);
	if (m != NULL) *m=malloc_locked_func;
	if (f != NULL) *f=free_locked_func;
	}

static unsigned long break_order_num=0;
void *CRYPTO_dbg_malloc(int num, const char *file, int line)
	{
	char *ret;
	MEM *m,*mm;
	APP_INFO tmp,*amim;

	if ((ret=malloc_func(num)) == NULL)
		return(NULL);

	if (is_MemCheck_On())
		{
		MemCheck_off();
		if ((m=(MEM *)Malloc(sizeof(MEM))) == NULL)
void *CRYPTO_malloc_locked(int num, char *file, int line)
	{
			Free(ret);
			MemCheck_on();
			return(NULL);
			}
		if (mh == NULL)
			{
			if ((mh=lh_new(mem_hash,mem_cmp)) == NULL)
				{
				Free(ret);
				Free(m);
				ret=NULL;
				goto err;
				}
			}
	char *ret = NULL;

		m->addr=ret;
		m->file=file;
		m->line=line;
		m->num=num;
#ifdef CRYPTO_MDEBUG_THREAD
		m->thread=CRYPTO_thread_id();
#endif
		if (order == break_order_num)
			{
			/* BREAK HERE */
			m->order=order;
			}
		m->order=order++;
#ifdef CRYPTO_MDEBUG_TIME
		m->time=time(NULL);
	malloc_debug_func(NULL, num, file, line, 0);
	ret = malloc_locked_func(num);
#ifdef LEVITTE_DEBUG
	fprintf(stderr, "LEVITTE_DEBUG:         > 0x%p (%d)\n", ret, num);
#endif
	malloc_debug_func(ret, num, file, line, 1);

		tmp.thread=CRYPTO_thread_id();
		m->app_info=NULL;
		if (amih != NULL
		    && (amim=(APP_INFO *)lh_retrieve(amih,(char *)&tmp)) != NULL)
			{
			m->app_info = amim;
			amim->references++;
			}

		if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL)
			{
			/* Not good, but don't sweat it */
			if (mm->app_info != NULL)
				{
				mm->app_info->references--;
	return ret;
	}
			Free(mm);
			}
err:
		MemCheck_on();
		}
	return(ret);
	}

void CRYPTO_dbg_free(void *addr)
	{
	MEM m,*mp;

	if (is_MemCheck_On() && (mh != NULL))
		{
		MemCheck_off();

		m.addr=addr;
		mp=(MEM *)lh_delete(mh,(char *)&m);
		if (mp != NULL)
			{
			if (mp->app_info != NULL)
				{
				mp->app_info->references--;
				}
			Free(mp);
			}

		MemCheck_on();
		}
	free_func(addr);
	}

void *CRYPTO_dbg_realloc(void *addr, int num, const char *file, int line)
	{
	char *ret;
	MEM m,*mp;

	ret=realloc_func(addr,num);
	if (ret == addr) return(ret);

	if (is_MemCheck_On())
		{
		if (ret == NULL) return(NULL);

		MemCheck_off();

		m.addr=addr;
		mp=(MEM *)lh_delete(mh,(char *)&m);
		if (mp != NULL)
			{
			mp->addr=ret;
			lh_insert(mh,(char *)mp);
			}

		MemCheck_on();
		}
	return(ret);
	}

void *CRYPTO_remalloc(void *a, int n)
	{
	if (a != NULL) Free(a);
	a=(char *)Malloc(n);
	return(a);
	}

void *CRYPTO_dbg_remalloc(void *a, int n, const char *file, int line)
void CRYPTO_free_locked(void *str)
	{
	if (a != NULL) CRYPTO_dbg_free(a);
	a=(char *)CRYPTO_dbg_malloc(n,file,line);
	return(a);
	free_debug_func(str, 0);
#ifdef LEVITTE_DEBUG
	fprintf(stderr, "LEVITTE_DEBUG:         < 0x%p\n", str);
#endif
	free_locked_func(str);
	free_debug_func(NULL, 1);
	}


typedef struct mem_leak_st
void *CRYPTO_malloc(int num, char *file, int line)
	{
	BIO *bio;
	int chunks;
	long bytes;
	} MEM_LEAK;

static void print_leak(MEM *m, MEM_LEAK *l)
	{
	char buf[128];
	APP_INFO *amip;
	int ami_cnt;
#ifdef CRYPTO_MDEBUG_TIME
	struct tm *lcl;
#endif
	unsigned long ti;
	char *ret = NULL;

	if(m->addr == (char *)l->bio)
	    return;

#ifdef CRYPTO_MDEBUG_TIME
	lcl = localtime(&m->time);
#endif

	sprintf(buf,
#ifdef CRYPTO_MDEBUG_TIME
		"[%02d:%02d:%02d] "
#endif
		"%5lu file=%s, line=%d, "
#ifdef CRYPTO_MDEBUG_THREAD
		"thread=%lu, "
#endif
		"number=%d, address=%08lX\n",
#ifdef CRYPTO_MDEBUG_TIME
		lcl->tm_hour,lcl->tm_min,lcl->tm_sec,
#endif
		m->order,m->file,m->line,
#ifdef CRYPTO_MDEBUG_THREAD
		m->thread,
	malloc_debug_func(NULL, num, file, line, 0);
	ret = malloc_func(num);
#ifdef LEVITTE_DEBUG
	fprintf(stderr, "LEVITTE_DEBUG:         > 0x%p (%d)\n", ret, num);
#endif
		m->num,(unsigned long)m->addr);

	BIO_puts(l->bio,buf);
	
	l->chunks++;
	l->bytes+=m->num;
	malloc_debug_func(ret, num, file, line, 1);

	amip=m->app_info;
	ami_cnt=0;
	if (amip)
		ti=amip->thread;
	while(amip && amip->thread == ti)
		{
		int buf_len;
		int info_len;

		ami_cnt++;
		memset(buf,'>',ami_cnt);
		sprintf(buf + ami_cnt,
			"thread=%lu, file=%s, line=%d, info=\"",
			amip->thread, amip->file, amip->line);
		buf_len=strlen(buf);
		info_len=strlen(amip->info);
		if (128 - buf_len - 3 < info_len)
			{
			memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
			buf_len = 128 - 3;
	return ret;
	}
		else
			{
			strcpy(buf + buf_len, amip->info);
			buf_len = strlen(buf);
			}
		sprintf(buf + buf_len, "\"\n");

		BIO_puts(l->bio,buf);
void *CRYPTO_realloc(void *str, int num, char *file, int line)
	{
	char *ret = NULL;

		amip = amip->next;
		}
	realloc_debug_func(str, NULL, num, file, line, 0);
	ret = realloc_func(str,num);
#ifdef LEVITTE_DEBUG
	if (amip)
		{
		fprintf(stderr, "Thread switch detected i backtrace!!!!\n");
		abort();
		}
	fprintf(stderr, "LEVITTE_DEBUG:         | 0x%p -> 0x%p (%d)\n", str, ret, num);
#endif
	}
	realloc_debug_func(str, ret, num, file, line, 1);

void CRYPTO_mem_leaks(BIO *b)
	{
	MEM_LEAK ml;
	char buf[80];

	if (mh == NULL) return;
	ml.bio=b;
	ml.bytes=0;
	ml.chunks=0;
	CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
	lh_doall_arg(mh,(void (*)())print_leak,(char *)&ml);
	CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
	if (ml.chunks != 0)
		{
		sprintf(buf,"%ld bytes leaked in %d chunks\n",
			ml.bytes,ml.chunks);
		BIO_puts(b,buf);
	return ret;
	}

#if 0
	lh_stats_bio(mh,b);
	lh_node_stats_bio(mh,b);
	lh_node_usage_stats_bio(mh,b);
void CRYPTO_free(void *str)
	{
	free_debug_func(str, 0);
#ifdef LEVITTE_DEBUG
	fprintf(stderr, "LEVITTE_DEBUG:         < 0x%p\n", str);
#endif
	free_func(str);
	free_debug_func(NULL, 1);
	}

static void (*mem_cb)()=NULL;

static void cb_leak(MEM *m, char *cb)
void *CRYPTO_remalloc(void *a, int num, char *file, int line)
	{
	void (*mem_callback)()=(void (*)())cb;
	mem_callback(m->order,m->file,m->line,m->num,m->addr);
	if (a != NULL) Free(a);
	a=(char *)Malloc(num);
	return(a);
	}

void CRYPTO_mem_leaks_cb(void (*cb)())
void CRYPTO_set_mem_debug_options(int bits)
	{
	if (mh == NULL) return;
	CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
	mem_cb=cb;
	lh_doall_arg(mh,(void (*)())cb_leak,(char *)mem_cb);
	mem_cb=NULL;
	CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
	set_debug_options_func(bits);
	}

#ifndef NO_FP_API
void CRYPTO_mem_leaks_fp(FILE *fp)
int CRYPTO_get_mem_debug_options()
	{
	BIO *b;

	if (mh == NULL) return;
	if ((b=BIO_new(BIO_s_file())) == NULL)
		return;
	BIO_set_fp(b,fp,BIO_NOCLOSE);
	CRYPTO_mem_leaks(b);
	BIO_free(b);
	return get_debug_options_func();
	}
#endif
Loading