aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2017-04-19 12:51:06 +0200
committerRichard Levitte <levitte@openssl.org>2017-04-24 18:09:01 +0200
commit20626cfd5870e80838010cddf99dd6297eceaa26 (patch)
tree2e11e89a048f99d331b8ea1e7779063c4f134ac6
parent331058180aba047ac6b25da781eebc08b7267d2f (diff)
downloadopenssl-20626cfd5870e80838010cddf99dd6297eceaa26.tar.gz
Add CRYPTO_mem_leaks_cb
Reviewed-by: Rich Salz <rsalz@openssl.org> (Merged from https://github.com/openssl/openssl/pull/3243)
-rw-r--r--crypto/mem_dbg.c43
-rw-r--r--doc/man3/OPENSSL_malloc.pod9
-rw-r--r--include/openssl/crypto.h2
-rw-r--r--util/libcrypto.num1
4 files changed, 41 insertions, 14 deletions
diff --git a/crypto/mem_dbg.c b/crypto/mem_dbg.c
index dc3f8ff571..4c4e7d3f12 100644
--- a/crypto/mem_dbg.c
+++ b/crypto/mem_dbg.c
@@ -443,7 +443,8 @@ void CRYPTO_mem_debug_realloc(void *addr1, void *addr2, size_t num,
}
typedef struct mem_leak_st {
- BIO *bio;
+ int (*print_cb) (const char *str, size_t len, void *u);
+ void *print_cb_arg;
int chunks;
long bytes;
} MEM_LEAK;
@@ -486,7 +487,7 @@ static void print_leak(const MEM *m, MEM_LEAK *l)
m->num, m->addr);
bufp += strlen(bufp);
- BIO_puts(l->bio, buf);
+ l->print_cb(buf, strlen(buf), l->print_cb_arg);
l->chunks++;
l->bytes += m->num;
@@ -520,7 +521,7 @@ static void print_leak(const MEM *m, MEM_LEAK *l)
}
BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n");
- BIO_puts(l->bio, buf);
+ l->print_cb(buf, strlen(buf), l->print_cb_arg);
amip = amip->next;
}
@@ -541,16 +542,11 @@ static void print_leak(const MEM *m, MEM_LEAK *l)
IMPLEMENT_LHASH_DOALL_ARG_CONST(MEM, MEM_LEAK);
-int CRYPTO_mem_leaks(BIO *b)
+int CRYPTO_mem_leaks_cb(int (*cb) (const char *str, size_t len, void *u),
+ void *u)
{
MEM_LEAK ml;
- /*
- * OPENSSL_cleanup() will free the ex_data locks so we can't have any
- * ex_data hanging around
- */
- bio_free_ex_data(b);
-
/* Ensure all resources are released */
OPENSSL_cleanup();
@@ -559,14 +555,19 @@ int CRYPTO_mem_leaks(BIO *b)
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
- ml.bio = b;
+ ml.print_cb = cb;
+ ml.print_cb_arg = u;
ml.bytes = 0;
ml.chunks = 0;
if (mh != NULL)
lh_MEM_doall_MEM_LEAK(mh, print_leak, &ml);
if (ml.chunks != 0) {
- BIO_printf(b, "%ld bytes leaked in %d chunks\n", ml.bytes, ml.chunks);
+ char buf[256];
+
+ BIO_snprintf(buf, sizeof(buf), "%ld bytes leaked in %d chunks\n",
+ ml.bytes, ml.chunks);
+ cb(buf, strlen(buf), u);
} else {
/*
* Make sure that, if we found no leaks, memory-leak debugging itself
@@ -603,6 +604,22 @@ int CRYPTO_mem_leaks(BIO *b)
return ml.chunks == 0 ? 1 : 0;
}
+static int print_bio(const char *str, size_t len, void *b)
+{
+ return BIO_write((BIO *)b, str, len);
+}
+
+int CRYPTO_mem_leaks(BIO *b)
+{
+ /*
+ * OPENSSL_cleanup() will free the ex_data locks so we can't have any
+ * ex_data hanging around
+ */
+ bio_free_ex_data(b);
+
+ return CRYPTO_mem_leaks_cb(print_bio, b);
+}
+
# ifndef OPENSSL_NO_STDIO
int CRYPTO_mem_leaks_fp(FILE *fp)
{
@@ -620,7 +637,7 @@ int CRYPTO_mem_leaks_fp(FILE *fp)
if (b == NULL)
return -1;
BIO_set_fp(b, fp, BIO_NOCLOSE);
- ret = CRYPTO_mem_leaks(b);
+ ret = CRYPTO_mem_leaks_cb(print_bio, b);
BIO_free(b);
return ret;
}
diff --git a/doc/man3/OPENSSL_malloc.pod b/doc/man3/OPENSSL_malloc.pod
index 2914143bbc..afcdb55606 100644
--- a/doc/man3/OPENSSL_malloc.pod
+++ b/doc/man3/OPENSSL_malloc.pod
@@ -15,7 +15,7 @@ CRYPTO_mem_debug_push, CRYPTO_mem_debug_pop,
CRYPTO_clear_realloc, CRYPTO_clear_free,
CRYPTO_get_mem_functions, CRYPTO_set_mem_functions,
CRYPTO_set_mem_debug, CRYPTO_mem_ctrl,
-CRYPTO_mem_leaks, CRYPTO_mem_leaks_fp
+CRYPTO_mem_leaks, CRYPTO_mem_leaks_fp, CRYPTO_mem_leaks_cb,
OPENSSL_MALLOC_FAILURES,
OPENSSL_MALLOC_FD
- Memory allocation functions
@@ -76,6 +76,8 @@ OPENSSL_MALLOC_FD
void CRYPTO_mem_leaks(BIO *b);
void CRYPTO_mem_leaks_fp(FILE *fp);
+ void CRYPTO_mem_leaks_cb(int (*cb)(const char *str, size_t len, void *u),
+ void *u);
=head1 DESCRIPTION
@@ -190,6 +192,11 @@ CRYPTO_mem_leaks_fp() will report all "leaked" memory, writing it
to the specified BIO B<b> or FILE B<fp>. These functions return 1 if
there are no leaks, 0 if there are leaks and -1 if an error occurred.
+CRYPTO_mem_leaks_cb() does the same as CRYPTO_mem_leaks(), but instead
+of writing to a given BIO, the callback function is called for each
+output string with the string, length, and userdata B<u> as the callback
+parameters.
+
=head1 RETURN VALUES
OPENSSL_malloc_init(), OPENSSL_free(), OPENSSL_clear_free()
diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h
index a8b8dc1696..42e888d240 100644
--- a/include/openssl/crypto.h
+++ b/include/openssl/crypto.h
@@ -314,6 +314,8 @@ void CRYPTO_mem_debug_realloc(void *addr1, void *addr2, size_t num, int flag,
void CRYPTO_mem_debug_free(void *addr, int flag,
const char *file, int line);
+int CRYPTO_mem_leaks_cb(int (*cb) (const char *str, size_t len, void *u),
+ void *u);
# ifndef OPENSSL_NO_STDIO
int CRYPTO_mem_leaks_fp(FILE *);
# endif
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 1a19273eab..725e075403 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4270,3 +4270,4 @@ UINT32_it 4214 1_1_0f EXIST:!EXPORT_VAR_AS_FUNCTIO
UINT32_it 4214 1_1_0f EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
ZINT64_it 4215 1_1_0f EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
ZINT64_it 4215 1_1_0f EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
+CRYPTO_mem_leaks_cb 4216 1_1_1 EXIST::FUNCTION:CRYPTO_MDEBUG