1/* crypto/mem_dbg.c */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@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@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@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@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#include <stdio.h>
60#include <stdlib.h>
61#include <time.h>
62#include <openssl/crypto.h>
63#include <openssl/buffer.h>
64#include <openssl/bio.h>
65#include <openssl/lhash.h>
66#include "cryptlib.h"
67
68static int mh_mode=CRYPTO_MEM_CHECK_OFF;
69/* The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE
70 * when the application asks for it (usually after library initialisation
71 * for which no book-keeping is desired).
72 *
73 * State CRYPTO_MEM_CHECK_ON exists only temporarily when the library
74 * thinks that certain allocations should not be checked (e.g. the data
75 * structures used for memory checking).  It is not suitable as an initial
76 * state: the library will unexpectedly enable memory checking when it
77 * executes one of those sections that want to disable checking
78 * temporarily.
79 *
80 * State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes no sense whatsoever.
81 */
82
83static unsigned long order = 0; /* number of memory requests */
84static LHASH *mh=NULL; /* hash-table of memory requests (address as key);
85                        * access requires MALLOC2 lock */
86
87
88typedef struct app_mem_info_st
89/* For application-defined information (static C-string `info')
90 * to be displayed in memory leak list.
91 * Each thread has its own stack.  For applications, there is
92 *   CRYPTO_push_info("...")     to push an entry,
93 *   CRYPTO_pop_info()           to pop an entry,
94 *   CRYPTO_remove_all_info()    to pop all entries.
95 */
96	{
97	unsigned long thread;
98	const char *file;
99	int line;
100	const char *info;
101	struct app_mem_info_st *next; /* tail of thread's stack */
102	int references;
103	} APP_INFO;
104
105static void app_info_free(APP_INFO *);
106
107static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's
108                          * that are at the top of their thread's stack
109                          * (with `thread' as key);
110                          * access requires MALLOC2 lock */
111
112typedef struct mem_st
113/* memory-block description */
114	{
115	void *addr;
116	int num;
117	const char *file;
118	int line;
119	unsigned long thread;
120	unsigned long order;
121	time_t time;
122	APP_INFO *app_info;
123	} MEM;
124
125static long options =             /* extra information to be recorded */
126#if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL)
127	V_CRYPTO_MDEBUG_TIME |
128#endif
129#if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL)
130	V_CRYPTO_MDEBUG_THREAD |
131#endif
132	0;
133
134
135static unsigned int num_disable = 0; /* num_disable > 0
136                                      *     iff
137                                      * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE)
138                                      */
139static unsigned long disabling_thread = 0; /* Valid iff num_disable > 0.
140                                            * CRYPTO_LOCK_MALLOC2 is locked
141                                            * exactly in this case (by the
142                                            * thread named in disabling_thread).
143                                            */
144
145static void app_info_free(APP_INFO *inf)
146	{
147	if (--(inf->references) <= 0)
148		{
149		if (inf->next != NULL)
150			{
151			app_info_free(inf->next);
152			}
153		OPENSSL_free(inf);
154		}
155	}
156
157int CRYPTO_mem_ctrl(int mode)
158	{
159	int ret=mh_mode;
160
161	CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
162	switch (mode)
163		{
164	/* for applications (not to be called while multiple threads
165	 * use the library): */
166	case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */
167		mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
168		num_disable = 0;
169		break;
170	case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
171		mh_mode = 0;
172		num_disable = 0; /* should be true *before* MemCheck_stop is used,
173		                    or there'll be a lot of confusion */
174		break;
175
176	/* switch off temporarily (for library-internal use): */
177	case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
178		if (mh_mode & CRYPTO_MEM_CHECK_ON)
179			{
180			if (!num_disable || (disabling_thread != CRYPTO_thread_id())) /* otherwise we already have the MALLOC2 lock */
181				{
182				/* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while
183				 * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if
184				 * somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot release
185				 * it because we block entry to this function).
186				 * Give them a chance, first, and then claim the locks in
187				 * appropriate order (long-time lock first).
188				 */
189				CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
190				/* Note that after we have waited for CRYPTO_LOCK_MALLOC2
191				 * and CRYPTO_LOCK_MALLOC, we'll still be in the right
192				 * "case" and "if" branch because MemCheck_start and
193				 * MemCheck_stop may never be used while there are multiple
194				 * OpenSSL threads. */
195				CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
196				CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
197				mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE;
198				disabling_thread=CRYPTO_thread_id();
199				}
200			num_disable++;
201			}
202		break;
203	case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */
204		if (mh_mode & CRYPTO_MEM_CHECK_ON)
205			{
206			if (num_disable) /* always true, or something is going wrong */
207				{
208				num_disable--;
209				if (num_disable == 0)
210					{
211					mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
212					CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
213					}
214				}
215			}
216		break;
217
218	default:
219		break;
220		}
221	CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
222	return(ret);
223	}
224
225int CRYPTO_is_mem_check_on(void)
226	{
227	int ret = 0;
228
229	if (mh_mode & CRYPTO_MEM_CHECK_ON)
230		{
231		CRYPTO_r_lock(CRYPTO_LOCK_MALLOC);
232
233		ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
234			|| (disabling_thread != CRYPTO_thread_id());
235
236		CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC);
237		}
238	return(ret);
239	}
240
241
242void CRYPTO_dbg_set_options(long bits)
243	{
244	options = bits;
245	}
246
247long CRYPTO_dbg_get_options(void)
248	{
249	return options;
250	}
251
252/* static int mem_cmp(MEM *a, MEM *b) */
253static int mem_cmp(const void *a_void, const void *b_void)
254	{
255	return((const char *)((const MEM *)a_void)->addr
256		- (const char *)((const MEM *)b_void)->addr);
257	}
258
259/* static unsigned long mem_hash(MEM *a) */
260static unsigned long mem_hash(const void *a_void)
261	{
262	unsigned long ret;
263
264	ret=(unsigned long)((const MEM *)a_void)->addr;
265
266	ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
267	return(ret);
268	}
269
270/* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */
271static int app_info_cmp(const void *a_void, const void *b_void)
272	{
273	return(((const APP_INFO *)a_void)->thread
274		!= ((const APP_INFO *)b_void)->thread);
275	}
276
277/* static unsigned long app_info_hash(APP_INFO *a) */
278static unsigned long app_info_hash(const void *a_void)
279	{
280	unsigned long ret;
281
282	ret=(unsigned long)((const APP_INFO *)a_void)->thread;
283
284	ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
285	return(ret);
286	}
287
288static APP_INFO *pop_info(void)
289	{
290	APP_INFO tmp;
291	APP_INFO *ret = NULL;
292
293	if (amih != NULL)
294		{
295		tmp.thread=CRYPTO_thread_id();
296		if ((ret=(APP_INFO *)lh_delete(amih,&tmp)) != NULL)
297			{
298			APP_INFO *next=ret->next;
299
300			if (next != NULL)
301				{
302				next->references++;
303				lh_insert(amih,(char *)next);
304				}
305#ifdef LEVITTE_DEBUG_MEM
306			if (ret->thread != tmp.thread)
307				{
308				fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
309					ret->thread, tmp.thread);
310				abort();
311				}
312#endif
313			if (--(ret->references) <= 0)
314				{
315				ret->next = NULL;
316				if (next != NULL)
317					next->references--;
318				OPENSSL_free(ret);
319				}
320			}
321		}
322	return(ret);
323	}
324
325int CRYPTO_push_info_(const char *info, const char *file, int line)
326	{
327	APP_INFO *ami, *amim;
328	int ret=0;
329
330	if (is_MemCheck_on())
331		{
332		MemCheck_off(); /* obtain MALLOC2 lock */
333
334		if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL)
335			{
336			ret=0;
337			goto err;
338			}
339		if (amih == NULL)
340			{
341			if ((amih=lh_new(app_info_hash, app_info_cmp)) == NULL)
342				{
343				OPENSSL_free(ami);
344				ret=0;
345				goto err;
346				}
347			}
348
349		ami->thread=CRYPTO_thread_id();
350		ami->file=file;
351		ami->line=line;
352		ami->info=info;
353		ami->references=1;
354		ami->next=NULL;
355
356		if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL)
357			{
358#ifdef LEVITTE_DEBUG_MEM
359			if (ami->thread != amim->thread)
360				{
361				fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
362					amim->thread, ami->thread);
363				abort();
364				}
365#endif
366			ami->next=amim;
367			}
368 err:
369		MemCheck_on(); /* release MALLOC2 lock */
370		}
371
372	return(ret);
373	}
374
375int CRYPTO_pop_info(void)
376	{
377	int ret=0;
378
379	if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */
380		{
381		MemCheck_off(); /* obtain MALLOC2 lock */
382
383		ret=(pop_info() != NULL);
384
385		MemCheck_on(); /* release MALLOC2 lock */
386		}
387	return(ret);
388	}
389
390int CRYPTO_remove_all_info(void)
391	{
392	int ret=0;
393
394	if (is_MemCheck_on()) /* _must_ be true */
395		{
396		MemCheck_off(); /* obtain MALLOC2 lock */
397
398		while(pop_info() != NULL)
399			ret++;
400
401		MemCheck_on(); /* release MALLOC2 lock */
402		}
403	return(ret);
404	}
405
406
407static unsigned long break_order_num=0;
408void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
409	int before_p)
410	{
411	MEM *m,*mm;
412	APP_INFO tmp,*amim;
413
414	switch(before_p & 127)
415		{
416	case 0:
417		break;
418	case 1:
419		if (addr == NULL)
420			break;
421
422		if (is_MemCheck_on())
423			{
424			MemCheck_off(); /* make sure we hold MALLOC2 lock */
425			if ((m=(MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL)
426				{
427				OPENSSL_free(addr);
428				MemCheck_on(); /* release MALLOC2 lock
429				                * if num_disabled drops to 0 */
430				return;
431				}
432			if (mh == NULL)
433				{
434				if ((mh=lh_new(mem_hash, mem_cmp)) == NULL)
435					{
436					OPENSSL_free(addr);
437					OPENSSL_free(m);
438					addr=NULL;
439					goto err;
440					}
441				}
442
443			m->addr=addr;
444			m->file=file;
445			m->line=line;
446			m->num=num;
447			if (options & V_CRYPTO_MDEBUG_THREAD)
448				m->thread=CRYPTO_thread_id();
449			else
450				m->thread=0;
451
452			if (order == break_order_num)
453				{
454				/* BREAK HERE */
455				m->order=order;
456				}
457			m->order=order++;
458#ifdef LEVITTE_DEBUG_MEM
459			fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] %c 0x%p (%d)\n",
460				m->order,
461				(before_p & 128) ? '*' : '+',
462				m->addr, m->num);
463#endif
464			if (options & V_CRYPTO_MDEBUG_TIME)
465				m->time=time(NULL);
466			else
467				m->time=0;
468
469			tmp.thread=CRYPTO_thread_id();
470			m->app_info=NULL;
471			if (amih != NULL
472				&& (amim=(APP_INFO *)lh_retrieve(amih,(char *)&tmp)) != NULL)
473				{
474				m->app_info = amim;
475				amim->references++;
476				}
477
478			if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL)
479				{
480				/* Not good, but don't sweat it */
481				if (mm->app_info != NULL)
482					{
483					mm->app_info->references--;
484					}
485				OPENSSL_free(mm);
486				}
487		err:
488			MemCheck_on(); /* release MALLOC2 lock
489			                * if num_disabled drops to 0 */
490			}
491		break;
492		}
493	return;
494	}
495
496void CRYPTO_dbg_free(void *addr, int before_p)
497	{
498	MEM m,*mp;
499
500	switch(before_p)
501		{
502	case 0:
503		if (addr == NULL)
504			break;
505
506		if (is_MemCheck_on() && (mh != NULL))
507			{
508			MemCheck_off(); /* make sure we hold MALLOC2 lock */
509
510			m.addr=addr;
511			mp=(MEM *)lh_delete(mh,(char *)&m);
512			if (mp != NULL)
513				{
514#ifdef LEVITTE_DEBUG_MEM
515			fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] - 0x%p (%d)\n",
516				mp->order, mp->addr, mp->num);
517#endif
518				if (mp->app_info != NULL)
519					app_info_free(mp->app_info);
520				OPENSSL_free(mp);
521				}
522
523			MemCheck_on(); /* release MALLOC2 lock
524			                * if num_disabled drops to 0 */
525			}
526		break;
527	case 1:
528		break;
529		}
530	}
531
532void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
533	const char *file, int line, int before_p)
534	{
535	MEM m,*mp;
536
537#ifdef LEVITTE_DEBUG_MEM
538	fprintf(stderr, "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n",
539		addr1, addr2, num, file, line, before_p);
540#endif
541
542	switch(before_p)
543		{
544	case 0:
545		break;
546	case 1:
547		if (addr2 == NULL)
548			break;
549
550		if (addr1 == NULL)
551			{
552			CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p);
553			break;
554			}
555
556		if (is_MemCheck_on())
557			{
558			MemCheck_off(); /* make sure we hold MALLOC2 lock */
559
560			m.addr=addr1;
561			mp=(MEM *)lh_delete(mh,(char *)&m);
562			if (mp != NULL)
563				{
564#ifdef LEVITTE_DEBUG_MEM
565				fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] * 0x%p (%d) -> 0x%p (%d)\n",
566					mp->order,
567					mp->addr, mp->num,
568					addr2, num);
569#endif
570				mp->addr=addr2;
571				mp->num=num;
572				lh_insert(mh,(char *)mp);
573				}
574
575			MemCheck_on(); /* release MALLOC2 lock
576			                * if num_disabled drops to 0 */
577			}
578		break;
579		}
580	return;
581	}
582
583
584typedef struct mem_leak_st
585	{
586	BIO *bio;
587	int chunks;
588	long bytes;
589	} MEM_LEAK;
590
591static void print_leak(const MEM *m, MEM_LEAK *l)
592	{
593	char buf[1024];
594	char *bufp = buf;
595	APP_INFO *amip;
596	int ami_cnt;
597	struct tm *lcl = NULL;
598	unsigned long ti;
599
600#define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf))
601
602	if(m->addr == (char *)l->bio)
603	    return;
604
605	if (options & V_CRYPTO_MDEBUG_TIME)
606		{
607		lcl = localtime(&m->time);
608
609		BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ",
610			lcl->tm_hour,lcl->tm_min,lcl->tm_sec);
611		bufp += strlen(bufp);
612		}
613
614	BIO_snprintf(bufp, BUF_REMAIN, "%5lu file=%s, line=%d, ",
615		m->order,m->file,m->line);
616	bufp += strlen(bufp);
617
618	if (options & V_CRYPTO_MDEBUG_THREAD)
619		{
620		BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ", m->thread);
621		bufp += strlen(bufp);
622		}
623
624	BIO_snprintf(bufp, BUF_REMAIN, "number=%d, address=%08lX\n",
625		m->num,(unsigned long)m->addr);
626	bufp += strlen(bufp);
627
628	BIO_puts(l->bio,buf);
629
630	l->chunks++;
631	l->bytes+=m->num;
632
633	amip=m->app_info;
634	ami_cnt=0;
635	if (!amip)
636		return;
637	ti=amip->thread;
638
639	do
640		{
641		int buf_len;
642		int info_len;
643
644		ami_cnt++;
645		memset(buf,'>',ami_cnt);
646		BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt,
647			" thread=%lu, file=%s, line=%d, info=\"",
648			amip->thread, amip->file, amip->line);
649		buf_len=strlen(buf);
650		info_len=strlen(amip->info);
651		if (128 - buf_len - 3 < info_len)
652			{
653			memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
654			buf_len = 128 - 3;
655			}
656		else
657			{
658			BUF_strlcpy(buf + buf_len, amip->info,
659				    sizeof buf - buf_len);
660			buf_len = strlen(buf);
661			}
662		BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n");
663
664		BIO_puts(l->bio,buf);
665
666		amip = amip->next;
667		}
668	while(amip && amip->thread == ti);
669
670#ifdef LEVITTE_DEBUG_MEM
671	if (amip)
672		{
673		fprintf(stderr, "Thread switch detected in backtrace!!!!\n");
674		abort();
675		}
676#endif
677	}
678
679static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM *, MEM_LEAK *)
680
681void CRYPTO_mem_leaks(BIO *b)
682	{
683	MEM_LEAK ml;
684
685	if (mh == NULL && amih == NULL)
686		return;
687
688	MemCheck_off(); /* obtain MALLOC2 lock */
689
690	ml.bio=b;
691	ml.bytes=0;
692	ml.chunks=0;
693	if (mh != NULL)
694		lh_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak),
695				(char *)&ml);
696	if (ml.chunks != 0)
697		{
698		BIO_printf(b,"%ld bytes leaked in %d chunks\n",
699			   ml.bytes,ml.chunks);
700		}
701	else
702		{
703		/* Make sure that, if we found no leaks, memory-leak debugging itself
704		 * does not introduce memory leaks (which might irritate
705		 * external debugging tools).
706		 * (When someone enables leak checking, but does not call
707		 * this function, we declare it to be their fault.)
708		 *
709		 * XXX    This should be in CRYPTO_mem_leaks_cb,
710		 * and CRYPTO_mem_leaks should be implemented by
711		 * using CRYPTO_mem_leaks_cb.
712		 * (Also their should be a variant of lh_doall_arg
713		 * that takes a function pointer instead of a void *;
714		 * this would obviate the ugly and illegal
715		 * void_fn_to_char kludge in CRYPTO_mem_leaks_cb.
716		 * Otherwise the code police will come and get us.)
717		 */
718		int old_mh_mode;
719
720		CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
721
722		/* avoid deadlock when lh_free() uses CRYPTO_dbg_free(),
723		 * which uses CRYPTO_is_mem_check_on */
724		old_mh_mode = mh_mode;
725		mh_mode = CRYPTO_MEM_CHECK_OFF;
726
727		if (mh != NULL)
728			{
729			lh_free(mh);
730			mh = NULL;
731			}
732		if (amih != NULL)
733			{
734			if (lh_num_items(amih) == 0)
735				{
736				lh_free(amih);
737				amih = NULL;
738				}
739			}
740
741		mh_mode = old_mh_mode;
742		CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
743		}
744	MemCheck_on(); /* release MALLOC2 lock */
745	}
746
747#ifndef OPENSSL_NO_FP_API
748void CRYPTO_mem_leaks_fp(FILE *fp)
749	{
750	BIO *b;
751
752	if (mh == NULL) return;
753	/* Need to turn off memory checking when allocated BIOs ... especially
754	 * as we're creating them at a time when we're trying to check we've not
755	 * left anything un-free()'d!! */
756	MemCheck_off();
757	b = BIO_new(BIO_s_file());
758	MemCheck_on();
759	if(!b) return;
760	BIO_set_fp(b,fp,BIO_NOCLOSE);
761	CRYPTO_mem_leaks(b);
762	BIO_free(b);
763	}
764#endif
765
766
767
768/* FIXME: We really don't allow much to the callback.  For example, it has
769   no chance of reaching the info stack for the item it processes.  Should
770   it really be this way?  -- Richard Levitte */
771/* NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside crypto.h
772 * If this code is restructured, remove the callback type if it is no longer
773 * needed. -- Geoff Thorpe */
774static void cb_leak(const MEM *m, CRYPTO_MEM_LEAK_CB **cb)
775	{
776	(**cb)(m->order,m->file,m->line,m->num,m->addr);
777	}
778
779static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM *, CRYPTO_MEM_LEAK_CB **)
780
781void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
782	{
783	if (mh == NULL) return;
784	CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
785	lh_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), &cb);
786	CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
787	}
788