mem_dbg.c revision 1.14
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
143typedef struct app_mem_info_st
144/* For application-defined information (static C-string `info')
145 * to be displayed in memory leak list.
146 * Each thread has its own stack.  For applications, there is
147 *   CRYPTO_push_info("...")     to push an entry,
148 *   CRYPTO_pop_info()           to pop an entry,
149 *   CRYPTO_remove_all_info()    to pop all entries.
150 */
151{
152	CRYPTO_THREADID threadid;
153	const char *file;
154	int line;
155	const char *info;
156	struct app_mem_info_st *next; /* tail of thread's stack */
157	int references;
158} APP_INFO;
159
160static void app_info_free(APP_INFO *);
161
162DECLARE_LHASH_OF(APP_INFO);
163static LHASH_OF(APP_INFO) *amih = NULL; /* hash - table with those
164					 * app_mem_info_st's that are at
165					 * the top of their thread's
166					 * stack (with `thread' as key);
167					 * access requires MALLOC2
168					 * lock */
169
170typedef struct mem_st
171/* memory-block description */
172{
173	void *addr;
174	int num;
175	const char *file;
176	int line;
177	CRYPTO_THREADID threadid;
178	unsigned long order;
179	time_t time;
180	APP_INFO *app_info;
181} MEM;
182
183static long options =             /* extra information to be recorded */
184#if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL)
185V_CRYPTO_MDEBUG_TIME |
186#endif
187#if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL)
188V_CRYPTO_MDEBUG_THREAD |
189#endif
1900;
191
192
193static unsigned int num_disable = 0; /* num_disable > 0
194				      *     iff
195				      * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE)
196				      */
197
198/* Valid iff num_disable > 0.  CRYPTO_LOCK_MALLOC2 is locked exactly in this
199 * case (by the thread named in disabling_thread).
200 */
201static CRYPTO_THREADID disabling_threadid;
202
203static void
204app_info_free(APP_INFO *inf)
205{
206	if (--(inf->references) <= 0) {
207		if (inf->next != NULL) {
208			app_info_free(inf->next);
209		}
210		OPENSSL_free(inf);
211	}
212}
213
214int
215CRYPTO_mem_ctrl(int mode)
216{
217	int ret = mh_mode;
218
219	CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
220	switch (mode) {
221	/* for applications (not to be called while multiple threads
222	 * use the library): */
223	case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */
224		mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
225		num_disable = 0;
226		break;
227	case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
228		mh_mode = 0;
229		num_disable = 0; /* should be true *before* MemCheck_stop is used,
230		                    or there'll be a lot of confusion */
231		break;
232
233		/* switch off temporarily (for library-internal use): */
234	case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
235		if (mh_mode & CRYPTO_MEM_CHECK_ON) {
236			CRYPTO_THREADID cur;
237			CRYPTO_THREADID_current(&cur);
238			if (!num_disable || CRYPTO_THREADID_cmp(&disabling_threadid, &cur)) /* otherwise we already have the MALLOC2 lock */
239			{
240				/* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while
241				 * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if
242				 * somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot release
243				 * it because we block entry to this function).
244				 * Give them a chance, first, and then claim the locks in
245				 * appropriate order (long-time lock first).
246				 */
247				CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
248				/* Note that after we have waited for CRYPTO_LOCK_MALLOC2
249				 * and CRYPTO_LOCK_MALLOC, we'll still be in the right
250				 * "case" and "if" branch because MemCheck_start and
251				 * MemCheck_stop may never be used while there are multiple
252				 * OpenSSL threads. */
253				CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
254				CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
255				mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE;
256				CRYPTO_THREADID_cpy(&disabling_threadid, &cur);
257			}
258			num_disable++;
259		}
260		break;
261	case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */
262		if (mh_mode & CRYPTO_MEM_CHECK_ON) {
263			if (num_disable) /* always true, or something is going wrong */
264			{
265				num_disable--;
266				if (num_disable == 0) {
267					mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
268					CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
269				}
270			}
271		}
272		break;
273
274	default:
275		break;
276	}
277	CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
278	return (ret);
279}
280
281int
282CRYPTO_is_mem_check_on(void)
283{
284	int ret = 0;
285
286	if (mh_mode & CRYPTO_MEM_CHECK_ON) {
287		CRYPTO_THREADID cur;
288		CRYPTO_THREADID_current(&cur);
289		CRYPTO_r_lock(CRYPTO_LOCK_MALLOC);
290
291		ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE) ||
292		    CRYPTO_THREADID_cmp(&disabling_threadid, &cur);
293
294		CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC);
295	}
296	return (ret);
297}
298
299
300void
301CRYPTO_dbg_set_options(long bits)
302{
303	options = bits;
304}
305
306long
307CRYPTO_dbg_get_options(void)
308{
309	return options;
310}
311
312static int
313mem_cmp(const MEM *a, const MEM *b)
314{
315#ifdef _WIN64
316	const char *ap = (const char *)a->addr,
317	*bp = (const char *)b->addr;
318	if (ap == bp)
319		return 0;
320	else if (ap > bp)	return 1;
321		else		return -1;
322#else
323	return (const char *)a->addr - (const char *)b->addr;
324#endif
325}
326
327static IMPLEMENT_LHASH_COMP_FN(mem, MEM)
328
329static unsigned long
330mem_hash(const MEM *a)
331{
332	unsigned long ret;
333
334	ret = (unsigned long)a->addr;
335
336	ret = ret * 17851 + (ret >> 14) * 7 + (ret >> 4) * 251;
337	return (ret);
338}
339
340static
341IMPLEMENT_LHASH_HASH_FN(mem, MEM)
342
343/* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */
344static int
345app_info_cmp(const void *a_void, const void *b_void)
346{
347	return CRYPTO_THREADID_cmp(&((const APP_INFO *)a_void)->threadid,
348	    &((const APP_INFO *)b_void)->threadid);
349}
350
351static IMPLEMENT_LHASH_COMP_FN(app_info, APP_INFO)
352
353static unsigned long
354app_info_hash(const APP_INFO *a)
355{
356	unsigned long ret;
357
358	ret = CRYPTO_THREADID_hash(&a->threadid);
359	/* This is left in as a "who am I to question legacy?" measure */
360	ret = ret * 17851 + (ret >> 14) * 7 + (ret >> 4) * 251;
361	return (ret);
362}
363
364static IMPLEMENT_LHASH_HASH_FN(app_info, APP_INFO)
365
366static APP_INFO
367*pop_info(void)
368{
369	APP_INFO tmp;
370	APP_INFO *ret = NULL;
371
372	if (amih != NULL) {
373		CRYPTO_THREADID_current(&tmp.threadid);
374		if ((ret = lh_APP_INFO_delete(amih, &tmp)) != NULL) {
375			APP_INFO *next = ret->next;
376
377			if (next != NULL) {
378				next->references++;
379				(void)lh_APP_INFO_insert(amih, next);
380			}
381#ifdef LEVITTE_DEBUG_MEM
382			if (CRYPTO_THREADID_cmp(&ret->threadid, &tmp.threadid)) {
383				fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
384				CRYPTO_THREADID_hash(&ret->threadid),
385				CRYPTO_THREADID_hash(&tmp.threadid));
386				abort();
387			}
388#endif
389			if (--(ret->references) <= 0) {
390				ret->next = NULL;
391				if (next != NULL)
392					next->references--;
393				OPENSSL_free(ret);
394			}
395		}
396	}
397	return (ret);
398}
399
400int
401CRYPTO_push_info_(const char *info, const char *file, int line)
402{
403	APP_INFO *ami, *amim;
404	int ret = 0;
405
406	if (is_MemCheck_on()) {
407		MemCheck_off(); /* obtain MALLOC2 lock */
408
409		if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL) {
410			ret = 0;
411			goto err;
412		}
413		if (amih == NULL) {
414			if ((amih = lh_APP_INFO_new()) == NULL) {
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#ifdef LEVITTE_DEBUG_MEM
430			if (CRYPTO_THREADID_cmp(&ami->threadid, &amim->threadid)) {
431				fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
432				CRYPTO_THREADID_hash(&amim->threadid),
433				CRYPTO_THREADID_hash(&ami->threadid));
434				abort();
435			}
436#endif
437			ami->next = amim;
438		}
439		err:
440		MemCheck_on(); /* release MALLOC2 lock */
441	}
442
443	return (ret);
444}
445
446int
447CRYPTO_pop_info(void)
448{
449	int ret = 0;
450
451	if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */
452	{
453		MemCheck_off(); /* obtain MALLOC2 lock */
454
455		ret = (pop_info() != NULL);
456
457		MemCheck_on(); /* release MALLOC2 lock */
458	}
459	return (ret);
460}
461
462int
463CRYPTO_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
482CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
483    int before_p)
484{
485	MEM *m, *mm;
486	APP_INFO tmp, *amim;
487
488	switch (before_p & 127) {
489	case 0:
490		break;
491	case 1:
492		if (addr == NULL)
493			break;
494
495		if (is_MemCheck_on()) {
496			MemCheck_off(); /* make sure we hold MALLOC2 lock */
497			if ((m = (MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL) {
498				OPENSSL_free(addr);
499				MemCheck_on(); /* release MALLOC2 lock
500				                * if num_disabled drops to 0 */
501				return;
502			}
503			if (mh == NULL) {
504				if ((mh = lh_MEM_new()) == NULL) {
505					OPENSSL_free(addr);
506					OPENSSL_free(m);
507					addr = NULL;
508					goto err;
509				}
510			}
511
512			m->addr = addr;
513			m->file = file;
514			m->line = line;
515			m->num = num;
516			if (options & V_CRYPTO_MDEBUG_THREAD)
517				CRYPTO_THREADID_current(&m->threadid);
518			else
519				memset(&m->threadid, 0, sizeof(m->threadid));
520
521			if (order == break_order_num) {
522				/* BREAK HERE */
523				m->order = order;
524			}
525			m->order = order++;
526#ifdef LEVITTE_DEBUG_MEM
527			fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] %c 0x%p (%d)\n",
528			    m->order,
529			    (before_p & 128) ? '*' : '+',
530			    m->addr, m->num);
531#endif
532			if (options & V_CRYPTO_MDEBUG_TIME)
533				m->time = time(NULL);
534			else
535				m->time = 0;
536
537			CRYPTO_THREADID_current(&tmp.threadid);
538			m->app_info = NULL;
539			if (amih != NULL &&
540			    (amim = lh_APP_INFO_retrieve(amih, &tmp)) != NULL) {
541				m->app_info = amim;
542				amim->references++;
543			}
544
545			if ((mm = lh_MEM_insert(mh, m)) != NULL) {
546				/* Not good, but don't sweat it */
547				if (mm->app_info != NULL) {
548					mm->app_info->references--;
549				}
550				OPENSSL_free(mm);
551			}
552err:
553			MemCheck_on(); /* release MALLOC2 lock
554			                * if num_disabled drops to 0 */
555		}
556		break;
557	}
558	return;
559}
560
561void
562CRYPTO_dbg_free(void *addr, int before_p)
563{
564	MEM m, *mp;
565
566	switch (before_p) {
567	case 0:
568		if (addr == NULL)
569			break;
570
571		if (is_MemCheck_on() && (mh != NULL)) {
572			MemCheck_off(); /* make sure we hold MALLOC2 lock */
573
574			m.addr = addr;
575			mp = lh_MEM_delete(mh, &m);
576			if (mp != NULL) {
577#ifdef LEVITTE_DEBUG_MEM
578				fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] - 0x%p (%d)\n",
579				mp->order, mp->addr, mp->num);
580#endif
581				if (mp->app_info != NULL)
582					app_info_free(mp->app_info);
583				OPENSSL_free(mp);
584			}
585
586			MemCheck_on(); /* release MALLOC2 lock
587			                * if num_disabled drops to 0 */
588		}
589		break;
590	case 1:
591		break;
592	}
593}
594
595void
596CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
597    const char *file, int line, int before_p)
598{
599	MEM m, *mp;
600
601#ifdef LEVITTE_DEBUG_MEM
602	fprintf(stderr, "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n",
603	addr1, addr2, num, file, line, before_p);
604#endif
605
606	switch (before_p) {
607	case 0:
608		break;
609	case 1:
610		if (addr2 == NULL)
611			break;
612
613		if (addr1 == NULL) {
614			CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p);
615			break;
616		}
617
618		if (is_MemCheck_on()) {
619			MemCheck_off(); /* make sure we hold MALLOC2 lock */
620
621			m.addr = addr1;
622			mp = lh_MEM_delete(mh, &m);
623			if (mp != NULL) {
624#ifdef LEVITTE_DEBUG_MEM
625				fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] * 0x%p (%d) -> 0x%p (%d)\n",
626				    mp->order,
627				    mp->addr, mp->num,
628				    addr2, num);
629#endif
630				mp->addr = addr2;
631				mp->num = num;
632				(void)lh_MEM_insert(mh, mp);
633			}
634
635			MemCheck_on(); /* release MALLOC2 lock
636			                * if num_disabled drops to 0 */
637		}
638		break;
639	}
640	return;
641}
642
643
644typedef struct mem_leak_st {
645	BIO *bio;
646	int chunks;
647	long bytes;
648} MEM_LEAK;
649
650static void
651print_leak_doall_arg(const MEM *m, MEM_LEAK *l)
652{
653	char buf[1024];
654	char *bufp = buf;
655	APP_INFO *amip;
656	int ami_cnt;
657	struct tm *lcl = NULL;
658	CRYPTO_THREADID ti;
659
660#define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf))
661
662	if (m->addr == (char *)l->bio)
663		return;
664
665	if (options & V_CRYPTO_MDEBUG_TIME) {
666		lcl = localtime(&m->time);
667
668		BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ",
669		lcl->tm_hour, lcl->tm_min, lcl->tm_sec);
670		bufp += strlen(bufp);
671	}
672
673	BIO_snprintf(bufp, BUF_REMAIN, "%5lu file=%s, line=%d, ",
674	m->order, m->file, m->line);
675	bufp += strlen(bufp);
676
677	if (options & V_CRYPTO_MDEBUG_THREAD) {
678		BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ",
679		CRYPTO_THREADID_hash(&m->threadid));
680		bufp += strlen(bufp);
681	}
682
683	BIO_snprintf(bufp, BUF_REMAIN, "number=%d, address=%08lX\n",
684	m->num,(unsigned long)m->addr);
685	bufp += strlen(bufp);
686
687	BIO_puts(l->bio, buf);
688
689	l->chunks++;
690	l->bytes += m->num;
691
692	amip = m->app_info;
693	ami_cnt = 0;
694	if (!amip)
695		return;
696	CRYPTO_THREADID_cpy(&ti, &amip->threadid);
697
698	do {
699		int buf_len;
700		int info_len;
701
702		ami_cnt++;
703		memset(buf, '>', ami_cnt);
704		BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt,
705		" thread=%lu, file=%s, line=%d, info=\"",
706		CRYPTO_THREADID_hash(&amip->threadid), amip->file,
707		amip->line);
708		buf_len = strlen(buf);
709		info_len = strlen(amip->info);
710		if (128 - buf_len - 3 < info_len) {
711			memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
712			buf_len = 128 - 3;
713		} else {
714			BUF_strlcpy(buf + buf_len, amip->info,
715			sizeof buf - buf_len);
716			buf_len = strlen(buf);
717		}
718		BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n");
719
720		BIO_puts(l->bio, buf);
721
722		amip = amip->next;
723	} while (amip && !CRYPTO_THREADID_cmp(&amip->threadid, &ti));
724
725#ifdef LEVITTE_DEBUG_MEM
726	if (amip) {
727		fprintf(stderr, "Thread switch detected in backtrace!!!!\n");
728		abort();
729	}
730#endif
731}
732
733static
734IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM, MEM_LEAK)
735
736void
737CRYPTO_mem_leaks(BIO *b)
738{
739	MEM_LEAK ml;
740
741	if (mh == NULL && amih == NULL)
742		return;
743
744	MemCheck_off(); /* obtain MALLOC2 lock */
745
746	ml.bio = b;
747	ml.bytes = 0;
748	ml.chunks = 0;
749	if (mh != NULL)
750		lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak),
751		    MEM_LEAK, &ml);
752	if (ml.chunks != 0) {
753		BIO_printf(b, "%ld bytes leaked in %d chunks\n",
754		ml.bytes, ml.chunks);
755#ifdef CRYPTO_MDEBUG_ABORT
756		abort();
757#endif
758	} else {
759		/* Make sure that, if we found no leaks, memory-leak debugging itself
760		 * does not introduce memory leaks (which might irritate
761		 * external debugging tools).
762		 * (When someone enables leak checking, but does not call
763		 * this function, we declare it to be their fault.)
764		 *
765		 * XXX    This should be in CRYPTO_mem_leaks_cb,
766		 * and CRYPTO_mem_leaks should be implemented by
767		 * using CRYPTO_mem_leaks_cb.
768		 * (Also there should be a variant of lh_doall_arg
769		 * that takes a function pointer instead of a void *;
770		 * this would obviate the ugly and illegal
771		 * void_fn_to_char kludge in CRYPTO_mem_leaks_cb.
772		 * Otherwise the code police will come and get us.)
773		 */
774		int old_mh_mode;
775
776		CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
777
778		/* avoid deadlock when lh_free() uses CRYPTO_dbg_free(),
779		 * which uses CRYPTO_is_mem_check_on */
780		old_mh_mode = mh_mode;
781		mh_mode = CRYPTO_MEM_CHECK_OFF;
782
783		if (mh != NULL) {
784			lh_MEM_free(mh);
785			mh = NULL;
786		}
787		if (amih != NULL) {
788			if (lh_APP_INFO_num_items(amih) == 0) {
789				lh_APP_INFO_free(amih);
790				amih = NULL;
791			}
792		}
793
794		mh_mode = old_mh_mode;
795		CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
796	}
797	MemCheck_on(); /* release MALLOC2 lock */
798}
799
800#ifndef OPENSSL_NO_FP_API
801void
802CRYPTO_mem_leaks_fp(FILE *fp)
803{
804	BIO *b;
805
806	if (mh == NULL)
807		return;
808	/* Need to turn off memory checking when allocated BIOs ... especially
809	 * as we're creating them at a time when we're trying to check we've not
810	 * left anything un-free()'d!! */
811	MemCheck_off();
812	b = BIO_new(BIO_s_file());
813	MemCheck_on();
814	if (!b)
815		return;
816	BIO_set_fp(b, fp, BIO_NOCLOSE);
817	CRYPTO_mem_leaks(b);
818	BIO_free(b);
819}
820#endif
821
822
823
824/* FIXME: We really don't allow much to the callback.  For example, it has
825   no chance of reaching the info stack for the item it processes.  Should
826   it really be this way?  -- Richard Levitte */
827/* NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside crypto.h
828 * If this code is restructured, remove the callback type if it is no longer
829 * needed. -- Geoff Thorpe */
830
831/* Can't pass CRYPTO_MEM_LEAK_CB directly to lh_MEM_doall_arg because it
832 * is a function pointer and conversion to void * is prohibited. Instead
833 * pass its address
834 */
835
836typedef CRYPTO_MEM_LEAK_CB *PCRYPTO_MEM_LEAK_CB;
837
838static void
839cb_leak_doall_arg(const MEM *m, PCRYPTO_MEM_LEAK_CB *cb)
840{
841	(*cb)(m->order, m->file, m->line, m->num, m->addr);
842}
843
844static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM, PCRYPTO_MEM_LEAK_CB)
845
846void
847CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
848{
849	if (mh == NULL)
850		return;
851	CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
852	lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), PCRYPTO_MEM_LEAK_CB,
853	&cb);
854	CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
855}
856