2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
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.
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).
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.
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
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)"
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
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.]
58 /* ====================================================================
59 * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
61 * Redistribution and use in source and binary forms, with or without
62 * modification, are permitted provided that the following conditions
65 * 1. Redistributions of source code must retain the above copyright
66 * notice, this list of conditions and the following disclaimer.
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
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/)"
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.
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.
87 * 6. Redistributions of any form whatsoever must retain the following
89 * "This product includes software developed by the OpenSSL Project
90 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
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 * ====================================================================
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).
115 #include "cryptlib.h"
116 #include <openssl/crypto.h>
117 #include <openssl/buffer.h>
118 #include <openssl/bio.h>
119 #include <openssl/lhash.h>
121 static 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).
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
133 * State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes no sense whatsoever.
136 static unsigned long order
= 0; /* number of memory requests */
138 DECLARE_LHASH_OF(MEM
);
139 static LHASH_OF(MEM
) *mh
=NULL
; /* hash-table of memory requests
140 * (address as key); access requires
144 typedef 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.
153 CRYPTO_THREADID threadid
;
157 struct app_mem_info_st
*next
; /* tail of thread's stack */
161 static void app_info_free(APP_INFO
*);
163 DECLARE_LHASH_OF(APP_INFO
);
164 static 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
171 typedef struct mem_st
172 /* memory-block description */
178 CRYPTO_THREADID threadid
;
184 static long options
= /* extra information to be recorded */
185 #if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL)
186 V_CRYPTO_MDEBUG_TIME
|
188 #if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL)
189 V_CRYPTO_MDEBUG_THREAD
|
194 static unsigned int num_disable
= 0; /* num_disable > 0
196 * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE)
199 /* Valid iff num_disable > 0. CRYPTO_LOCK_MALLOC2 is locked exactly in this
200 * case (by the thread named in disabling_thread).
202 static CRYPTO_THREADID disabling_threadid
;
204 static void app_info_free(APP_INFO
*inf
)
206 if (--(inf
->references
) <= 0)
208 if (inf
->next
!= NULL
)
210 app_info_free(inf
->next
);
216 int CRYPTO_mem_ctrl(int mode
)
220 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC
);
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
;
229 case CRYPTO_MEM_CHECK_OFF
: /* aka MemCheck_stop() */
231 num_disable
= 0; /* should be true *before* MemCheck_stop is used,
232 or there'll be a lot of confusion */
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
)
240 CRYPTO_THREADID_current(&cur
);
241 if (!num_disable
|| CRYPTO_THREADID_cmp(&disabling_threadid
, &cur
)) /* otherwise we already have the MALLOC2 lock */
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).
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
;
259 CRYPTO_THREADID_cpy(&disabling_threadid
, &cur
);
264 case CRYPTO_MEM_CHECK_ENABLE
: /* aka MemCheck_on() */
265 if (mh_mode
& CRYPTO_MEM_CHECK_ON
)
267 if (num_disable
) /* always true, or something is going wrong */
270 if (num_disable
== 0)
272 mh_mode
|=CRYPTO_MEM_CHECK_ENABLE
;
273 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2
);
282 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC
);
286 int CRYPTO_is_mem_check_on(void)
290 if (mh_mode
& CRYPTO_MEM_CHECK_ON
)
293 CRYPTO_THREADID_current(&cur
);
294 CRYPTO_r_lock(CRYPTO_LOCK_MALLOC
);
296 ret
= (mh_mode
& CRYPTO_MEM_CHECK_ENABLE
)
297 || CRYPTO_THREADID_cmp(&disabling_threadid
, &cur
);
299 CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC
);
305 void CRYPTO_dbg_set_options(long bits
)
310 long CRYPTO_dbg_get_options(void)
315 static int mem_cmp(const MEM
*a
, const MEM
*b
)
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;
324 return (const char *)a
->addr
- (const char *)b
->addr
;
327 static IMPLEMENT_LHASH_COMP_FN(mem
, MEM
)
329 static unsigned long mem_hash(const MEM
*a
)
333 ret
=(unsigned long)a
->addr
;
335 ret
=ret
*17851+(ret
>>14)*7+(ret
>>4)*251;
338 static IMPLEMENT_LHASH_HASH_FN(mem
, MEM
)
340 /* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */
341 static int app_info_cmp(const void *a_void
, const void *b_void
)
343 return CRYPTO_THREADID_cmp(&((const APP_INFO
*)a_void
)->threadid
,
344 &((const APP_INFO
*)b_void
)->threadid
);
346 static IMPLEMENT_LHASH_COMP_FN(app_info
, APP_INFO
)
348 static unsigned long app_info_hash(const APP_INFO
*a
)
352 ret
= CRYPTO_THREADID_hash(&a
->threadid
);
353 /* This is left in as a "who am I to question legacy?" measure */
354 ret
=ret
*17851+(ret
>>14)*7+(ret
>>4)*251;
357 static IMPLEMENT_LHASH_HASH_FN(app_info
, APP_INFO
)
359 static APP_INFO
*pop_info(void)
362 APP_INFO
*ret
= NULL
;
366 CRYPTO_THREADID_current(&tmp
.threadid
);
367 if ((ret
=lh_APP_INFO_delete(amih
,&tmp
)) != NULL
)
369 APP_INFO
*next
=ret
->next
;
374 (void)lh_APP_INFO_insert(amih
,next
);
376 #ifdef LEVITTE_DEBUG_MEM
377 if (CRYPTO_THREADID_cmp(&ret
->threadid
, &tmp
.threadid
))
379 fprintf(stderr
, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
380 CRYPTO_THREADID_hash(&ret
->threadid
),
381 CRYPTO_THREADID_hash(&tmp
.threadid
));
385 if (--(ret
->references
) <= 0)
397 int CRYPTO_push_info_(const char *info
, const char *file
, int line
)
399 APP_INFO
*ami
, *amim
;
402 if (is_MemCheck_on())
404 MemCheck_off(); /* obtain MALLOC2 lock */
406 if ((ami
= (APP_INFO
*)OPENSSL_malloc(sizeof(APP_INFO
))) == NULL
)
413 if ((amih
=lh_APP_INFO_new()) == NULL
)
421 CRYPTO_THREADID_current(&ami
->threadid
);
428 if ((amim
=lh_APP_INFO_insert(amih
,ami
)) != NULL
)
430 #ifdef LEVITTE_DEBUG_MEM
431 if (CRYPTO_THREADID_cmp(&ami
->threadid
, &amim
->threadid
))
433 fprintf(stderr
, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
434 CRYPTO_THREADID_hash(&amim
->threadid
),
435 CRYPTO_THREADID_hash(&ami
->threadid
));
442 MemCheck_on(); /* release MALLOC2 lock */
448 int CRYPTO_pop_info(void)
452 if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */
454 MemCheck_off(); /* obtain MALLOC2 lock */
456 ret
=(pop_info() != NULL
);
458 MemCheck_on(); /* release MALLOC2 lock */
463 int CRYPTO_remove_all_info(void)
467 if (is_MemCheck_on()) /* _must_ be true */
469 MemCheck_off(); /* obtain MALLOC2 lock */
471 while(pop_info() != NULL
)
474 MemCheck_on(); /* release MALLOC2 lock */
480 static unsigned long break_order_num
=0;
481 void CRYPTO_dbg_malloc(void *addr
, int num
, const char *file
, int line
,
487 switch(before_p
& 127)
495 if (is_MemCheck_on())
497 MemCheck_off(); /* make sure we hold MALLOC2 lock */
498 if ((m
=(MEM
*)OPENSSL_malloc(sizeof(MEM
))) == NULL
)
501 MemCheck_on(); /* release MALLOC2 lock
502 * if num_disabled drops to 0 */
507 if ((mh
=lh_MEM_new()) == NULL
)
520 if (options
& V_CRYPTO_MDEBUG_THREAD
)
521 CRYPTO_THREADID_current(&m
->threadid
);
523 memset(&m
->threadid
, 0, sizeof(m
->threadid
));
525 if (order
== break_order_num
)
531 #ifdef LEVITTE_DEBUG_MEM
532 fprintf(stderr
, "LEVITTE_DEBUG_MEM: [%5ld] %c 0x%p (%d)\n",
534 (before_p
& 128) ? '*' : '+',
537 if (options
& V_CRYPTO_MDEBUG_TIME
)
542 CRYPTO_THREADID_current(&tmp
.threadid
);
545 && (amim
=lh_APP_INFO_retrieve(amih
,&tmp
)) != NULL
)
551 if ((mm
=lh_MEM_insert(mh
, m
)) != NULL
)
553 /* Not good, but don't sweat it */
554 if (mm
->app_info
!= NULL
)
556 mm
->app_info
->references
--;
561 MemCheck_on(); /* release MALLOC2 lock
562 * if num_disabled drops to 0 */
569 void CRYPTO_dbg_free(void *addr
, int before_p
)
579 if (is_MemCheck_on() && (mh
!= NULL
))
581 MemCheck_off(); /* make sure we hold MALLOC2 lock */
584 mp
=lh_MEM_delete(mh
,&m
);
587 #ifdef LEVITTE_DEBUG_MEM
588 fprintf(stderr
, "LEVITTE_DEBUG_MEM: [%5ld] - 0x%p (%d)\n",
589 mp
->order
, mp
->addr
, mp
->num
);
591 if (mp
->app_info
!= NULL
)
592 app_info_free(mp
->app_info
);
596 MemCheck_on(); /* release MALLOC2 lock
597 * if num_disabled drops to 0 */
605 void CRYPTO_dbg_realloc(void *addr1
, void *addr2
, int num
,
606 const char *file
, int line
, int before_p
)
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
);
625 CRYPTO_dbg_malloc(addr2
, num
, file
, line
, 128 | before_p
);
629 if (is_MemCheck_on())
631 MemCheck_off(); /* make sure we hold MALLOC2 lock */
634 mp
=lh_MEM_delete(mh
,&m
);
637 #ifdef LEVITTE_DEBUG_MEM
638 fprintf(stderr
, "LEVITTE_DEBUG_MEM: [%5ld] * 0x%p (%d) -> 0x%p (%d)\n",
645 (void)lh_MEM_insert(mh
,mp
);
648 MemCheck_on(); /* release MALLOC2 lock
649 * if num_disabled drops to 0 */
657 typedef struct mem_leak_st
664 static void print_leak_doall_arg(const MEM
*m
, MEM_LEAK
*l
)
670 struct tm
*lcl
= NULL
;
673 #define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf))
675 if(m
->addr
== (char *)l
->bio
)
678 if (options
& V_CRYPTO_MDEBUG_TIME
)
680 lcl
= localtime(&m
->time
);
682 BIO_snprintf(bufp
, BUF_REMAIN
, "[%02d:%02d:%02d] ",
683 lcl
->tm_hour
,lcl
->tm_min
,lcl
->tm_sec
);
684 bufp
+= strlen(bufp
);
687 BIO_snprintf(bufp
, BUF_REMAIN
, "%5lu file=%s, line=%d, ",
688 m
->order
,m
->file
,m
->line
);
689 bufp
+= strlen(bufp
);
691 if (options
& V_CRYPTO_MDEBUG_THREAD
)
693 BIO_snprintf(bufp
, BUF_REMAIN
, "thread=%lu, ",
694 CRYPTO_THREADID_hash(&m
->threadid
));
695 bufp
+= strlen(bufp
);
698 BIO_snprintf(bufp
, BUF_REMAIN
, "number=%d, address=%08lX\n",
699 m
->num
,(unsigned long)m
->addr
);
700 bufp
+= strlen(bufp
);
702 BIO_puts(l
->bio
,buf
);
711 CRYPTO_THREADID_cpy(&ti
, &amip
->threadid
);
719 memset(buf
,'>',ami_cnt
);
720 BIO_snprintf(buf
+ ami_cnt
, sizeof buf
- ami_cnt
,
721 " thread=%lu, file=%s, line=%d, info=\"",
722 CRYPTO_THREADID_hash(&amip
->threadid
), amip
->file
,
725 info_len
=strlen(amip
->info
);
726 if (128 - buf_len
- 3 < info_len
)
728 memcpy(buf
+ buf_len
, amip
->info
, 128 - buf_len
- 3);
733 BUF_strlcpy(buf
+ buf_len
, amip
->info
,
734 sizeof buf
- buf_len
);
735 buf_len
= strlen(buf
);
737 BIO_snprintf(buf
+ buf_len
, sizeof buf
- buf_len
, "\"\n");
739 BIO_puts(l
->bio
,buf
);
743 while(amip
&& !CRYPTO_THREADID_cmp(&amip
->threadid
, &ti
));
745 #ifdef LEVITTE_DEBUG_MEM
748 fprintf(stderr
, "Thread switch detected in backtrace!!!!\n");
754 static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak
, const MEM
, MEM_LEAK
)
756 void CRYPTO_mem_leaks(BIO
*b
)
760 if (mh
== NULL
&& amih
== NULL
)
763 MemCheck_off(); /* obtain MALLOC2 lock */
769 lh_MEM_doall_arg(mh
, LHASH_DOALL_ARG_FN(print_leak
), MEM_LEAK
,
773 BIO_printf(b
,"%ld bytes leaked in %d chunks\n",
775 #ifdef CRYPTO_MDEBUG_ABORT
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.)
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.
790 * (Also there should be a variant of lh_doall_arg
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.)
798 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC
);
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
;
812 if (lh_APP_INFO_num_items(amih
) == 0)
814 lh_APP_INFO_free(amih
);
819 mh_mode
= old_mh_mode
;
820 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC
);
822 MemCheck_on(); /* release MALLOC2 lock */
825 #ifndef OPENSSL_NO_FP_API
826 void CRYPTO_mem_leaks_fp(FILE *fp
)
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!! */
835 b
= BIO_new(BIO_s_file());
838 BIO_set_fp(b
,fp
,BIO_NOCLOSE
);
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 */
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
858 typedef CRYPTO_MEM_LEAK_CB
*PCRYPTO_MEM_LEAK_CB
;
860 static void cb_leak_doall_arg(const MEM
*m
, PCRYPTO_MEM_LEAK_CB
*cb
)
862 (*cb
)(m
->order
,m
->file
,m
->line
,m
->num
,m
->addr
);
865 static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak
, const MEM
, PCRYPTO_MEM_LEAK_CB
)
867 void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB
*cb
)
869 if (mh
== NULL
) return;
870 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2
);
871 lh_MEM_doall_arg(mh
, LHASH_DOALL_ARG_FN(cb_leak
), PCRYPTO_MEM_LEAK_CB
,
873 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2
);