summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbeck <>2014-04-16 14:31:03 +0000
committerbeck <>2014-04-16 14:31:03 +0000
commit10dfdaaf3324c4eccc97564cc84c12408a7b659b (patch)
treefbb3a72187001acbb3491b15b92eeaeb8e8e46f6 /src
parent9d01b22113829c89fb59915fd5789b1f902ba5a0 (diff)
downloadopenbsd-10dfdaaf3324c4eccc97564cc84c12408a7b659b.tar.gz
openbsd-10dfdaaf3324c4eccc97564cc84c12408a7b659b.tar.bz2
openbsd-10dfdaaf3324c4eccc97564cc84c12408a7b659b.zip
Make this byzantine horror a shell of it's former self by stubbing the
functions. The ability to set the debug mem functions died with mem.c, but some of the rest of this is still exposed API so we can't delete it.. yet... ok tedu@
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/mem_dbg.c677
-rw-r--r--src/lib/libssl/src/crypto/mem_dbg.c677
2 files changed, 34 insertions, 1320 deletions
diff --git a/src/lib/libcrypto/mem_dbg.c b/src/lib/libcrypto/mem_dbg.c
index 944c3d9a61..693b47bced 100644
--- a/src/lib/libcrypto/mem_dbg.c
+++ b/src/lib/libcrypto/mem_dbg.c
@@ -111,7 +111,7 @@
111 111
112#include <stdio.h> 112#include <stdio.h>
113#include <stdlib.h> 113#include <stdlib.h>
114#include <time.h> 114#include <time.h>
115#include "cryptlib.h" 115#include "cryptlib.h"
116#include <openssl/crypto.h> 116#include <openssl/crypto.h>
117#include <openssl/buffer.h> 117#include <openssl/buffer.h>
@@ -119,361 +119,48 @@
119#include <openssl/lhash.h> 119#include <openssl/lhash.h>
120 120
121static int mh_mode = CRYPTO_MEM_CHECK_OFF; 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 122
214int 123int
215CRYPTO_mem_ctrl(int mode) 124CRYPTO_mem_ctrl(int mode)
216{ 125{
217 int ret = mh_mode; 126 return (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} 127}
280 128
281int 129int
282CRYPTO_is_mem_check_on(void) 130CRYPTO_is_mem_check_on(void)
283{ 131{
284 int ret = 0; 132 return(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} 133}
298 134
299 135
300void 136void
301CRYPTO_dbg_set_options(long bits) 137CRYPTO_dbg_set_options(long bits)
302{ 138{
303 options = bits; 139 return;
304} 140}
305 141
306long 142long
307CRYPTO_dbg_get_options(void) 143CRYPTO_dbg_get_options(void)
308{ 144{
309 return options; 145 return(0);
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} 146}
399 147
400int 148int
401CRYPTO_push_info_(const char *info, const char *file, int line) 149CRYPTO_push_info_(const char *info, const char *file, int line)
402{ 150{
403 APP_INFO *ami, *amim; 151 return(0);
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} 152}
445 153
446int 154int
447CRYPTO_pop_info(void) 155CRYPTO_pop_info(void)
448{ 156{
449 int ret = 0; 157 return(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} 158}
461 159
462int 160int
463CRYPTO_remove_all_info(void) 161CRYPTO_remove_all_info(void)
464{ 162{
465 int ret = 0; 163 return(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} 164}
478 165
479 166
@@ -482,374 +169,44 @@ void
482CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line, 169CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
483 int before_p) 170 int before_p)
484{ 171{
485 MEM *m, *mm; 172 fprintf(stderr, "this is a bad idea");
486 APP_INFO tmp, *amim; 173 abort();
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} 174}
560 175
561void 176void
562CRYPTO_dbg_free(void *addr, int before_p) 177CRYPTO_dbg_free(void *addr, int before_p)
563{ 178{
564 MEM m, *mp; 179 fprintf(stderr, "this is a bad idea");
565 180 abort();
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} 181}
594 182
595void 183void
596CRYPTO_dbg_realloc(void *addr1, void *addr2, int num, 184CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
597 const char *file, int line, int before_p) 185 const char *file, int line, int before_p)
598{ 186{
599 MEM m, *mp; 187 fprintf(stderr, "this is a bad idea");
600 188 abort();
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} 189}
642 190
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 (void) snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ",
669 lcl->tm_hour, lcl->tm_min, lcl->tm_sec);
670 bufp += strlen(bufp);
671 }
672
673 (void) 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 (void) snprintf(bufp, BUF_REMAIN, "thread=%lu, ",
679 CRYPTO_THREADID_hash(&m->threadid));
680 bufp += strlen(bufp);
681 }
682
683 (void) 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 (void) 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 (void) 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 191void
737CRYPTO_mem_leaks(BIO *b) 192CRYPTO_mem_leaks(BIO *b)
738{ 193{
739 MEM_LEAK ml; 194 return;
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} 195}
799 196
800#ifndef OPENSSL_NO_FP_API 197#ifndef OPENSSL_NO_FP_API
801void 198void
802CRYPTO_mem_leaks_fp(FILE *fp) 199CRYPTO_mem_leaks_fp(FILE *fp)
803{ 200{
804 BIO *b; 201 return;
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} 202}
820#endif 203#endif
821 204
822 205
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; 206typedef CRYPTO_MEM_LEAK_CB *PCRYPTO_MEM_LEAK_CB;
837 207
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 208void
847CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb) 209CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
848{ 210{
849 if (mh == NULL) 211 return;
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} 212}
diff --git a/src/lib/libssl/src/crypto/mem_dbg.c b/src/lib/libssl/src/crypto/mem_dbg.c
index 944c3d9a61..693b47bced 100644
--- a/src/lib/libssl/src/crypto/mem_dbg.c
+++ b/src/lib/libssl/src/crypto/mem_dbg.c
@@ -111,7 +111,7 @@
111 111
112#include <stdio.h> 112#include <stdio.h>
113#include <stdlib.h> 113#include <stdlib.h>
114#include <time.h> 114#include <time.h>
115#include "cryptlib.h" 115#include "cryptlib.h"
116#include <openssl/crypto.h> 116#include <openssl/crypto.h>
117#include <openssl/buffer.h> 117#include <openssl/buffer.h>
@@ -119,361 +119,48 @@
119#include <openssl/lhash.h> 119#include <openssl/lhash.h>
120 120
121static int mh_mode = CRYPTO_MEM_CHECK_OFF; 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 122
214int 123int
215CRYPTO_mem_ctrl(int mode) 124CRYPTO_mem_ctrl(int mode)
216{ 125{
217 int ret = mh_mode; 126 return (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} 127}
280 128
281int 129int
282CRYPTO_is_mem_check_on(void) 130CRYPTO_is_mem_check_on(void)
283{ 131{
284 int ret = 0; 132 return(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} 133}
298 134
299 135
300void 136void
301CRYPTO_dbg_set_options(long bits) 137CRYPTO_dbg_set_options(long bits)
302{ 138{
303 options = bits; 139 return;
304} 140}
305 141
306long 142long
307CRYPTO_dbg_get_options(void) 143CRYPTO_dbg_get_options(void)
308{ 144{
309 return options; 145 return(0);
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} 146}
399 147
400int 148int
401CRYPTO_push_info_(const char *info, const char *file, int line) 149CRYPTO_push_info_(const char *info, const char *file, int line)
402{ 150{
403 APP_INFO *ami, *amim; 151 return(0);
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} 152}
445 153
446int 154int
447CRYPTO_pop_info(void) 155CRYPTO_pop_info(void)
448{ 156{
449 int ret = 0; 157 return(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} 158}
461 159
462int 160int
463CRYPTO_remove_all_info(void) 161CRYPTO_remove_all_info(void)
464{ 162{
465 int ret = 0; 163 return(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} 164}
478 165
479 166
@@ -482,374 +169,44 @@ void
482CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line, 169CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
483 int before_p) 170 int before_p)
484{ 171{
485 MEM *m, *mm; 172 fprintf(stderr, "this is a bad idea");
486 APP_INFO tmp, *amim; 173 abort();
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} 174}
560 175
561void 176void
562CRYPTO_dbg_free(void *addr, int before_p) 177CRYPTO_dbg_free(void *addr, int before_p)
563{ 178{
564 MEM m, *mp; 179 fprintf(stderr, "this is a bad idea");
565 180 abort();
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} 181}
594 182
595void 183void
596CRYPTO_dbg_realloc(void *addr1, void *addr2, int num, 184CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
597 const char *file, int line, int before_p) 185 const char *file, int line, int before_p)
598{ 186{
599 MEM m, *mp; 187 fprintf(stderr, "this is a bad idea");
600 188 abort();
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} 189}
642 190
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 (void) snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ",
669 lcl->tm_hour, lcl->tm_min, lcl->tm_sec);
670 bufp += strlen(bufp);
671 }
672
673 (void) 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 (void) snprintf(bufp, BUF_REMAIN, "thread=%lu, ",
679 CRYPTO_THREADID_hash(&m->threadid));
680 bufp += strlen(bufp);
681 }
682
683 (void) 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 (void) 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 (void) 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 191void
737CRYPTO_mem_leaks(BIO *b) 192CRYPTO_mem_leaks(BIO *b)
738{ 193{
739 MEM_LEAK ml; 194 return;
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} 195}
799 196
800#ifndef OPENSSL_NO_FP_API 197#ifndef OPENSSL_NO_FP_API
801void 198void
802CRYPTO_mem_leaks_fp(FILE *fp) 199CRYPTO_mem_leaks_fp(FILE *fp)
803{ 200{
804 BIO *b; 201 return;
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} 202}
820#endif 203#endif
821 204
822 205
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; 206typedef CRYPTO_MEM_LEAK_CB *PCRYPTO_MEM_LEAK_CB;
837 207
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 208void
847CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb) 209CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
848{ 210{
849 if (mh == NULL) 211 return;
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} 212}