mem.c 8.9 KB
Newer Older
1
/* crypto/mem.c */
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
 * All rights reserved.
 *
 * This package is an SSL implementation written
 * by Eric Young (eay@cryptsoft.com).
 * The implementation was written so as to conform with Netscapes SSL.
 * 
 * This library is free for commercial and non-commercial use as long as
 * the following conditions are aheared to.  The following conditions
 * apply to all code found in this distribution, be it the RC4, RSA,
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
 * included with this distribution is covered by the same copyright terms
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
 * 
 * Copyright remains Eric Young's, and as such any Copyright notices in
 * the code are not to be removed.
 * If this package is used in a product, Eric Young should be given attribution
 * as the author of the parts of the library used.
 * This can be in the form of a textual message at program startup or
 * in documentation (online or textual) provided with the package.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    "This product includes cryptographic software written by
 *     Eric Young (eay@cryptsoft.com)"
 *    The word 'cryptographic' can be left out if the rouines from the library
 *    being used are not cryptographic related :-).
 * 4. If you include any Windows specific code (or a derivative thereof) from 
 *    the apps directory (application code) you must include an acknowledgement:
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
 * 
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * 
 * The licence and distribution terms for any publically available version or
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 * copied and put under another distribution licence
 * [including the GNU Public Licence.]
 */

#include <stdio.h>
#include <stdlib.h>
61 62 63
#include <openssl/buffer.h>
#include <openssl/bio.h>
#include <openssl/lhash.h>
64 65
#include "cryptlib.h"

66 67 68
#ifdef CRYPTO_MDEBUG
static int mh_mode=CRYPTO_MEM_CHECK_ON;
#else
69
static int mh_mode=CRYPTO_MEM_CHECK_OFF;
70
#endif
71 72 73 74 75 76 77 78
static unsigned long order=0;

static LHASH *mh=NULL;

typedef struct mem_st
	{
	char *addr;
	int num;
B
Ben Laurie 已提交
79
	const char *file;
80 81 82 83
	int line;
	unsigned long order;
	} MEM;

U
Ulf Möller 已提交
84
int CRYPTO_mem_ctrl(int mode)
85 86 87 88 89 90 91 92 93 94 95 96
	{
	int ret=mh_mode;

	CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
	switch (mode)
		{
	case CRYPTO_MEM_CHECK_ON:
		mh_mode|=CRYPTO_MEM_CHECK_ON;
		break;
	case CRYPTO_MEM_CHECK_OFF:
		mh_mode&= ~CRYPTO_MEM_CHECK_ON;
		break;
97 98 99 100 101 102 103
	case CRYPTO_MEM_CHECK_DISABLE:
		mh_mode&= ~CRYPTO_MEM_CHECK_ENABLE;
		break;
	case CRYPTO_MEM_CHECK_ENABLE:
		if (mh_mode&CRYPTO_MEM_CHECK_ON)
			mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
		break;
104 105 106 107 108 109 110
	default:
		break;
		}
	CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
	return(ret);
	}

U
Ulf Möller 已提交
111
static int mem_cmp(MEM *a, MEM *b)
112 113 114 115
	{
	return(a->addr - b->addr);
	}

