Update build for OpenSSL-1.0.0a.
[dragonfly.git] / crypto / openssl / crypto / mem_dbg.c
CommitLineData
56276539
SS
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 */
919b01cc
PA
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 */
56276539
SS
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 */
919b01cc
PA
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 */
56276539
SS
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 */
919b01cc
PA
152 {
153 CRYPTO_THREADID threadid;
56276539
SS
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
919b01cc
PA
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 */
56276539
SS
170
171typedef struct mem_st
172/* memory-block description */
173 {
174 void *addr;
175 int num;
176 const char *file;
177 int line;
919b01cc 178 CRYPTO_THREADID threadid;
56276539
SS
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 */
919b01cc
PA
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;
56276539
SS
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 {
919b01cc
PA
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 */
56276539
SS
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;
919b01cc 259 CRYPTO_THREADID_cpy(&disabling_threadid, &cur);
56276539
SS
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 {
919b01cc
PA
292 CRYPTO_THREADID cur;
293 CRYPTO_THREADID_current(&cur);
56276539
SS
294 CRYPTO_r_lock(CRYPTO_LOCK_MALLOC);
295
296 ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
919b01cc 297 || CRYPTO_THREADID_cmp(&disabling_threadid, &cur);
56276539
SS
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
919b01cc 315static int mem_cmp(const MEM *a, const MEM *b)
56276539
SS
316 {
317#ifdef _WIN64
919b01cc
PA
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;
56276539
SS
322 else return -1;
323#else
919b01cc 324 return (const char *)a->addr - (const char *)b->addr;
56276539
SS
325#endif
326 }
919b01cc 327static IMPLEMENT_LHASH_COMP_FN(mem, MEM)
56276539 328
919b01cc 329static unsigned long mem_hash(const MEM *a)
56276539
SS
330 {
331 unsigned long ret;
332
919b01cc 333 ret=(unsigned long)a->addr;
56276539
SS
334
335 ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
336 return(ret);
337 }
919b01cc 338static IMPLEMENT_LHASH_HASH_FN(mem, MEM)
56276539
SS
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 {
919b01cc
PA
343 return CRYPTO_THREADID_cmp(&((const APP_INFO *)a_void)->threadid,
344 &((const APP_INFO *)b_void)->threadid);
56276539 345 }
919b01cc 346static IMPLEMENT_LHASH_COMP_FN(app_info, APP_INFO)
56276539 347
919b01cc 348static unsigned long app_info_hash(const APP_INFO *a)
56276539
SS
349 {
350 unsigned long ret;
351
919b01cc
PA
352 ret = CRYPTO_THREADID_hash(&a->threadid);
353 /* This is left in as a "who am I to question legacy?" measure */
56276539
SS
354 ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
355 return(ret);
356 }
919b01cc 357static IMPLEMENT_LHASH_HASH_FN(app_info, APP_INFO)
56276539
SS
358
359static APP_INFO *pop_info(void)
360 {
361 APP_INFO tmp;
362 APP_INFO *ret = NULL;
363
364 if (amih != NULL)
365 {
919b01cc
PA
366 CRYPTO_THREADID_current(&tmp.threadid);
367 if ((ret=lh_APP_INFO_delete(amih,&tmp)) != NULL)
56276539
SS
368 {
369 APP_INFO *next=ret->next;
370
371 if (next != NULL)
372 {
373 next->references++;
919b01cc 374 (void)lh_APP_INFO_insert(amih,next);
56276539
SS
375 }
376#ifdef LEVITTE_DEBUG_MEM
919b01cc 377 if (CRYPTO_THREADID_cmp(&ret->threadid, &tmp.threadid))
56276539
SS
378 {
379 fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
919b01cc
PA
380 CRYPTO_THREADID_hash(&ret->threadid),
381 CRYPTO_THREADID_hash(&tmp.threadid));
56276539
SS
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
919b01cc 397int CRYPTO_push_info_(const char *info, const char *file, int line)
56276539
SS
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 {
919b01cc 413 if ((amih=lh_APP_INFO_new()) == NULL)
56276539
SS
414 {
415 OPENSSL_free(ami);
416 ret=0;
417 goto err;
418 }
419 }
420
919b01cc 421 CRYPTO_THREADID_current(&ami->threadid);
56276539
SS
422 ami->file=file;
423 ami->line=line;
424 ami->info=info;
425 ami->references=1;
426 ami->next=NULL;
427
919b01cc 428 if ((amim=lh_APP_INFO_insert(amih,ami)) != NULL)
56276539
SS
429 {
430#ifdef LEVITTE_DEBUG_MEM
919b01cc 431 if (CRYPTO_THREADID_cmp(&ami->threadid, &amim->threadid))
56276539
SS
432 {
433 fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
919b01cc
PA
434 CRYPTO_THREADID_hash(&amim->threadid),
435 CRYPTO_THREADID_hash(&ami->threadid));
56276539
SS
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
919b01cc 448int CRYPTO_pop_info(void)
56276539
SS
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
919b01cc 463int CRYPTO_remove_all_info(void)
56276539
SS
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 {
919b01cc 507 if ((mh=lh_MEM_new()) == NULL)
56276539
SS
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)
919b01cc 521 CRYPTO_THREADID_current(&m->threadid);
56276539 522 else
919b01cc 523 memset(&m->threadid, 0, sizeof(m->threadid));
56276539
SS
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
919b01cc 532 fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] %c 0x%p (%d)\n",
56276539
SS
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
919b01cc 542 CRYPTO_THREADID_current(&tmp.threadid);
56276539
SS
543 m->app_info=NULL;
544 if (amih != NULL
919b01cc 545 && (amim=lh_APP_INFO_retrieve(amih,&tmp)) != NULL)
56276539
SS
546 {
547 m->app_info = amim;
548 amim->references++;
549 }
550
919b01cc 551 if ((mm=lh_MEM_insert(mh, m)) != NULL)
56276539
SS
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;
919b01cc 584 mp=lh_MEM_delete(mh,&m);
56276539
SS
585 if (mp != NULL)
586 {
587#ifdef LEVITTE_DEBUG_MEM
919b01cc 588 fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] - 0x%p (%d)\n",
56276539
SS
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;
919b01cc 634 mp=lh_MEM_delete(mh,&m);
56276539
SS
635 if (mp != NULL)
636 {
637#ifdef LEVITTE_DEBUG_MEM
919b01cc 638 fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5ld] * 0x%p (%d) -> 0x%p (%d)\n",
56276539
SS
639 mp->order,
640 mp->addr, mp->num,
641 addr2, num);
642#endif
643 mp->addr=addr2;
644 mp->num=num;
919b01cc 645 (void)lh_MEM_insert(mh,mp);
56276539
SS
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
919b01cc 664static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l)
56276539
SS
665 {
666 char buf[1024];
667 char *bufp = buf;
668 APP_INFO *amip;
669 int ami_cnt;
670 struct tm *lcl = NULL;
919b01cc 671 CRYPTO_THREADID ti;
56276539
SS
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 {
919b01cc
PA
693 BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ",
694 CRYPTO_THREADID_hash(&m->threadid));
56276539
SS
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;
919b01cc
PA
711 CRYPTO_THREADID_cpy(&ti, &amip->threadid);
712
56276539
SS
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=\"",
919b01cc
PA
722 CRYPTO_THREADID_hash(&amip->threadid), amip->file,
723 amip->line);
56276539
SS
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 }
919b01cc
PA
743 while(amip && !CRYPTO_THREADID_cmp(&amip->threadid, &ti));
744
56276539
SS
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
919b01cc 754static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM, MEM_LEAK)
56276539
SS
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)
919b01cc
PA
769 lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak), MEM_LEAK,
770 &ml);
56276539
SS
771 if (ml.chunks != 0)
772 {
773 BIO_printf(b,"%ld bytes leaked in %d chunks\n",
774 ml.bytes,ml.chunks);
919b01cc
PA
775#ifdef CRYPTO_MDEBUG_ABORT
776 abort();
777#endif
56276539
SS
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.
919b01cc 790 * (Also there should be a variant of lh_doall_arg
56276539
SS
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 {
919b01cc 807 lh_MEM_free(mh);
56276539
SS
808 mh = NULL;
809 }
810 if (amih != NULL)
811 {
919b01cc 812 if (lh_APP_INFO_num_items(amih) == 0)
56276539 813 {
919b01cc 814 lh_APP_INFO_free(amih);
56276539
SS
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 */
919b01cc
PA
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)
56276539 861 {
919b01cc 862 (*cb)(m->order,m->file,m->line,m->num,m->addr);
56276539
SS
863 }
864
919b01cc 865static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM, PCRYPTO_MEM_LEAK_CB)
56276539
SS
866
867void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
868 {
869 if (mh == NULL) return;
870 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
919b01cc
PA
871 lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), PCRYPTO_MEM_LEAK_CB,
872 &cb);
56276539
SS
873 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
874 }