-/* crypto/mem_dbg.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
#include <openssl/buffer.h>
#include <openssl/bio.h>
#include <openssl/lhash.h>
-#if defined(CRYPTO_MDEBUG_BACKTRACE) && defined(__GNUC__)
+
+#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
# include <execinfo.h>
#endif
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
static unsigned long order = 0; /* number of memory requests */
-DECLARE_LHASH_OF(MEM);
-static LHASH_OF(MEM) *mh = NULL; /* hash-table of memory requests (address as
- * key); access requires MALLOC2 lock */
-
/*-
* For application-defined information (static C-string `info')
* to be displayed in memory leak list.
* OPENSSL_mem_debug_push("...") to push an entry,
* OPENSSL_mem_debug_pop() to pop an entry,
*/
-typedef struct app_mem_info_st {
+struct app_mem_info_st {
CRYPTO_THREADID threadid;
const char *file;
int line;
const char *info;
struct app_mem_info_st *next; /* tail of thread's stack */
int references;
-} APP_INFO;
+};
/*
* hash-table with those app_mem_info_st's that are at the
* top of their thread's stack (with `thread' as key); access requires
* MALLOC2 lock
*/
-DECLARE_LHASH_OF(APP_INFO);
static LHASH_OF(APP_INFO) *amih = NULL;
/* memory-block description */
-typedef struct mem_st {
+struct mem_st {
void *addr;
int num;
const char *file;
unsigned long order;
time_t time;
APP_INFO *app_info;
-#if defined(CRYPTO_MDEBUG_BACKTRACE) && defined(__GNUC__)
+#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
void *array[30];
size_t array_siz;
#endif
-} MEM;
+};
+
+static LHASH_OF(MEM) *mh = NULL; /* hash-table of memory requests (address as
+ * key); access requires MALLOC2 lock */
/* num_disable > 0 iff mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE) */
static unsigned int num_disable = 0;
#endif
}
-static IMPLEMENT_LHASH_COMP_FN(mem, MEM)
-
static unsigned long mem_hash(const MEM *a)
{
size_t ret;
return (ret);
}
-static IMPLEMENT_LHASH_HASH_FN(mem, MEM)
-
-/* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */
-static int app_info_cmp(const void *a_void, const void *b_void)
+static int app_info_cmp(const APP_INFO *a, const APP_INFO *b)
{
- return CRYPTO_THREADID_cmp(&((const APP_INFO *)a_void)->threadid,
- &((const APP_INFO *)b_void)->threadid);
+ return CRYPTO_THREADID_cmp(&a->threadid, &b->threadid);
}
-static IMPLEMENT_LHASH_COMP_FN(app_info, APP_INFO)
-
static unsigned long app_info_hash(const APP_INFO *a)
{
unsigned long ret;
return (ret);
}
-static IMPLEMENT_LHASH_HASH_FN(app_info, APP_INFO)
-
-static APP_INFO *pop_info(void)
+/* returns 1 if there was an info to pop, 0 if the stack was empty. */
+static int pop_info(void)
{
APP_INFO tmp;
- APP_INFO *ret = NULL;
+ APP_INFO *current = NULL;
if (amih != NULL) {
CRYPTO_THREADID_current(&tmp.threadid);
- if ((ret = lh_APP_INFO_delete(amih, &tmp)) != NULL) {
- APP_INFO *next = ret->next;
+ if ((current = lh_APP_INFO_delete(amih, &tmp)) != NULL) {
+ APP_INFO *next = current->next;
if (next != NULL) {
next->references++;
(void)lh_APP_INFO_insert(amih, next);
}
- if (--(ret->references) <= 0) {
- ret->next = NULL;
+ if (--(current->references) <= 0) {
+ current->next = NULL;
if (next != NULL)
next->references--;
- OPENSSL_free(ret);
+ OPENSSL_free(current);
}
+ return 1;
}
}
- return (ret);
+ return 0;
}
int CRYPTO_mem_debug_push(const char *info, const char *file, int line)
if ((ami = OPENSSL_malloc(sizeof(*ami))) == NULL)
goto err;
if (amih == NULL) {
- if ((amih = lh_APP_INFO_new()) == NULL) {
+ if ((amih = lh_APP_INFO_new(app_info_hash, app_info_cmp)) == NULL) {
OPENSSL_free(ami);
goto err;
}
if (mem_check_on()) {
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
- ret = (pop_info() != NULL);
+ ret = pop_info();
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
}
return (ret);
return;
}
if (mh == NULL) {
- if ((mh = lh_MEM_new()) == NULL) {
+ if ((mh = lh_MEM_new(mem_hash, mem_cmp)) == NULL) {
OPENSSL_free(addr);
OPENSSL_free(m);
addr = NULL;
m->order = order;
}
m->order = order++;
-# if defined(CRYPTO_MDEBUG_BACKTRACE) && defined(__GNUC__)
+# ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
m->array_siz = backtrace(m->array, OSSL_NELEM(m->array));
# endif
m->time = time(NULL);
if (mp != NULL) {
mp->addr = addr2;
mp->num = num;
-#if defined(CRYPTO_MDEBUG_BACKTRACE) && defined(__GNUC__)
+#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
mp->array_siz = backtrace(mp->array, OSSL_NELEM(mp->array));
#endif
(void)lh_MEM_insert(mh, mp);
long bytes;
} MEM_LEAK;
-static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l)
+static void print_leak(const MEM *m, MEM_LEAK *l)
{
char buf[1024];
char *bufp = buf;
while (amip && !CRYPTO_THREADID_cmp(&amip->threadid, &ti));
}
-#if defined(CRYPTO_MDEBUG_BACKTRACE) && defined(__GNUC__)
+#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
{
size_t i;
char **strings = backtrace_symbols(m->array, m->array_siz);
#endif
}
-static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM, MEM_LEAK)
+IMPLEMENT_LHASH_DOALL_ARG_CONST(MEM, MEM_LEAK);
-void CRYPTO_mem_leaks(BIO *b)
+int CRYPTO_mem_leaks(BIO *b)
{
MEM_LEAK ml;
if (mh == NULL && amih == NULL)
- return;
+ return 1;
+
+ /* Ensure all resources are released */
+ OPENSSL_cleanup();
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
ml.chunks = 0;
ml.seen = 0;
if (mh != NULL)
- lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak), MEM_LEAK, &ml);
+ lh_MEM_doall_MEM_LEAK(mh, print_leak, &ml);
/* Don't count the BIO that was passed in as a "leak" */
if (ml.seen && ml.chunks >= 1 && ml.bytes >= (int)sizeof (*b)) {
ml.chunks--;
}
if (ml.chunks != 0) {
BIO_printf(b, "%ld bytes leaked in %d chunks\n", ml.bytes, ml.chunks);
- abort();
} else {
/*
* Make sure that, if we found no leaks, memory-leak debugging itself
CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
}
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
+ return ml.chunks == 0 ? 1 : 0;
}
# ifndef OPENSSL_NO_STDIO
-void CRYPTO_mem_leaks_fp(FILE *fp)
+int CRYPTO_mem_leaks_fp(FILE *fp)
{
BIO *b;
+ int ret;
- if (mh == NULL)
- return;
+ if (mh == NULL && amih == NULL)
+ return 1;
/*
* Need to turn off memory checking when allocated BIOs ... especially as
* we're creating them at a time when we're trying to check we've not
b = BIO_new(BIO_s_file());
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
if (b == NULL)
- return;
+ return -1;
BIO_set_fp(b, fp, BIO_NOCLOSE);
- CRYPTO_mem_leaks(b);
+ ret = CRYPTO_mem_leaks(b);
BIO_free(b);
+ return ret;
}
# endif