summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/mem_dbg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/mem_dbg.c')
-rw-r--r--src/lib/libcrypto/mem_dbg.c730
1 files changed, 0 insertions, 730 deletions
diff --git a/src/lib/libcrypto/mem_dbg.c b/src/lib/libcrypto/mem_dbg.c
deleted file mode 100644
index 866c53e73a..0000000000
--- a/src/lib/libcrypto/mem_dbg.c
+++ /dev/null
@@ -1,730 +0,0 @@
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 <openssl/crypto.h>
63#include <openssl/buffer.h>
64#include <openssl/bio.h>
65#include <openssl/lhash.h>
66#include "cryptlib.h"
67
68static 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
83static unsigned long order = 0; /* number of memory requests */
84static LHASH *mh=NULL; /* hash-table of memory requests (address as key) */
85
86
87typedef struct app_mem_info_st
88/* For application-defined information (static C-string `info')
89 * to be displayed in memory leak list.
90 * Each thread has its own stack. For applications, there is
91 * CRYPTO_push_info("...") to push an entry,
92 * CRYPTO_pop_info() to pop an entry,
93 * CRYPTO_remove_all_info() to pop all entries.
94 */
95 {
96 unsigned long thread;
97 const char *file;
98 int line;
99 const char *info;
100 struct app_mem_info_st *next; /* tail of thread's stack */
101 int references;
102 } APP_INFO;
103
104static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's
105 * that are at the top of their thread's stack
106 * (with `thread' as key) */
107
108typedef struct mem_st
109/* memory-block description */
110 {
111 void *addr;
112 int num;
113 const char *file;
114 int line;
115 unsigned long thread;
116 unsigned long order;
117 time_t time;
118 APP_INFO *app_info;
119 } MEM;
120
121static long options = /* extra information to be recorded */
122#if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL)
123 V_CRYPTO_MDEBUG_TIME |
124#endif
125#if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL)
126 V_CRYPTO_MDEBUG_THREAD |
127#endif
128 0;
129
130
131static unsigned long disabling_thread = 0;
132
133int CRYPTO_mem_ctrl(int mode)
134 {
135 int ret=mh_mode;
136
137 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
138 switch (mode)
139 {
140 /* for applications: */
141 case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */
142 mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
143 disabling_thread = 0;
144 break;
145 case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
146 mh_mode = 0;
147 disabling_thread = 0;
148 break;
149
150 /* switch off temporarily (for library-internal use): */
151 case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
152 if (mh_mode & CRYPTO_MEM_CHECK_ON)
153 {
154 mh_mode&= ~CRYPTO_MEM_CHECK_ENABLE;
155 if (disabling_thread != CRYPTO_thread_id()) /* otherwise we already have the MALLOC2 lock */
156 {
157 /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while
158 * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if
159 * somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot release
160 * it because we block entry to this function).
161 * Give them a chance, first, and then claim the locks in
162 * appropriate order (long-time lock first).
163 */
164 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
165 /* Note that after we have waited for CRYPTO_LOCK_MALLOC2
166 * and CRYPTO_LOCK_MALLOC, we'll still be in the right
167 * "case" and "if" branch because MemCheck_start and
168 * MemCheck_stop may never be used while there are multiple
169 * OpenSSL threads. */
170 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
171 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
172 disabling_thread=CRYPTO_thread_id();
173 }
174 }
175 break;
176 case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */
177 if (mh_mode & CRYPTO_MEM_CHECK_ON)
178 {
179 mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
180 if (disabling_thread != 0)
181 {
182 disabling_thread=0;
183 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
184 }
185 }
186 break;
187
188 default:
189 break;
190 }
191 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
192 return(ret);
193 }
194
195int CRYPTO_is_mem_check_on(void)
196 {
197 int ret = 0;
198
199 if (mh_mode & CRYPTO_MEM_CHECK_ON)
200 {
201 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
202
203 ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
204 && disabling_thread != CRYPTO_thread_id();
205
206 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
207 }
208 return(ret);
209 }
210
211
212void CRYPTO_dbg_set_options(long bits)
213 {
214 options = bits;
215 }
216
217long CRYPTO_dbg_get_options(void)
218 {
219 return options;
220 }
221
222static int mem_cmp(MEM *a, MEM *b)
223 {
224 return((char *)a->addr - (char *)b->addr);
225 }
226
227static unsigned long mem_hash(MEM *a)
228 {
229 unsigned long ret;
230
231 ret=(unsigned long)a->addr;
232
233 ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
234 return(ret);
235 }
236
237static int app_info_cmp(APP_INFO *a, APP_INFO *b)
238 {
239 return(a->thread != b->thread);
240 }
241
242static unsigned long app_info_hash(APP_INFO *a)
243 {
244 unsigned long ret;
245
246 ret=(unsigned long)a->thread;
247
248 ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
249 return(ret);
250 }
251
252static APP_INFO *pop_info()
253 {
254 APP_INFO tmp;
255 APP_INFO *ret = NULL;
256
257 if (amih != NULL)
258 {
259 tmp.thread=CRYPTO_thread_id();
260 if ((ret=(APP_INFO *)lh_delete(amih,&tmp)) != NULL)
261 {
262 APP_INFO *next=ret->next;
263
264 if (next != NULL)
265 {
266 next->references++;
267 lh_insert(amih,(char *)next);
268 }
269#ifdef LEVITTE_DEBUG
270 if (ret->thread != tmp.thread)
271 {
272 fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
273 ret->thread, tmp.thread);
274 abort();
275 }
276#endif
277 if (--(ret->references) <= 0)
278 {
279 ret->next = NULL;
280 if (next != NULL)
281 next->references--;
282 OPENSSL_free(ret);
283 }
284 }
285 }
286 return(ret);
287 }
288
289int CRYPTO_push_info_(const char *info, const char *file, int line)
290 {
291 APP_INFO *ami, *amim;
292 int ret=0;
293
294 if (is_MemCheck_on())
295 {
296 MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */
297
298 if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL)
299 {
300 ret=0;
301 goto err;
302 }
303 if (amih == NULL)
304 {
305 if ((amih=lh_new(app_info_hash,app_info_cmp)) == NULL)
306 {
307 OPENSSL_free(ami);
308 ret=0;
309 goto err;
310 }
311 }
312
313 ami->thread=CRYPTO_thread_id();
314 ami->file=file;
315 ami->line=line;
316 ami->info=info;
317 ami->references=1;
318 ami->next=NULL;
319
320 if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL)
321 {
322#ifdef LEVITTE_DEBUG
323 if (ami->thread != amim->thread)
324 {
325 fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
326 amim->thread, ami->thread);
327 abort();
328 }
329#endif
330 ami->next=amim;
331 }
332 err:
333 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
334 }
335
336 return(ret);
337 }
338
339int CRYPTO_pop_info(void)
340 {
341 int ret=0;
342
343 if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */
344 {
345 MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */
346
347 ret=(pop_info() != NULL);
348
349 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
350 }
351 return(ret);
352 }
353
354int CRYPTO_remove_all_info(void)
355 {
356 int ret=0;
357
358 if (is_MemCheck_on()) /* _must_ be true */
359 {
360 MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */
361
362 while(pop_info() != NULL)
363 ret++;
364
365 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
366 }
367 return(ret);
368 }
369
370
371static unsigned long break_order_num=0;
372void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
373 int before_p)
374 {
375 MEM *m,*mm;
376 APP_INFO tmp,*amim;
377
378 switch(before_p & 127)
379 {
380 case 0:
381 break;
382 case 1:
383 if (addr == NULL)
384 break;
385
386 if (is_MemCheck_on())
387 {
388 MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */
389 if ((m=(MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL)
390 {
391 OPENSSL_free(addr);
392 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
393 return;
394 }
395 if (mh == NULL)
396 {
397 if ((mh=lh_new(mem_hash,mem_cmp)) == NULL)
398 {
399 OPENSSL_free(addr);
400 OPENSSL_free(m);
401 addr=NULL;
402 goto err;
403 }
404 }
405
406 m->addr=addr;
407 m->file=file;
408 m->line=line;
409 m->num=num;
410 if (options & V_CRYPTO_MDEBUG_THREAD)
411 m->thread=CRYPTO_thread_id();
412 else
413 m->thread=0;
414
415 if (order == break_order_num)
416 {
417 /* BREAK HERE */
418 m->order=order;
419 }
420 m->order=order++;
421#ifdef LEVITTE_DEBUG
422 fprintf(stderr, "LEVITTE_DEBUG: [%5d] %c 0x%p (%d)\n",
423 m->order,
424 (before_p & 128) ? '*' : '+',
425 m->addr, m->num);
426#endif
427 if (options & V_CRYPTO_MDEBUG_TIME)
428 m->time=time(NULL);
429 else
430 m->time=0;
431
432 tmp.thread=CRYPTO_thread_id();
433 m->app_info=NULL;
434 if (amih != NULL
435 && (amim=(APP_INFO *)lh_retrieve(amih,(char *)&tmp)) != NULL)
436 {
437 m->app_info = amim;
438 amim->references++;
439 }
440
441 if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL)
442 {
443 /* Not good, but don't sweat it */
444 if (mm->app_info != NULL)
445 {
446 mm->app_info->references--;
447 }
448 OPENSSL_free(mm);
449 }
450 err:
451 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
452 }
453 break;
454 }
455 return;
456 }
457
458void CRYPTO_dbg_free(void *addr, int before_p)
459 {
460 MEM m,*mp;
461
462 switch(before_p)
463 {
464 case 0:
465 if (addr == NULL)
466 break;
467
468 if (is_MemCheck_on() && (mh != NULL))
469 {
470 MemCheck_off();
471
472 m.addr=addr;
473 mp=(MEM *)lh_delete(mh,(char *)&m);
474 if (mp != NULL)
475 {
476#ifdef LEVITTE_DEBUG
477 fprintf(stderr, "LEVITTE_DEBUG: [%5d] - 0x%p (%d)\n",
478 mp->order, mp->addr, mp->num);
479#endif
480 if (mp->app_info != NULL)
481 {
482 mp->app_info->references--;
483 }
484 OPENSSL_free(mp);
485 }
486
487 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
488 }
489 break;
490 case 1:
491 break;
492 }
493 }
494
495void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
496 const char *file, int line, int before_p)
497 {
498 MEM m,*mp;
499
500#ifdef LEVITTE_DEBUG
501 fprintf(stderr, "LEVITTE_DEBUG: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n",
502 addr1, addr2, num, file, line, before_p);
503#endif
504
505 switch(before_p)
506 {
507 case 0:
508 break;
509 case 1:
510 if (addr2 == NULL)
511 break;
512
513 if (addr1 == NULL)
514 {
515 CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p);
516 break;
517 }
518
519 if (is_MemCheck_on())
520 {
521 MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */
522
523 m.addr=addr1;
524 mp=(MEM *)lh_delete(mh,(char *)&m);
525 if (mp != NULL)
526 {
527#ifdef LEVITTE_DEBUG
528 fprintf(stderr, "LEVITTE_DEBUG: [%5d] * 0x%p (%d) -> 0x%p (%d)\n",
529 mp->order,
530 mp->addr, mp->num,
531 addr2, num);
532#endif
533 mp->addr=addr2;
534 mp->num=num;
535 lh_insert(mh,(char *)mp);
536 }
537
538 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
539 }
540 break;
541 }
542 return;
543 }
544
545
546typedef struct mem_leak_st
547 {
548 BIO *bio;
549 int chunks;
550 long bytes;
551 } MEM_LEAK;
552
553static void print_leak(MEM *m, MEM_LEAK *l)
554 {
555 char buf[1024];
556 char *bufp = buf;
557 APP_INFO *amip;
558 int ami_cnt;
559 struct tm *lcl = NULL;
560 unsigned long ti;
561
562 if(m->addr == (char *)l->bio)
563 return;
564
565 if (options & V_CRYPTO_MDEBUG_TIME)
566 {
567 lcl = localtime(&m->time);
568
569 sprintf(bufp, "[%02d:%02d:%02d] ",
570 lcl->tm_hour,lcl->tm_min,lcl->tm_sec);
571 bufp += strlen(bufp);
572 }
573
574 sprintf(bufp, "%5lu file=%s, line=%d, ",
575 m->order,m->file,m->line);
576 bufp += strlen(bufp);
577
578 if (options & V_CRYPTO_MDEBUG_THREAD)
579 {
580 sprintf(bufp, "thread=%lu, ", m->thread);
581 bufp += strlen(bufp);
582 }
583
584 sprintf(bufp, "number=%d, address=%08lX\n",
585 m->num,(unsigned long)m->addr);
586 bufp += strlen(bufp);
587
588 BIO_puts(l->bio,buf);
589
590 l->chunks++;
591 l->bytes+=m->num;
592
593 amip=m->app_info;
594 ami_cnt=0;
595 if (!amip)
596 return;
597 ti=amip->thread;
598
599 do
600 {
601 int buf_len;
602 int info_len;
603
604 ami_cnt++;
605 memset(buf,'>',ami_cnt);
606 sprintf(buf + ami_cnt,
607 " thread=%lu, file=%s, line=%d, info=\"",
608 amip->thread, amip->file, amip->line);
609 buf_len=strlen(buf);
610 info_len=strlen(amip->info);
611 if (128 - buf_len - 3 < info_len)
612 {
613 memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
614 buf_len = 128 - 3;
615 }
616 else
617 {
618 strcpy(buf + buf_len, amip->info);
619 buf_len = strlen(buf);
620 }
621 sprintf(buf + buf_len, "\"\n");
622
623 BIO_puts(l->bio,buf);
624
625 amip = amip->next;
626 }
627 while(amip && amip->thread == ti);
628
629#ifdef LEVITTE_DEBUG
630 if (amip)
631 {
632 fprintf(stderr, "Thread switch detected in backtrace!!!!\n");
633 abort();
634 }
635#endif
636 }
637
638void CRYPTO_mem_leaks(BIO *b)
639 {
640 MEM_LEAK ml;
641 char buf[80];
642
643 if (mh == NULL && amih == NULL)
644 return;
645 ml.bio=b;
646 ml.bytes=0;
647 ml.chunks=0;
648 MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */
649 if (mh != NULL)
650 lh_doall_arg(mh,(void (*)())print_leak,(char *)&ml);
651 if (ml.chunks != 0)
652 {
653 sprintf(buf,"%ld bytes leaked in %d chunks\n",
654 ml.bytes,ml.chunks);
655 BIO_puts(b,buf);
656 }
657 else
658 {
659 /* Make sure that, if we found no leaks, memory-leak debugging itself
660 * does not introduce memory leaks (which might irritate
661 * external debugging tools).
662 * (When someone enables leak checking, but does not call
663 * this function, we declare it to be their fault.)
664 *
665 * XXX This should be in CRYPTO_mem_leaks_cb,
666 * and CRYPTO_mem_leaks should be implemented by
667 * using CRYPTO_mem_leaks_cb.
668 * (Also their should be a variant of lh_doall_arg
669 * that takes a function pointer instead of a void *;
670 * this would obviate the ugly and illegal
671 * void_fn_to_char kludge in CRYPTO_mem_leaks_cb.
672 * Otherwise the code police will come and get us.)
673 */
674 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
675 if (mh != NULL)
676 {
677 lh_free(mh);
678 mh = NULL;
679 }
680 if (amih != NULL)
681 {
682 if (lh_num_items(amih) == 0)
683 {
684 lh_free(amih);
685 amih = NULL;
686 }
687 }
688 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
689 }
690 MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
691
692#if 0
693 lh_stats_bio(mh,b);
694 lh_node_stats_bio(mh,b);
695 lh_node_usage_stats_bio(mh,b);
696#endif
697 }
698
699#ifndef NO_FP_API
700void CRYPTO_mem_leaks_fp(FILE *fp)
701 {
702 BIO *b;
703
704 if (mh == NULL) return;
705 if ((b=BIO_new(BIO_s_file())) == NULL)
706 return;
707 BIO_set_fp(b,fp,BIO_NOCLOSE);
708 CRYPTO_mem_leaks(b);
709 BIO_free(b);
710 }
711#endif
712
713
714
715/* FIXME: We really don't allow much to the callback. For example, it has
716 no chance of reaching the info stack for the item it processes. Should
717 it really be this way? -- Richard Levitte */
718static void cb_leak(MEM *m,
719 void (**cb)(unsigned long, const char *, int, int, void *))
720 {
721 (**cb)(m->order,m->file,m->line,m->num,m->addr);
722 }
723
724void CRYPTO_mem_leaks_cb(void (*cb)(unsigned long, const char *, int, int, void *))
725 {
726 if (mh == NULL) return;
727 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
728 lh_doall_arg(mh,(void (*)())cb_leak,(void *)&cb);
729 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
730 }