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