10Sstevel@tonic-gate /* crypto/mem_dbg.c */
20Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
30Sstevel@tonic-gate * All rights reserved.
40Sstevel@tonic-gate *
50Sstevel@tonic-gate * This package is an SSL implementation written
60Sstevel@tonic-gate * by Eric Young (eay@cryptsoft.com).
70Sstevel@tonic-gate * The implementation was written so as to conform with Netscapes SSL.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * This library is free for commercial and non-commercial use as long as
100Sstevel@tonic-gate * the following conditions are aheared to. The following conditions
110Sstevel@tonic-gate * apply to all code found in this distribution, be it the RC4, RSA,
120Sstevel@tonic-gate * lhash, DES, etc., code; not just the SSL code. The SSL documentation
130Sstevel@tonic-gate * included with this distribution is covered by the same copyright terms
140Sstevel@tonic-gate * except that the holder is Tim Hudson (tjh@cryptsoft.com).
150Sstevel@tonic-gate *
160Sstevel@tonic-gate * Copyright remains Eric Young's, and as such any Copyright notices in
170Sstevel@tonic-gate * the code are not to be removed.
180Sstevel@tonic-gate * If this package is used in a product, Eric Young should be given attribution
190Sstevel@tonic-gate * as the author of the parts of the library used.
200Sstevel@tonic-gate * This can be in the form of a textual message at program startup or
210Sstevel@tonic-gate * in documentation (online or textual) provided with the package.
220Sstevel@tonic-gate *
230Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
240Sstevel@tonic-gate * modification, are permitted provided that the following conditions
250Sstevel@tonic-gate * are met:
260Sstevel@tonic-gate * 1. Redistributions of source code must retain the copyright
270Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
280Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
290Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the
300Sstevel@tonic-gate * documentation and/or other materials provided with the distribution.
310Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software
320Sstevel@tonic-gate * must display the following acknowledgement:
330Sstevel@tonic-gate * "This product includes cryptographic software written by
340Sstevel@tonic-gate * Eric Young (eay@cryptsoft.com)"
350Sstevel@tonic-gate * The word 'cryptographic' can be left out if the rouines from the library
360Sstevel@tonic-gate * being used are not cryptographic related :-).
370Sstevel@tonic-gate * 4. If you include any Windows specific code (or a derivative thereof) from
380Sstevel@tonic-gate * the apps directory (application code) you must include an acknowledgement:
390Sstevel@tonic-gate * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
400Sstevel@tonic-gate *
410Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
420Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
430Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
440Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
450Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
460Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
470Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
480Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
490Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
500Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
510Sstevel@tonic-gate * SUCH DAMAGE.
520Sstevel@tonic-gate *
530Sstevel@tonic-gate * The licence and distribution terms for any publically available version or
540Sstevel@tonic-gate * derivative of this code cannot be changed. i.e. this code cannot simply be
550Sstevel@tonic-gate * copied and put under another distribution licence
560Sstevel@tonic-gate * [including the GNU Public Licence.]
570Sstevel@tonic-gate */
580Sstevel@tonic-gate
590Sstevel@tonic-gate #include <stdio.h>
600Sstevel@tonic-gate #include <stdlib.h>
610Sstevel@tonic-gate #include <time.h>
62*2139Sjp161948 #include "cryptlib.h"
630Sstevel@tonic-gate #include <openssl/crypto.h>
640Sstevel@tonic-gate #include <openssl/buffer.h>
650Sstevel@tonic-gate #include <openssl/bio.h>
660Sstevel@tonic-gate #include <openssl/lhash.h>
670Sstevel@tonic-gate
680Sstevel@tonic-gate static int mh_mode=CRYPTO_MEM_CHECK_OFF;
690Sstevel@tonic-gate /* The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE
700Sstevel@tonic-gate * when the application asks for it (usually after library initialisation
710Sstevel@tonic-gate * for which no book-keeping is desired).
720Sstevel@tonic-gate *
730Sstevel@tonic-gate * State CRYPTO_MEM_CHECK_ON exists only temporarily when the library
740Sstevel@tonic-gate * thinks that certain allocations should not be checked (e.g. the data
750Sstevel@tonic-gate * structures used for memory checking). It is not suitable as an initial
760Sstevel@tonic-gate * state: the library will unexpectedly enable memory checking when it
770Sstevel@tonic-gate * executes one of those sections that want to disable checking
780Sstevel@tonic-gate * temporarily.
790Sstevel@tonic-gate *
800Sstevel@tonic-gate * State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes no sense whatsoever.
810Sstevel@tonic-gate */
820Sstevel@tonic-gate
830Sstevel@tonic-gate static unsigned long order = 0; /* number of memory requests */
840Sstevel@tonic-gate static LHASH *mh=NULL; /* hash-table of memory requests (address as key);
850Sstevel@tonic-gate * access requires MALLOC2 lock */
860Sstevel@tonic-gate
870Sstevel@tonic-gate
880Sstevel@tonic-gate typedef struct app_mem_info_st
890Sstevel@tonic-gate /* For application-defined information (static C-string `info')
900Sstevel@tonic-gate * to be displayed in memory leak list.
910Sstevel@tonic-gate * Each thread has its own stack. For applications, there is
920Sstevel@tonic-gate * CRYPTO_push_info("...") to push an entry,
930Sstevel@tonic-gate * CRYPTO_pop_info() to pop an entry,
940Sstevel@tonic-gate * CRYPTO_remove_all_info() to pop all entries.
950Sstevel@tonic-gate */
960Sstevel@tonic-gate {
970Sstevel@tonic-gate unsigned long thread;
980Sstevel@tonic-gate const char *file;
990Sstevel@tonic-gate int line;
1000Sstevel@tonic-gate const char *info;
1010Sstevel@tonic-gate struct app_mem_info_st *next; /* tail of thread's stack */
1020Sstevel@tonic-gate int references;
1030Sstevel@tonic-gate } APP_INFO;
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate static void app_info_free(APP_INFO *);
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's
1080Sstevel@tonic-gate * that are at the top of their thread's stack
1090Sstevel@tonic-gate * (with `thread' as key);
1100Sstevel@tonic-gate * access requires MALLOC2 lock */
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate typedef struct mem_st
1130Sstevel@tonic-gate /* memory-block description */
1140Sstevel@tonic-gate {
1150Sstevel@tonic-gate void *addr;
1160Sstevel@tonic-gate int num;
1170Sstevel@tonic-gate const char *file;
1180Sstevel@tonic-gate int line;
1190Sstevel@tonic-gate unsigned long thread;
1200Sstevel@tonic-gate unsigned long order;
1210Sstevel@tonic-gate time_t time;
1220Sstevel@tonic-gate APP_INFO *app_info;
1230Sstevel@tonic-gate } MEM;
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate static long options = /* extra information to be recorded */
1260Sstevel@tonic-gate #if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL)
1270Sstevel@tonic-gate V_CRYPTO_MDEBUG_TIME |
1280Sstevel@tonic-gate #endif
1290Sstevel@tonic-gate #if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL)
1300Sstevel@tonic-gate V_CRYPTO_MDEBUG_THREAD |
1310Sstevel@tonic-gate #endif
1320Sstevel@tonic-gate 0;
1330Sstevel@tonic-gate
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate static unsigned int num_disable = 0; /* num_disable > 0
1360Sstevel@tonic-gate * iff
1370Sstevel@tonic-gate * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE)
1380Sstevel@tonic-gate */
1390Sstevel@tonic-gate static unsigned long disabling_thread = 0; /* Valid iff num_disable > 0.
1400Sstevel@tonic-gate * CRYPTO_LOCK_MALLOC2 is locked
1410Sstevel@tonic-gate * exactly in this case (by the
1420Sstevel@tonic-gate * thread named in disabling_thread).
1430Sstevel@tonic-gate */
1440Sstevel@tonic-gate
app_info_free(APP_INFO * inf)1450Sstevel@tonic-gate static void app_info_free(APP_INFO *inf)
1460Sstevel@tonic-gate {
1470Sstevel@tonic-gate if (--(inf->references) <= 0)
1480Sstevel@tonic-gate {
1490Sstevel@tonic-gate if (inf->next != NULL)
1500Sstevel@tonic-gate {
1510Sstevel@tonic-gate app_info_free(inf->next);
1520Sstevel@tonic-gate }
1530Sstevel@tonic-gate OPENSSL_free(inf);
1540Sstevel@tonic-gate }
1550Sstevel@tonic-gate }
1560Sstevel@tonic-gate
CRYPTO_mem_ctrl(int mode)1570Sstevel@tonic-gate int CRYPTO_mem_ctrl(int mode)
1580Sstevel@tonic-gate {
1590Sstevel@tonic-gate int ret=mh_mode;
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
1620Sstevel@tonic-gate switch (mode)
1630Sstevel@tonic-gate {
1640Sstevel@tonic-gate /* for applications (not to be called while multiple threads
1650Sstevel@tonic-gate * use the library): */
1660Sstevel@tonic-gate case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */
1670Sstevel@tonic-gate mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
1680Sstevel@tonic-gate num_disable = 0;
1690Sstevel@tonic-gate break;
1700Sstevel@tonic-gate case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
1710Sstevel@tonic-gate mh_mode = 0;
1720Sstevel@tonic-gate num_disable = 0; /* should be true *before* MemCheck_stop is used,
1730Sstevel@tonic-gate or there'll be a lot of confusion */
1740Sstevel@tonic-gate break;
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate /* switch off temporarily (for library-internal use): */
1770Sstevel@tonic-gate case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
1780Sstevel@tonic-gate if (mh_mode & CRYPTO_MEM_CHECK_ON)
1790Sstevel@tonic-gate {
1800Sstevel@tonic-gate if (!num_disable || (disabling_thread != CRYPTO_thread_id())) /* otherwise we already have the MALLOC2 lock */
1810Sstevel@tonic-gate {
1820Sstevel@tonic-gate /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while
1830Sstevel@tonic-gate * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if
1840Sstevel@tonic-gate * somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot release
1850Sstevel@tonic-gate * it because we block entry to this function).
1860Sstevel@tonic-gate * Give them a chance, first, and then claim the locks in
1870Sstevel@tonic-gate * appropriate order (long-time lock first).
1880Sstevel@tonic-gate */
1890Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
1900Sstevel@tonic-gate /* Note that after we have waited for CRYPTO_LOCK_MALLOC2
1910Sstevel@tonic-gate * and CRYPTO_LOCK_MALLOC, we'll still be in the right
1920Sstevel@tonic-gate * "case" and "if" branch because MemCheck_start and
1930Sstevel@tonic-gate * MemCheck_stop may never be used while there are multiple
1940Sstevel@tonic-gate * OpenSSL threads. */
1950Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
1960Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
1970Sstevel@tonic-gate mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE;
1980Sstevel@tonic-gate disabling_thread=CRYPTO_thread_id();
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate num_disable++;
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate break;
2030Sstevel@tonic-gate case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */
2040Sstevel@tonic-gate if (mh_mode & CRYPTO_MEM_CHECK_ON)
2050Sstevel@tonic-gate {
2060Sstevel@tonic-gate if (num_disable) /* always true, or something is going wrong */
2070Sstevel@tonic-gate {
2080Sstevel@tonic-gate num_disable--;
2090Sstevel@tonic-gate if (num_disable == 0)
2100Sstevel@tonic-gate {
2110Sstevel@tonic-gate mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
2120Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
2130Sstevel@tonic-gate }
2140Sstevel@tonic-gate }
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate break;
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate default:
2190Sstevel@tonic-gate break;
2200Sstevel@tonic-gate }
2210Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
2220Sstevel@tonic-gate return(ret);
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate
CRYPTO_is_mem_check_on(void)2250Sstevel@tonic-gate int CRYPTO_is_mem_check_on(void)
2260Sstevel@tonic-gate {
2270Sstevel@tonic-gate int ret = 0;
2280Sstevel@tonic-gate
2290Sstevel@tonic-gate if (mh_mode & CRYPTO_MEM_CHECK_ON)
2300Sstevel@tonic-gate {
2310Sstevel@tonic-gate CRYPTO_r_lock(CRYPTO_LOCK_MALLOC);
2320Sstevel@tonic-gate
2330Sstevel@tonic-gate ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
2340Sstevel@tonic-gate || (disabling_thread != CRYPTO_thread_id());
2350Sstevel@tonic-gate
2360Sstevel@tonic-gate CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC);
2370Sstevel@tonic-gate }
2380Sstevel@tonic-gate return(ret);
2390Sstevel@tonic-gate }
2400Sstevel@tonic-gate
2410Sstevel@tonic-gate
CRYPTO_dbg_set_options(long bits)2420Sstevel@tonic-gate void CRYPTO_dbg_set_options(long bits)
2430Sstevel@tonic-gate {
2440Sstevel@tonic-gate options = bits;
2450Sstevel@tonic-gate }
2460Sstevel@tonic-gate
CRYPTO_dbg_get_options(void)2470Sstevel@tonic-gate long CRYPTO_dbg_get_options(void)
2480Sstevel@tonic-gate {
2490Sstevel@tonic-gate return options;
2500Sstevel@tonic-gate }
2510Sstevel@tonic-gate
2520Sstevel@tonic-gate /* static int mem_cmp(MEM *a, MEM *b) */
mem_cmp(const void * a_void,const void * b_void)2530Sstevel@tonic-gate static int mem_cmp(const void *a_void, const void *b_void)
2540Sstevel@tonic-gate {
255*2139Sjp161948 #ifdef _WIN64
256*2139Sjp161948 const char *a=(const char *)((const MEM *)a_void)->addr,
257*2139Sjp161948 *b=(const char *)((const MEM *)b_void)->addr;
258*2139Sjp161948 if (a==b) return 0;
259*2139Sjp161948 else if (a>b) return 1;
260*2139Sjp161948 else return -1;
261*2139Sjp161948 #else
2620Sstevel@tonic-gate return((const char *)((const MEM *)a_void)->addr
2630Sstevel@tonic-gate - (const char *)((const MEM *)b_void)->addr);
264*2139Sjp161948 #endif
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate /* static unsigned long mem_hash(MEM *a) */
mem_hash(const void * a_void)2680Sstevel@tonic-gate static unsigned long mem_hash(const void *a_void)
2690Sstevel@tonic-gate {
2700Sstevel@tonic-gate unsigned long ret;
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate ret=(unsigned long)((const MEM *)a_void)->addr;
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
2750Sstevel@tonic-gate return(ret);
2760Sstevel@tonic-gate }
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate /* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */
app_info_cmp(const void * a_void,const void * b_void)2790Sstevel@tonic-gate static int app_info_cmp(const void *a_void, const void *b_void)
2800Sstevel@tonic-gate {
2810Sstevel@tonic-gate return(((const APP_INFO *)a_void)->thread
2820Sstevel@tonic-gate != ((const APP_INFO *)b_void)->thread);
2830Sstevel@tonic-gate }
2840Sstevel@tonic-gate
2850Sstevel@tonic-gate /* static unsigned long app_info_hash(APP_INFO *a) */
app_info_hash(const void * a_void)2860Sstevel@tonic-gate static unsigned long app_info_hash(const void *a_void)
2870Sstevel@tonic-gate {
2880Sstevel@tonic-gate unsigned long ret;
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate ret=(unsigned long)((const APP_INFO *)a_void)->thread;
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
2930Sstevel@tonic-gate return(ret);
2940Sstevel@tonic-gate }
2950Sstevel@tonic-gate
pop_info(void)2960Sstevel@tonic-gate static APP_INFO *pop_info(void)
2970Sstevel@tonic-gate {
2980Sstevel@tonic-gate APP_INFO tmp;
2990Sstevel@tonic-gate APP_INFO *ret = NULL;
3000Sstevel@tonic-gate
3010Sstevel@tonic-gate if (amih != NULL)
3020Sstevel@tonic-gate {
3030Sstevel@tonic-gate tmp.thread=CRYPTO_thread_id();
3040Sstevel@tonic-gate if ((ret=(APP_INFO *)lh_delete(amih,&tmp)) != NULL)
3050Sstevel@tonic-gate {
3060Sstevel@tonic-gate APP_INFO *next=ret->next;
3070Sstevel@tonic-gate
3080Sstevel@tonic-gate if (next != NULL)
3090Sstevel@tonic-gate {
3100Sstevel@tonic-gate next->references++;
3110Sstevel@tonic-gate lh_insert(amih,(char *)next);
3120Sstevel@tonic-gate }
3130Sstevel@tonic-gate #ifdef LEVITTE_DEBUG_MEM
3140Sstevel@tonic-gate if (ret->thread != tmp.thread)
3150Sstevel@tonic-gate {
3160Sstevel@tonic-gate fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
3170Sstevel@tonic-gate ret->thread, tmp.thread);
3180Sstevel@tonic-gate abort();
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate #endif
3210Sstevel@tonic-gate if (--(ret->references) <= 0)
3220Sstevel@tonic-gate {
3230Sstevel@tonic-gate ret->next = NULL;
3240Sstevel@tonic-gate if (next != NULL)
3250Sstevel@tonic-gate next->references--;
3260Sstevel@tonic-gate OPENSSL_free(ret);
3270Sstevel@tonic-gate }
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate return(ret);
3310Sstevel@tonic-gate }
3320Sstevel@tonic-gate
CRYPTO_push_info_(const char * info,const char * file,int line)3330Sstevel@tonic-gate int CRYPTO_push_info_(const char *info, const char *file, int line)
3340Sstevel@tonic-gate {
3350Sstevel@tonic-gate APP_INFO *ami, *amim;
3360Sstevel@tonic-gate int ret=0;
3370Sstevel@tonic-gate
3380Sstevel@tonic-gate if (is_MemCheck_on())
3390Sstevel@tonic-gate {
3400Sstevel@tonic-gate MemCheck_off(); /* obtain MALLOC2 lock */
3410Sstevel@tonic-gate
3420Sstevel@tonic-gate if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL)
3430Sstevel@tonic-gate {
3440Sstevel@tonic-gate ret=0;
3450Sstevel@tonic-gate goto err;
3460Sstevel@tonic-gate }
3470Sstevel@tonic-gate if (amih == NULL)
3480Sstevel@tonic-gate {
3490Sstevel@tonic-gate if ((amih=lh_new(app_info_hash, app_info_cmp)) == NULL)
3500Sstevel@tonic-gate {
3510Sstevel@tonic-gate OPENSSL_free(ami);
3520Sstevel@tonic-gate ret=0;
3530Sstevel@tonic-gate goto err;
3540Sstevel@tonic-gate }
3550Sstevel@tonic-gate }
3560Sstevel@tonic-gate
3570Sstevel@tonic-gate ami->thread=CRYPTO_thread_id();
3580Sstevel@tonic-gate ami->file=file;
3590Sstevel@tonic-gate ami->line=line;
3600Sstevel@tonic-gate ami->info=info;
3610Sstevel@tonic-gate ami->references=1;
3620Sstevel@tonic-gate ami->next=NULL;
3630Sstevel@tonic-gate
3640Sstevel@tonic-gate if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL)
3650Sstevel@tonic-gate {
3660Sstevel@tonic-gate #ifdef LEVITTE_DEBUG_MEM
3670Sstevel@tonic-gate if (ami->thread != amim->thread)
3680Sstevel@tonic-gate {
3690Sstevel@tonic-gate fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
3700Sstevel@tonic-gate amim->thread, ami->thread);
3710Sstevel@tonic-gate abort();
3720Sstevel@tonic-gate }
3730Sstevel@tonic-gate #endif
3740Sstevel@tonic-gate ami->next=amim;
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate err:
3770Sstevel@tonic-gate MemCheck_on(); /* release MALLOC2 lock */
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate return(ret);
3810Sstevel@tonic-gate }
3820Sstevel@tonic-gate
CRYPTO_pop_info(void)3830Sstevel@tonic-gate int CRYPTO_pop_info(void)
3840Sstevel@tonic-gate {
3850Sstevel@tonic-gate int ret=0;
3860Sstevel@tonic-gate
3870Sstevel@tonic-gate if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */
3880Sstevel@tonic-gate {
3890Sstevel@tonic-gate MemCheck_off(); /* obtain MALLOC2 lock */
3900Sstevel@tonic-gate
3910Sstevel@tonic-gate ret=(pop_info() != NULL);
3920Sstevel@tonic-gate
3930Sstevel@tonic-gate MemCheck_on(); /* release MALLOC2 lock */
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate return(ret);
3960Sstevel@tonic-gate }
3970Sstevel@tonic-gate
CRYPTO_remove_all_info(void)3980Sstevel@tonic-gate int CRYPTO_remove_all_info(void)
3990Sstevel@tonic-gate {
4000Sstevel@tonic-gate int ret=0;
4010Sstevel@tonic-gate
4020Sstevel@tonic-gate if (is_MemCheck_on()) /* _must_ be true */
4030Sstevel@tonic-gate {
4040Sstevel@tonic-gate MemCheck_off(); /* obtain MALLOC2 lock */
4050Sstevel@tonic-gate
4060Sstevel@tonic-gate while(pop_info() != NULL)
4070Sstevel@tonic-gate ret++;
4080Sstevel@tonic-gate
4090Sstevel@tonic-gate MemCheck_on(); /* release MALLOC2 lock */
4100Sstevel@tonic-gate }
4110Sstevel@tonic-gate return(ret);
4120Sstevel@tonic-gate }
4130Sstevel@tonic-gate
4140Sstevel@tonic-gate
4150Sstevel@tonic-gate static unsigned long break_order_num=0;
CRYPTO_dbg_malloc(void * addr,int num,const char * file,int line,int before_p)4160Sstevel@tonic-gate void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
4170Sstevel@tonic-gate int before_p)
4180Sstevel@tonic-gate {
4190Sstevel@tonic-gate MEM *m,*mm;
4200Sstevel@tonic-gate APP_INFO tmp,*amim;
4210Sstevel@tonic-gate
4220Sstevel@tonic-gate switch(before_p & 127)
4230Sstevel@tonic-gate {
4240Sstevel@tonic-gate case 0:
4250Sstevel@tonic-gate break;
4260Sstevel@tonic-gate case 1:
4270Sstevel@tonic-gate if (addr == NULL)
4280Sstevel@tonic-gate break;
4290Sstevel@tonic-gate
4300Sstevel@tonic-gate if (is_MemCheck_on())
4310Sstevel@tonic-gate {
4320Sstevel@tonic-gate MemCheck_off(); /* make sure we hold MALLOC2 lock */
4330Sstevel@tonic-gate if ((m=(MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL)
4340Sstevel@tonic-gate {
4350Sstevel@tonic-gate OPENSSL_free(addr);
4360Sstevel@tonic-gate MemCheck_on(); /* release MALLOC2 lock
4370Sstevel@tonic-gate * if num_disabled drops to 0 */
4380Sstevel@tonic-gate return;
4390Sstevel@tonic-gate }
4400Sstevel@tonic-gate if (mh == NULL)
4410Sstevel@tonic-gate {
4420Sstevel@tonic-gate if ((mh=lh_new(mem_hash, mem_cmp)) == NULL)
4430Sstevel@tonic-gate {
4440Sstevel@tonic-gate OPENSSL_free(addr);
4450Sstevel@tonic-gate OPENSSL_free(m);
4460Sstevel@tonic-gate addr=NULL;
4470Sstevel@tonic-gate goto err;
4480Sstevel@tonic-gate }
4490Sstevel@tonic-gate }
4500Sstevel@tonic-gate
4510Sstevel@tonic-gate m->addr=addr;
4520Sstevel@tonic-gate m->file=file;
4530Sstevel@tonic-gate m->line=line;
4540Sstevel@tonic-gate m->num=num;
4550Sstevel@tonic-gate if (options & V_CRYPTO_MDEBUG_THREAD)
4560Sstevel@tonic-gate m->thread=CRYPTO_thread_id();
4570Sstevel@tonic-gate else
4580Sstevel@tonic-gate m->thread=0;
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate if (order == break_order_num)
4610Sstevel@tonic-gate {
4620Sstevel@tonic-gate /* BREAK HERE */
4630Sstevel@tonic-gate m->order=order;
4640Sstevel@tonic-gate }
4650Sstevel@tonic-gate m->order=order++;
4660Sstevel@tonic-gate #ifdef LEVITTE_DEBUG_MEM
4670Sstevel@tonic-gate fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] %c 0x%p (%d)\n",
4680Sstevel@tonic-gate m->order,
4690Sstevel@tonic-gate (before_p & 128) ? '*' : '+',
4700Sstevel@tonic-gate m->addr, m->num);
4710Sstevel@tonic-gate #endif
4720Sstevel@tonic-gate if (options & V_CRYPTO_MDEBUG_TIME)
4730Sstevel@tonic-gate m->time=time(NULL);
4740Sstevel@tonic-gate else
4750Sstevel@tonic-gate m->time=0;
4760Sstevel@tonic-gate
4770Sstevel@tonic-gate tmp.thread=CRYPTO_thread_id();
4780Sstevel@tonic-gate m->app_info=NULL;
4790Sstevel@tonic-gate if (amih != NULL
4800Sstevel@tonic-gate && (amim=(APP_INFO *)lh_retrieve(amih,(char *)&tmp)) != NULL)
4810Sstevel@tonic-gate {
4820Sstevel@tonic-gate m->app_info = amim;
4830Sstevel@tonic-gate amim->references++;
4840Sstevel@tonic-gate }
4850Sstevel@tonic-gate
4860Sstevel@tonic-gate if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL)
4870Sstevel@tonic-gate {
4880Sstevel@tonic-gate /* Not good, but don't sweat it */
4890Sstevel@tonic-gate if (mm->app_info != NULL)
4900Sstevel@tonic-gate {
4910Sstevel@tonic-gate mm->app_info->references--;
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate OPENSSL_free(mm);
4940Sstevel@tonic-gate }
4950Sstevel@tonic-gate err:
4960Sstevel@tonic-gate MemCheck_on(); /* release MALLOC2 lock
4970Sstevel@tonic-gate * if num_disabled drops to 0 */
4980Sstevel@tonic-gate }
4990Sstevel@tonic-gate break;
5000Sstevel@tonic-gate }
5010Sstevel@tonic-gate return;
5020Sstevel@tonic-gate }
5030Sstevel@tonic-gate
CRYPTO_dbg_free(void * addr,int before_p)5040Sstevel@tonic-gate void CRYPTO_dbg_free(void *addr, int before_p)
5050Sstevel@tonic-gate {
5060Sstevel@tonic-gate MEM m,*mp;
5070Sstevel@tonic-gate
5080Sstevel@tonic-gate switch(before_p)
5090Sstevel@tonic-gate {
5100Sstevel@tonic-gate case 0:
5110Sstevel@tonic-gate if (addr == NULL)
5120Sstevel@tonic-gate break;
5130Sstevel@tonic-gate
5140Sstevel@tonic-gate if (is_MemCheck_on() && (mh != NULL))
5150Sstevel@tonic-gate {
5160Sstevel@tonic-gate MemCheck_off(); /* make sure we hold MALLOC2 lock */
5170Sstevel@tonic-gate
5180Sstevel@tonic-gate m.addr=addr;
5190Sstevel@tonic-gate mp=(MEM *)lh_delete(mh,(char *)&m);
5200Sstevel@tonic-gate if (mp != NULL)
5210Sstevel@tonic-gate {
5220Sstevel@tonic-gate #ifdef LEVITTE_DEBUG_MEM
5230Sstevel@tonic-gate fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] - 0x%p (%d)\n",
5240Sstevel@tonic-gate mp->order, mp->addr, mp->num);
5250Sstevel@tonic-gate #endif
5260Sstevel@tonic-gate if (mp->app_info != NULL)
5270Sstevel@tonic-gate app_info_free(mp->app_info);
5280Sstevel@tonic-gate OPENSSL_free(mp);
5290Sstevel@tonic-gate }
5300Sstevel@tonic-gate
5310Sstevel@tonic-gate MemCheck_on(); /* release MALLOC2 lock
5320Sstevel@tonic-gate * if num_disabled drops to 0 */
5330Sstevel@tonic-gate }
5340Sstevel@tonic-gate break;
5350Sstevel@tonic-gate case 1:
5360Sstevel@tonic-gate break;
5370Sstevel@tonic-gate }
5380Sstevel@tonic-gate }
5390Sstevel@tonic-gate
CRYPTO_dbg_realloc(void * addr1,void * addr2,int num,const char * file,int line,int before_p)5400Sstevel@tonic-gate void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
5410Sstevel@tonic-gate const char *file, int line, int before_p)
5420Sstevel@tonic-gate {
5430Sstevel@tonic-gate MEM m,*mp;
5440Sstevel@tonic-gate
5450Sstevel@tonic-gate #ifdef LEVITTE_DEBUG_MEM
5460Sstevel@tonic-gate fprintf(stderr, "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n",
5470Sstevel@tonic-gate addr1, addr2, num, file, line, before_p);
5480Sstevel@tonic-gate #endif
5490Sstevel@tonic-gate
5500Sstevel@tonic-gate switch(before_p)
5510Sstevel@tonic-gate {
5520Sstevel@tonic-gate case 0:
5530Sstevel@tonic-gate break;
5540Sstevel@tonic-gate case 1:
5550Sstevel@tonic-gate if (addr2 == NULL)
5560Sstevel@tonic-gate break;
5570Sstevel@tonic-gate
5580Sstevel@tonic-gate if (addr1 == NULL)
5590Sstevel@tonic-gate {
5600Sstevel@tonic-gate CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p);
5610Sstevel@tonic-gate break;
5620Sstevel@tonic-gate }
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate if (is_MemCheck_on())
5650Sstevel@tonic-gate {
5660Sstevel@tonic-gate MemCheck_off(); /* make sure we hold MALLOC2 lock */
5670Sstevel@tonic-gate
5680Sstevel@tonic-gate m.addr=addr1;
5690Sstevel@tonic-gate mp=(MEM *)lh_delete(mh,(char *)&m);
5700Sstevel@tonic-gate if (mp != NULL)
5710Sstevel@tonic-gate {
5720Sstevel@tonic-gate #ifdef LEVITTE_DEBUG_MEM
5730Sstevel@tonic-gate fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] * 0x%p (%d) -> 0x%p (%d)\n",
5740Sstevel@tonic-gate mp->order,
5750Sstevel@tonic-gate mp->addr, mp->num,
5760Sstevel@tonic-gate addr2, num);
5770Sstevel@tonic-gate #endif
5780Sstevel@tonic-gate mp->addr=addr2;
5790Sstevel@tonic-gate mp->num=num;
5800Sstevel@tonic-gate lh_insert(mh,(char *)mp);
5810Sstevel@tonic-gate }
5820Sstevel@tonic-gate
5830Sstevel@tonic-gate MemCheck_on(); /* release MALLOC2 lock
5840Sstevel@tonic-gate * if num_disabled drops to 0 */
5850Sstevel@tonic-gate }
5860Sstevel@tonic-gate break;
5870Sstevel@tonic-gate }
5880Sstevel@tonic-gate return;
5890Sstevel@tonic-gate }
5900Sstevel@tonic-gate
5910Sstevel@tonic-gate
5920Sstevel@tonic-gate typedef struct mem_leak_st
5930Sstevel@tonic-gate {
5940Sstevel@tonic-gate BIO *bio;
5950Sstevel@tonic-gate int chunks;
5960Sstevel@tonic-gate long bytes;
5970Sstevel@tonic-gate } MEM_LEAK;
5980Sstevel@tonic-gate
print_leak(const MEM * m,MEM_LEAK * l)5990Sstevel@tonic-gate static void print_leak(const MEM *m, MEM_LEAK *l)
6000Sstevel@tonic-gate {
6010Sstevel@tonic-gate char buf[1024];
6020Sstevel@tonic-gate char *bufp = buf;
6030Sstevel@tonic-gate APP_INFO *amip;
6040Sstevel@tonic-gate int ami_cnt;
6050Sstevel@tonic-gate struct tm *lcl = NULL;
6060Sstevel@tonic-gate unsigned long ti;
6070Sstevel@tonic-gate
6080Sstevel@tonic-gate #define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf))
6090Sstevel@tonic-gate
6100Sstevel@tonic-gate if(m->addr == (char *)l->bio)
6110Sstevel@tonic-gate return;
6120Sstevel@tonic-gate
6130Sstevel@tonic-gate if (options & V_CRYPTO_MDEBUG_TIME)
6140Sstevel@tonic-gate {
6150Sstevel@tonic-gate lcl = localtime(&m->time);
6160Sstevel@tonic-gate
6170Sstevel@tonic-gate BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ",
6180Sstevel@tonic-gate lcl->tm_hour,lcl->tm_min,lcl->tm_sec);
6190Sstevel@tonic-gate bufp += strlen(bufp);
6200Sstevel@tonic-gate }
6210Sstevel@tonic-gate
6220Sstevel@tonic-gate BIO_snprintf(bufp, BUF_REMAIN, "%5lu file=%s, line=%d, ",
6230Sstevel@tonic-gate m->order,m->file,m->line);
6240Sstevel@tonic-gate bufp += strlen(bufp);
6250Sstevel@tonic-gate
6260Sstevel@tonic-gate if (options & V_CRYPTO_MDEBUG_THREAD)
6270Sstevel@tonic-gate {
6280Sstevel@tonic-gate BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ", m->thread);
6290Sstevel@tonic-gate bufp += strlen(bufp);
6300Sstevel@tonic-gate }
6310Sstevel@tonic-gate
6320Sstevel@tonic-gate BIO_snprintf(bufp, BUF_REMAIN, "number=%d, address=%08lX\n",
6330Sstevel@tonic-gate m->num,(unsigned long)m->addr);
6340Sstevel@tonic-gate bufp += strlen(bufp);
6350Sstevel@tonic-gate
6360Sstevel@tonic-gate BIO_puts(l->bio,buf);
6370Sstevel@tonic-gate
6380Sstevel@tonic-gate l->chunks++;
6390Sstevel@tonic-gate l->bytes+=m->num;
6400Sstevel@tonic-gate
6410Sstevel@tonic-gate amip=m->app_info;
6420Sstevel@tonic-gate ami_cnt=0;
6430Sstevel@tonic-gate if (!amip)
6440Sstevel@tonic-gate return;
6450Sstevel@tonic-gate ti=amip->thread;
6460Sstevel@tonic-gate
6470Sstevel@tonic-gate do
6480Sstevel@tonic-gate {
6490Sstevel@tonic-gate int buf_len;
6500Sstevel@tonic-gate int info_len;
6510Sstevel@tonic-gate
6520Sstevel@tonic-gate ami_cnt++;
6530Sstevel@tonic-gate memset(buf,'>',ami_cnt);
6540Sstevel@tonic-gate BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt,
6550Sstevel@tonic-gate " thread=%lu, file=%s, line=%d, info=\"",
6560Sstevel@tonic-gate amip->thread, amip->file, amip->line);
6570Sstevel@tonic-gate buf_len=strlen(buf);
6580Sstevel@tonic-gate info_len=strlen(amip->info);
6590Sstevel@tonic-gate if (128 - buf_len - 3 < info_len)
6600Sstevel@tonic-gate {
6610Sstevel@tonic-gate memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
6620Sstevel@tonic-gate buf_len = 128 - 3;
6630Sstevel@tonic-gate }
6640Sstevel@tonic-gate else
6650Sstevel@tonic-gate {
6660Sstevel@tonic-gate BUF_strlcpy(buf + buf_len, amip->info,
6670Sstevel@tonic-gate sizeof buf - buf_len);
6680Sstevel@tonic-gate buf_len = strlen(buf);
6690Sstevel@tonic-gate }
6700Sstevel@tonic-gate BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n");
6710Sstevel@tonic-gate
6720Sstevel@tonic-gate BIO_puts(l->bio,buf);
6730Sstevel@tonic-gate
6740Sstevel@tonic-gate amip = amip->next;
6750Sstevel@tonic-gate }
6760Sstevel@tonic-gate while(amip && amip->thread == ti);
6770Sstevel@tonic-gate
6780Sstevel@tonic-gate #ifdef LEVITTE_DEBUG_MEM
6790Sstevel@tonic-gate if (amip)
6800Sstevel@tonic-gate {
6810Sstevel@tonic-gate fprintf(stderr, "Thread switch detected in backtrace!!!!\n");
6820Sstevel@tonic-gate abort();
6830Sstevel@tonic-gate }
6840Sstevel@tonic-gate #endif
6850Sstevel@tonic-gate }
6860Sstevel@tonic-gate
IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak,const MEM *,MEM_LEAK *)6870Sstevel@tonic-gate static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM *, MEM_LEAK *)
6880Sstevel@tonic-gate
6890Sstevel@tonic-gate void CRYPTO_mem_leaks(BIO *b)
6900Sstevel@tonic-gate {
6910Sstevel@tonic-gate MEM_LEAK ml;
6920Sstevel@tonic-gate
6930Sstevel@tonic-gate if (mh == NULL && amih == NULL)
6940Sstevel@tonic-gate return;
6950Sstevel@tonic-gate
6960Sstevel@tonic-gate MemCheck_off(); /* obtain MALLOC2 lock */
6970Sstevel@tonic-gate
6980Sstevel@tonic-gate ml.bio=b;
6990Sstevel@tonic-gate ml.bytes=0;
7000Sstevel@tonic-gate ml.chunks=0;
7010Sstevel@tonic-gate if (mh != NULL)
7020Sstevel@tonic-gate lh_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak),
7030Sstevel@tonic-gate (char *)&ml);
7040Sstevel@tonic-gate if (ml.chunks != 0)
7050Sstevel@tonic-gate {
7060Sstevel@tonic-gate BIO_printf(b,"%ld bytes leaked in %d chunks\n",
7070Sstevel@tonic-gate ml.bytes,ml.chunks);
7080Sstevel@tonic-gate }
7090Sstevel@tonic-gate else
7100Sstevel@tonic-gate {
7110Sstevel@tonic-gate /* Make sure that, if we found no leaks, memory-leak debugging itself
7120Sstevel@tonic-gate * does not introduce memory leaks (which might irritate
7130Sstevel@tonic-gate * external debugging tools).
7140Sstevel@tonic-gate * (When someone enables leak checking, but does not call
7150Sstevel@tonic-gate * this function, we declare it to be their fault.)
7160Sstevel@tonic-gate *
7170Sstevel@tonic-gate * XXX This should be in CRYPTO_mem_leaks_cb,
7180Sstevel@tonic-gate * and CRYPTO_mem_leaks should be implemented by
7190Sstevel@tonic-gate * using CRYPTO_mem_leaks_cb.
7200Sstevel@tonic-gate * (Also their should be a variant of lh_doall_arg
7210Sstevel@tonic-gate * that takes a function pointer instead of a void *;
7220Sstevel@tonic-gate * this would obviate the ugly and illegal
7230Sstevel@tonic-gate * void_fn_to_char kludge in CRYPTO_mem_leaks_cb.
7240Sstevel@tonic-gate * Otherwise the code police will come and get us.)
7250Sstevel@tonic-gate */
7260Sstevel@tonic-gate int old_mh_mode;
7270Sstevel@tonic-gate
7280Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
7290Sstevel@tonic-gate
7300Sstevel@tonic-gate /* avoid deadlock when lh_free() uses CRYPTO_dbg_free(),
7310Sstevel@tonic-gate * which uses CRYPTO_is_mem_check_on */
7320Sstevel@tonic-gate old_mh_mode = mh_mode;
7330Sstevel@tonic-gate mh_mode = CRYPTO_MEM_CHECK_OFF;
7340Sstevel@tonic-gate
7350Sstevel@tonic-gate if (mh != NULL)
7360Sstevel@tonic-gate {
7370Sstevel@tonic-gate lh_free(mh);
7380Sstevel@tonic-gate mh = NULL;
7390Sstevel@tonic-gate }
7400Sstevel@tonic-gate if (amih != NULL)
7410Sstevel@tonic-gate {
7420Sstevel@tonic-gate if (lh_num_items(amih) == 0)
7430Sstevel@tonic-gate {
7440Sstevel@tonic-gate lh_free(amih);
7450Sstevel@tonic-gate amih = NULL;
7460Sstevel@tonic-gate }
7470Sstevel@tonic-gate }
7480Sstevel@tonic-gate
7490Sstevel@tonic-gate mh_mode = old_mh_mode;
7500Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
7510Sstevel@tonic-gate }
7520Sstevel@tonic-gate MemCheck_on(); /* release MALLOC2 lock */
7530Sstevel@tonic-gate }
7540Sstevel@tonic-gate
7550Sstevel@tonic-gate #ifndef OPENSSL_NO_FP_API
CRYPTO_mem_leaks_fp(FILE * fp)7560Sstevel@tonic-gate void CRYPTO_mem_leaks_fp(FILE *fp)
7570Sstevel@tonic-gate {
7580Sstevel@tonic-gate BIO *b;
7590Sstevel@tonic-gate
7600Sstevel@tonic-gate if (mh == NULL) return;
7610Sstevel@tonic-gate /* Need to turn off memory checking when allocated BIOs ... especially
7620Sstevel@tonic-gate * as we're creating them at a time when we're trying to check we've not
7630Sstevel@tonic-gate * left anything un-free()'d!! */
7640Sstevel@tonic-gate MemCheck_off();
7650Sstevel@tonic-gate b = BIO_new(BIO_s_file());
7660Sstevel@tonic-gate MemCheck_on();
7670Sstevel@tonic-gate if(!b) return;
7680Sstevel@tonic-gate BIO_set_fp(b,fp,BIO_NOCLOSE);
7690Sstevel@tonic-gate CRYPTO_mem_leaks(b);
7700Sstevel@tonic-gate BIO_free(b);
7710Sstevel@tonic-gate }
7720Sstevel@tonic-gate #endif
7730Sstevel@tonic-gate
7740Sstevel@tonic-gate
7750Sstevel@tonic-gate
7760Sstevel@tonic-gate /* FIXME: We really don't allow much to the callback. For example, it has
7770Sstevel@tonic-gate no chance of reaching the info stack for the item it processes. Should
7780Sstevel@tonic-gate it really be this way? -- Richard Levitte */
7790Sstevel@tonic-gate /* NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside crypto.h
7800Sstevel@tonic-gate * If this code is restructured, remove the callback type if it is no longer
7810Sstevel@tonic-gate * needed. -- Geoff Thorpe */
cb_leak(const MEM * m,CRYPTO_MEM_LEAK_CB ** cb)7820Sstevel@tonic-gate static void cb_leak(const MEM *m, CRYPTO_MEM_LEAK_CB **cb)
7830Sstevel@tonic-gate {
7840Sstevel@tonic-gate (**cb)(m->order,m->file,m->line,m->num,m->addr);
7850Sstevel@tonic-gate }
7860Sstevel@tonic-gate
IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak,const MEM *,CRYPTO_MEM_LEAK_CB **)7870Sstevel@tonic-gate static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM *, CRYPTO_MEM_LEAK_CB **)
7880Sstevel@tonic-gate
7890Sstevel@tonic-gate void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
7900Sstevel@tonic-gate {
7910Sstevel@tonic-gate if (mh == NULL) return;
7920Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
7930Sstevel@tonic-gate lh_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), &cb);
7940Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
7950Sstevel@tonic-gate }
796