xref: /onnv-gate/usr/src/common/openssl/crypto/mem_dbg.c (revision 2139:6243c3338933)
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 
68 static 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 
83 static unsigned long order = 0; /* number of memory requests */
84 static LHASH *mh=NULL; /* hash-table of memory requests (address as key);
85                         * access requires MALLOC2 lock */
86 
87 
88 typedef 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 
105 static void app_info_free(APP_INFO *);
106 
107 static 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 
112 typedef 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 
125 static 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 
135 static unsigned int num_disable = 0; /* num_disable > 0
136                                       *     iff
137                                       * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE)
138                                       */
139 static 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 
app_info_free(APP_INFO * inf)145 static 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 
CRYPTO_mem_ctrl(int mode)157 int 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 
CRYPTO_is_mem_check_on(void)225 int 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 
CRYPTO_dbg_set_options(long bits)242 void CRYPTO_dbg_set_options(long bits)
243 	{
244 	options = bits;
245 	}
246 
CRYPTO_dbg_get_options(void)247 long CRYPTO_dbg_get_options(void)
248 	{
249 	return options;
250 	}
251 
252 /* static int mem_cmp(MEM *a, MEM *b) */
mem_cmp(const void * a_void,const void * b_void)253 static 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) */
mem_hash(const void * a_void)268 static 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) */
app_info_cmp(const void * a_void,const void * b_void)279 static 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) */
app_info_hash(const void * a_void)286 static 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 
pop_info(void)296 static 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 
CRYPTO_push_info_(const char * info,const char * file,int line)333 int 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 
CRYPTO_pop_info(void)383 int 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 
CRYPTO_remove_all_info(void)398 int 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 
415 static unsigned long break_order_num=0;
CRYPTO_dbg_malloc(void * addr,int num,const char * file,int line,int before_p)416 void 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 
CRYPTO_dbg_free(void * addr,int before_p)504 void 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 
CRYPTO_dbg_realloc(void * addr1,void * addr2,int num,const char * file,int line,int before_p)540 void 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 
592 typedef struct mem_leak_st
593 	{
594 	BIO *bio;
595 	int chunks;
596 	long bytes;
597 	} MEM_LEAK;
598 
print_leak(const MEM * m,MEM_LEAK * l)599 static 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 
IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak,const MEM *,MEM_LEAK *)687 static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM *, MEM_LEAK *)
688 
689 void 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
CRYPTO_mem_leaks_fp(FILE * fp)756 void 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 */
cb_leak(const MEM * m,CRYPTO_MEM_LEAK_CB ** cb)782 static 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 
IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak,const MEM *,CRYPTO_MEM_LEAK_CB **)787 static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM *, CRYPTO_MEM_LEAK_CB **)
788 
789 void 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