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 "cryptlib.h"
63#include <openssl/crypto.h>
64#include <openssl/buffer.h>
65#include <openssl/bio.h>
66#include <openssl/lhash.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#ifdef _WIN64
256	const char *a=(const char *)((const MEM *)a_void)->addr,
257		   *b=(const char *)((const MEM *)b_void)->addr;
258	if (a==b)	return 0;
259	else if (a>b)	return 1;
260	else		return -1;
261#else
262	return((const char *)((const MEM *)a_void)->addr
263		- (const char *)((const MEM *)b_void)->addr);
264#endif
265	}
266
267/* static unsigned long mem_hash(MEM *a) */
268static unsigned long mem_hash(const void *a_void)
269	{
270	unsigned long ret;
271
272	ret=(unsigned long)((const MEM *)a_void)->addr;
273
274	ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
275	return(ret);
276	}
277
278/* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */
279static int app_info_cmp(const void *a_void, const void *b_void)
280	{
281	return(((const APP_INFO *)a_void)->thread
282		!= ((const APP_INFO *)b_void)->thread);
283	}
284
285/* static unsigned long app_info_hash(APP_INFO *a) */
286static unsigned long app_info_hash(const void *a_void)
287	{
288	unsigned long ret;
289
290	ret=(unsigned long)((const APP_INFO *)a_void)->thread;
291
292	ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
293	return(ret);
294	}
295
296static APP_INFO *pop_info(void)
297	{
298	APP_INFO tmp;
299	APP_INFO *ret = NULL;
300
301	if (amih != NULL)
302		{
303		tmp.thread=CRYPTO_thread_id();
304		if ((ret=(APP_INFO *)lh_delete(amih,&tmp)) != NULL)
305			{
306			APP_INFO *next=ret->next;
307
308			if (next != NULL)
309				{
310				next->references++;
311				lh_insert(amih,(char *)next);
312				}
313#ifdef LEVITTE_DEBUG_MEM
314			if (ret->thread != tmp.thread)
315				{
316				fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
317					ret->thread, tmp.thread);
318				abort();
319				}
320#endif
321			if (--(ret->references) <= 0)
322				{
323				ret->next = NULL;
324				if (next != NULL)
325					next->references--;
326				OPENSSL_free(ret);
327				}
328			}
329		}
330	return(ret);
331	}
332
333int CRYPTO_push_info_(const char *info, const char *file, int line)
334	{
335	APP_INFO *ami, *amim;
336	int ret=0;
337
338	if (is_MemCheck_on())
339		{
340		MemCheck_off(); /* obtain MALLOC2 lock */
341
342		if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL)
343			{
344			ret=0;
345			goto err;
346			}
347		if (amih == NULL)
348			{
349			if ((amih=lh_new(app_info_hash, app_info_cmp)) == NULL)
350				{
351				OPENSSL_free(ami);
352				ret=0;
353				goto err;
354				}
355			}
356
357		ami->thread=CRYPTO_thread_id();
358		ami->file=file;
359		ami->line=line;
360		ami->info=info;
361		ami->references=1;
362		ami->next=NULL;
363
364		if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL)
365			{
366#ifdef LEVITTE_DEBUG_MEM
367			if (ami->thread != amim->thread)
368				{
369				fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
370					amim->thread, ami->thread);
371				abort();
372				}
373#endif
374			ami->next=amim;
375			}
376 err:
377		MemCheck_on(); /* release MALLOC2 lock */
378		}
379
380	return(ret);
381	}
382
383int CRYPTO_pop_info(void)
384	{
385	int ret=0;
386
387	if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */
388		{
389		MemCheck_off(); /* obtain MALLOC2 lock */
390
391		ret=(pop_info() != NULL);
392
393		MemCheck_on(); /* release MALLOC2 lock */
394		}
395	return(ret);
396	}
397
398int CRYPTO_remove_all_info(void)
399	{
400	int ret=0;
401
402	if (is_MemCheck_on()) /* _must_ be true */
403		{
404		MemCheck_off(); /* obtain MALLOC2 lock */
405
406		while(pop_info() != NULL)
407			ret++;
408
409		MemCheck_on(); /* release MALLOC2 lock */
410		}
411	return(ret);
412	}
413
414
415static unsigned long break_order_num=0;
416void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
417	int before_p)
418	{
419	MEM *m,*mm;
420	APP_INFO tmp,*amim;
421
422	switch(before_p & 127)
423		{
424	case 0:
425		break;
426	case 1:
427		if (addr == NULL)
428			break;
429
430		if (is_MemCheck_on())
431			{
432			MemCheck_off(); /* make sure we hold MALLOC2 lock */
433			if ((m=(MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL)
434				{
435				OPENSSL_free(addr);
436				MemCheck_on(); /* release MALLOC2 lock
437				                * if num_disabled drops to 0 */
438				return;
439				}
440			if (mh == NULL)
441				{
442				if ((mh=lh_new(mem_hash, mem_cmp)) == NULL)
443					{
444					OPENSSL_free(addr);
445					OPENSSL_free(m);
446					addr=NULL;
447					goto err;
448					}
449				}
450
451			m->addr=addr;
452			m->file=file;
453			m->line=line;
454			m->num=num;
455			if (options & V_CRYPTO_MDEBUG_THREAD)
456				m->thread=CRYPTO_thread_id();
457			else
458				m->thread=0;
459
460			if (order == break_order_num)
461				{
462				/* BREAK HERE */
463				m->order=order;
464				}
465			m->order=order++;
466#ifdef LEVITTE_DEBUG_MEM
467			fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] %c 0x%p (%d)\n",
468				m->order,
469				(before_p & 128) ? '*' : '+',
470				m->addr, m->num);
471#endif
472			if (options & V_CRYPTO_MDEBUG_TIME)
473				m->time=time(NULL);
474			else
475				m->time=0;
476
477			tmp.thread=CRYPTO_thread_id();
478			m->app_info=NULL;
479			if (amih != NULL
480				&& (amim=(APP_INFO *)lh_retrieve(amih,(char *)&tmp)) != NULL)
481				{
482				m->app_info = amim;
483				amim->references++;
484				}
485
486			if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL)
487				{
488				/* Not good, but don't sweat it */
489				if (mm->app_info != NULL)
490					{
491					mm->app_info->references--;
492					}
493				OPENSSL_free(mm);
494				}
495		err:
496			MemCheck_on(); /* release MALLOC2 lock
497			                * if num_disabled drops to 0 */
498			}
499		break;
500		}
501	return;
502	}
503
504void CRYPTO_dbg_free(void *addr, int before_p)
505	{
506	MEM m,*mp;
507
508	switch(before_p)
509		{
510	case 0:
511		if (addr == NULL)
512			break;
513
514		if (is_MemCheck_on() && (mh != NULL))
515			{
516			MemCheck_off(); /* make sure we hold MALLOC2 lock */
517
518			m.addr=addr;
519			mp=(MEM *)lh_delete(mh,(char *)&m);
520			if (mp != NULL)
521				{
522#ifdef LEVITTE_DEBUG_MEM
523			fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] - 0x%p (%d)\n",
524				mp->order, mp->addr, mp->num);
525#endif
526				if (mp->app_info != NULL)
527					app_info_free(mp->app_info);
528				OPENSSL_free(mp);
529				}
530
531			MemCheck_on(); /* release MALLOC2 lock
532			                * if num_disabled drops to 0 */
533			}
534		break;
535	case 1:
536		break;
537		}
538	}
539
540void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
541	const char *file, int line, int before_p)
542	{
543	MEM m,*mp;
544
545#ifdef LEVITTE_DEBUG_MEM
546	fprintf(stderr, "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n",
547		addr1, addr2, num, file, line, before_p);
548#endif
549
550	switch(before_p)
551		{
552	case 0:
553		break;
554	case 1:
555		if (addr2 == NULL)
556			break;
557
558		if (addr1 == NULL)
559			{
560			CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p);
561			break;
562			}
563
564		if (is_MemCheck_on())
565			{
566			MemCheck_off(); /* make sure we hold MALLOC2 lock */
567
568			m.addr=addr1;
569			mp=(MEM *)lh_delete(mh,(char *)&m);
570			if (mp != NULL)
571				{
572#ifdef LEVITTE_DEBUG_MEM
573				fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] * 0x%p (%d) -> 0x%p (%d)\n",
574					mp->order,
575					mp->addr, mp->num,
576					addr2, num);
577#endif
578				mp->addr=addr2;
579				mp->num=num;
580				lh_insert(mh,(char *)mp);
581				}
582
583			MemCheck_on(); /* release MALLOC2 lock
584			                * if num_disabled drops to 0 */
585			}
586		break;
587		}
588	return;
589	}
590
591
592typedef struct mem_leak_st
593	{
594	BIO *bio;
595	int chunks;
596	long bytes;
597	} MEM_LEAK;
598
599static void print_leak(const MEM *m, MEM_LEAK *l)
600	{
601	char buf[1024];
602	char *bufp = buf;
603	APP_INFO *amip;
604	int ami_cnt;
605	struct tm *lcl = NULL;
606	unsigned long ti;
607
608#define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf))
609
610	if(m->addr == (char *)l->bio)
611	    return;
612
613	if (options & V_CRYPTO_MDEBUG_TIME)
614		{
615		lcl = localtime(&m->time);
616
617		BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ",
618			lcl->tm_hour,lcl->tm_min,lcl->tm_sec);
619		bufp += strlen(bufp);
620		}
621
622	BIO_snprintf(bufp, BUF_REMAIN, "%5lu file=%s, line=%d, ",
623		m->order,m->file,m->line);
624	bufp += strlen(bufp);
625
626	if (options & V_CRYPTO_MDEBUG_THREAD)
627		{
628		BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ", m->thread);
629		bufp += strlen(bufp);
630		}
631
632	BIO_snprintf(bufp, BUF_REMAIN, "number=%d, address=%08lX\n",
633		m->num,(unsigned long)m->addr);
634	bufp += strlen(bufp);
635
636	BIO_puts(l->bio,buf);
637
638	l->chunks++;
639	l->bytes+=m->num;
640
641	amip=m->app_info;
642	ami_cnt=0;
643	if (!amip)
644		return;
645	ti=amip->thread;
646
647	do
648		{
649		int buf_len;
650		int info_len;
651
652		ami_cnt++;
653		memset(buf,'>',ami_cnt);
654		BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt,
655			" thread=%lu, file=%s, line=%d, info=\"",
656			amip->thread, amip->file, amip->line);
657		buf_len=strlen(buf);
658		info_len=strlen(amip->info);
659		if (128 - buf_len - 3 < info_len)
660			{
661			memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
662			buf_len = 128 - 3;
663			}
664		else
665			{
666			BUF_strlcpy(buf + buf_len, amip->info,
667				    sizeof buf - buf_len);
668			buf_len = strlen(buf);
669			}
670		BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n");
671
672		BIO_puts(l->bio,buf);
673
674		amip = amip->next;
675		}
676	while(amip && amip->thread == ti);
677
678#ifdef LEVITTE_DEBUG_MEM
679	if (amip)
680		{
681		fprintf(stderr, "Thread switch detected in backtrace!!!!\n");
682		abort();
683		}
684#endif
685	}
686
687static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM *, MEM_LEAK *)
688
689void CRYPTO_mem_leaks(BIO *b)
690	{
691	MEM_LEAK ml;
692
693	if (mh == NULL && amih == NULL)
694		return;
695
696	MemCheck_off(); /* obtain MALLOC2 lock */
697
698	ml.bio=b;
699	ml.bytes=0;
700	ml.chunks=0;
701	if (mh != NULL)
702		lh_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak),
703				(char *)&ml);
704	if (ml.chunks != 0)
705		{
706		BIO_printf(b,"%ld bytes leaked in %d chunks\n",
707			   ml.bytes,ml.chunks);
708		}
709	else
710		{
711		/* Make sure that, if we found no leaks, memory-leak debugging itself
712		 * does not introduce memory leaks (which might irritate
713		 * external debugging tools).
714		 * (When someone enables leak checking, but does not call
715		 * this function, we declare it to be their fault.)
716		 *
717		 * XXX    This should be in CRYPTO_mem_leaks_cb,
718		 * and CRYPTO_mem_leaks should be implemented by
719		 * using CRYPTO_mem_leaks_cb.
720		 * (Also their should be a variant of lh_doall_arg
721		 * that takes a function pointer instead of a void *;
722		 * this would obviate the ugly and illegal
723		 * void_fn_to_char kludge in CRYPTO_mem_leaks_cb.
724		 * Otherwise the code police will come and get us.)
725		 */
726		int old_mh_mode;
727
728		CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
729
730		/* avoid deadlock when lh_free() uses CRYPTO_dbg_free(),
731		 * which uses CRYPTO_is_mem_check_on */
732		old_mh_mode = mh_mode;
733		mh_mode = CRYPTO_MEM_CHECK_OFF;
734
735		if (mh != NULL)
736			{
737			lh_free(mh);
738			mh = NULL;
739			}
740		if (amih != NULL)
741			{
742			if (lh_num_items(amih) == 0)
743				{
744				lh_free(amih);
745				amih = NULL;
746				}
747			}
748
749		mh_mode = old_mh_mode;
750		CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
751		}
752	MemCheck_on(); /* release MALLOC2 lock */
753	}
754
755#ifndef OPENSSL_NO_FP_API
756void CRYPTO_mem_leaks_fp(FILE *fp)
757	{
758	BIO *b;
759
760	if (mh == NULL) return;
761	/* Need to turn off memory checking when allocated BIOs ... especially
762	 * as we're creating them at a time when we're trying to check we've not
763	 * left anything un-free()'d!! */
764	MemCheck_off();
765	b = BIO_new(BIO_s_file());
766	MemCheck_on();
767	if(!b) return;
768	BIO_set_fp(b,fp,BIO_NOCLOSE);
769	CRYPTO_mem_leaks(b);
770	BIO_free(b);
771	}
772#endif
773
774
775
776/* FIXME: We really don't allow much to the callback.  For example, it has
777   no chance of reaching the info stack for the item it processes.  Should
778   it really be this way?  -- Richard Levitte */
779/* NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside crypto.h
780 * If this code is restructured, remove the callback type if it is no longer
781 * needed. -- Geoff Thorpe */
782static void cb_leak(const MEM *m, CRYPTO_MEM_LEAK_CB **cb)
783	{
784	(**cb)(m->order,m->file,m->line,m->num,m->addr);
785	}
786
787static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM *, CRYPTO_MEM_LEAK_CB **)
788
789void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
790	{
791	if (mh == NULL) return;
792	CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
793	lh_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), &cb);
794	CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
795	}
796