U
Ulf Möller 已提交
116
static unsigned long mem_hash(MEM *a)
117 118 119 120 121 122 123 124 125
	{
	unsigned long ret;

	ret=(unsigned long)a->addr;

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

126 127
static char *(*malloc_locked_func)()=(char *(*)())malloc;
static void (*free_locked_func)()=(void (*)())free;
128 129 130 131
static char *(*malloc_func)()=	(char *(*)())malloc;
static char *(*realloc_func)()=	(char *(*)())realloc;
static void (*free_func)()=	(void (*)())free;

U
Ulf Möller 已提交
132
void CRYPTO_set_mem_functions(char *(*m)(), char *(*r)(), void (*f)())
133 134 135 136 137
	{
	if ((m == NULL) || (r == NULL) || (f == NULL)) return;
	malloc_func=m;
	realloc_func=r;
	free_func=f;
138 139 140 141
	malloc_locked_func=m;
	free_locked_func=f;
	}

U
Ulf Möller 已提交
142
void CRYPTO_set_locked_mem_functions(char *(*m)(), void (*f)())
143 144 145 146
	{
	if ((m == NULL) || (f == NULL)) return;
	malloc_locked_func=m;
	free_locked_func=f;
147 148
	}

U
Ulf Möller 已提交
149
void CRYPTO_get_mem_functions(char *(**m)(), char *(**r)(), void (**f)())
150 151 152 153 154 155
	{
	if (m != NULL) *m=malloc_func;
	if (r != NULL) *r=realloc_func;
	if (f != NULL) *f=free_func;
	}

U
Ulf Möller 已提交
156
void CRYPTO_get_locked_mem_functions(char *(**m)(), void (**f)())
157 158 159 160 161
	{
	if (m != NULL) *m=malloc_locked_func;
	if (f != NULL) *f=free_locked_func;
	}

U
Ulf Möller 已提交
162
void *CRYPTO_malloc_locked(int num)
163 164 165 166
	{
	return(malloc_locked_func(num));
	}

U
Ulf Möller 已提交
167
void CRYPTO_free_locked(void *str)
168 169 170 171
	{
	free_locked_func(str);
	}

U
Ulf Möller 已提交
172
void *CRYPTO_malloc(int num)
173 174 175 176
	{
	return(malloc_func(num));
	}

U
Ulf Möller 已提交
177
void *CRYPTO_realloc(void *str, int num)
178 179 180 181
	{
	return(realloc_func(str,num));
	}

U
Ulf Möller 已提交
182
void CRYPTO_free(void *str)
183 184 185 186
	{
	free_func(str);
	}

187
static unsigned long break_order_num=0;
U
Ulf Möller 已提交
188
void *CRYPTO_dbg_malloc(int num, const char *file, int line)
189 190
	{
	char *ret;
191
	MEM *m,*mm;
192 193 194 195

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

196
	if (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
197
		{
198 199
		MemCheck_off();
		if ((m=(MEM *)Malloc(sizeof(MEM))) == NULL)
200
			{
201 202
			Free(ret);
			MemCheck_on();
203 204 205 206 207 208 209
			return(NULL);
			}
		CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
		if (mh == NULL)
			{
			if ((mh=lh_new(mem_hash,mem_cmp)) == NULL)
				{
210 211 212 213
				Free(ret);
				Free(m);
				ret=NULL;
				goto err;
214 215 216 217 218 219 220
				}
			}

		m->addr=ret;
		m->file=file;
		m->line=line;
		m->num=num;
221 222 223 224 225
		if (order == break_order_num)
			{
			/* BREAK HERE */
			m->order=order;
			}
226
		m->order=order++;
227
		if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL)
228
			{
229
			/* Not good, but don't sweat it */
230
			Free(mm);
231
			}
232
err:
233
		CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
234
		MemCheck_on();
235 236 237 238
		}
	return(ret);
	}

U
Ulf Möller 已提交
239
void CRYPTO_dbg_free(void *addr)
240 241 242
	{
	MEM m,*mp;

243
	if ((mh_mode & CRYPTO_MEM_CHECK_ENABLE) && (mh != NULL))
244
		{
245
		MemCheck_off();
246 247 248 249
		CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
		m.addr=addr;
		mp=(MEM *)lh_delete(mh,(char *)&m);
		if (mp != NULL)
250
			Free(mp);
251
		CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
252
		MemCheck_on();
253 254 255 256
		}
	free_func(addr);
	}

U
Ulf Möller 已提交
257
void *CRYPTO_dbg_realloc(void *addr, int num, const char *file, int line)
258 259 260 261 262 263 264
	{
	char *ret;
	MEM m,*mp;

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

265
	if (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
266
		{
267
		MemCheck_off();
268 269 270 271 272 273 274 275 276 277
		if (ret == NULL) return(NULL);
		m.addr=addr;
		CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
		mp=(MEM *)lh_delete(mh,(char *)&m);
		if (mp != NULL)
			{
			mp->addr=ret;
			lh_insert(mh,(char *)mp);
			}
		CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
278
		MemCheck_on();
279 280 281 282
		}
	return(ret);
	}

U
Ulf Möller 已提交
283
void *CRYPTO_remalloc(void *a, int n)
284 285 286 287 288 289
	{
	if (a != NULL) Free(a);
	a=(char *)Malloc(n);
	return(a);
	}

U
Ulf Möller 已提交
290
void *CRYPTO_dbg_remalloc(void *a, int n, const char *file, int line)
291 292 293 294 295 296 297 298 299 300 301 302 303 304
	{
	if (a != NULL) CRYPTO_dbg_free(a);
	a=(char *)CRYPTO_dbg_malloc(n,file,line);
	return(a);
	}


typedef struct mem_leak_st
	{
	BIO *bio;
	int chunks;
	long bytes;
	} MEM_LEAK;

U
Ulf Möller 已提交
305
static void print_leak(MEM *m, MEM_LEAK *l)
306 307 308
	{
	char buf[128];

B
Ben Laurie 已提交
309 310
	if(m->addr == (char *)l->bio)
	    return;
311 312 313 314 315 316 317
	sprintf(buf,"%5ld file=%s, line=%d, number=%d, address=%08lX\n",
		m->order,m->file,m->line,m->num,(long)m->addr);
	BIO_puts(l->bio,buf);
	l->chunks++;
	l->bytes+=m->num;
	}

U
Ulf Möller 已提交
318
void CRYPTO_mem_leaks(BIO *b)
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
	{
	MEM_LEAK ml;
	char buf[80];

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

#if 0
338 339 340
	lh_stats_bio(mh,b);
        lh_node_stats_bio(mh,b);
        lh_node_usage_stats_bio(mh,b);
341
#endif
342 343 344 345
	}

static void (*mem_cb)()=NULL;

U
Ulf Möller 已提交
346
static void cb_leak(MEM *m, char *cb)
347 348 349 350 351
	{
	void (*mem_callback)()=(void (*)())cb;
	mem_callback(m->order,m->file,m->line,m->num,m->addr);
	}

U
Ulf Möller 已提交
352
void CRYPTO_mem_leaks_cb(void (*cb)())
353 354 355 356 357 358 359 360 361
	{
	if (mh == NULL) return;
	CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
	mem_cb=cb;
	lh_doall_arg(mh,(void (*)())cb_leak,(char *)mem_cb);
	mem_cb=NULL;
	CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
	}

362
#ifndef NO_FP_API
U
Ulf Möller 已提交
363
void CRYPTO_mem_leaks_fp(FILE *fp)
364 365 366 367 368 369 370 371 372 373 374 375
	{
	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);
	}
#endif