aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/err
diff options
context:
space:
mode:
authorBodo Möller <bodo@openssl.org>2000-04-29 23:58:05 +0000
committerBodo Möller <bodo@openssl.org>2000-04-29 23:58:05 +0000
commitdcba2534fa9fb9e9a36be554ece9cb58ffc76f41 (patch)
tree2c5ca5b2c8abe87377f54bebd3073cbda9d12cc6 /crypto/err
parentb222eb644385699b2a17b24d68696f2a67935ffd (diff)
downloadopenssl-dcba2534fa9fb9e9a36be554ece9cb58ffc76f41.tar.gz
Avoid leaking memory in thread_hash (and enable memory leak detection
for it).
Diffstat (limited to 'crypto/err')
-rw-r--r--crypto/err/err.c52
-rw-r--r--crypto/err/err.h10
2 files changed, 36 insertions, 26 deletions
diff --git a/crypto/err/err.c b/crypto/err/err.c
index a0135579f0..c8dba5284b 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -116,9 +116,8 @@
#include <openssl/crypto.h>
#include "cryptlib.h"
#include <openssl/buffer.h>
-#include <openssl/err.h>
-#include <openssl/crypto.h>
#include <openssl/bio.h>
+#include <openssl/err.h>
static LHASH *error_hash=NULL;
@@ -545,6 +544,7 @@ LHASH *ERR_get_string_table(void)
return(error_hash);
}
+/* not thread-safe */
LHASH *ERR_get_err_state_table(void)
{
return(thread_hash);
@@ -652,6 +652,12 @@ void ERR_remove_state(unsigned long pid)
tmp.pid=pid;
CRYPTO_w_lock(CRYPTO_LOCK_ERR);
p=(ERR_STATE *)lh_delete(thread_hash,&tmp);
+ if (lh_num_items(thread_hash) == 0)
+ {
+ /* make sure we don't leak memory */
+ lh_free(thread_hash);
+ thread_hash = NULL;
+ }
CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
if (p != NULL) ERR_STATE_free(p);
@@ -661,33 +667,19 @@ ERR_STATE *ERR_get_state(void)
{
static ERR_STATE fallback;
ERR_STATE *ret=NULL,tmp,*tmpp;
+ int thread_state_exists;
int i;
unsigned long pid;
pid=(unsigned long)CRYPTO_thread_id();
CRYPTO_r_lock(CRYPTO_LOCK_ERR);
- if (thread_hash == NULL)
- {
- CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
- CRYPTO_w_lock(CRYPTO_LOCK_ERR);
- if (thread_hash == NULL)
- {
- MemCheck_off();
- thread_hash=lh_new(pid_hash,pid_cmp);
- MemCheck_on();
- CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
- if (thread_hash == NULL) return(&fallback);
- }
- else
- CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
- }
- else
+ if (thread_hash != NULL)
{
tmp.pid=pid;
ret=(ERR_STATE *)lh_retrieve(thread_hash,&tmp);
- CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
}
+ CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
/* ret == the error state, if NULL, make a new one */
if (ret == NULL)
@@ -702,9 +694,29 @@ ERR_STATE *ERR_get_state(void)
ret->err_data[i]=NULL;
ret->err_data_flags[i]=0;
}
+
CRYPTO_w_lock(CRYPTO_LOCK_ERR);
- tmpp=(ERR_STATE *)lh_insert(thread_hash,ret);
+
+ /* no entry yet in thread_hash for current thread -
+ * thus, it may have changed since we last looked at it */
+ if (thread_hash == NULL)
+ thread_hash = lh_new(pid_hash, pid_cmp);
+ if (thread_hash == NULL)
+ thread_state_exists = 0; /* allocation error */
+ else
+ {
+ tmpp=(ERR_STATE *)lh_insert(thread_hash,ret);
+ thread_state_exists = 1;
+ }
+
CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+
+ if (!thread_state_exists)
+ {
+ ERR_STATE_free(ret); /* could not insert it */
+ return(&fallback);
+ }
+
if (tmpp != NULL) /* old entry - should not happen */
{
ERR_STATE_free(tmpp);
diff --git a/crypto/err/err.h b/crypto/err/err.h
index e3984bb7a4..eb62af2af8 100644
--- a/crypto/err/err.h
+++ b/crypto/err/err.h
@@ -253,14 +253,12 @@ void ERR_remove_state(unsigned long pid); /* if zero we look it up */
ERR_STATE *ERR_get_state(void);
#ifdef HEADER_LHASH_H
-LHASH *ERR_get_string_table(void );
-LHASH *ERR_get_err_state_table(void );
-#else
-char *ERR_get_string_table(void );
-char *ERR_get_err_state_table(void );
+LHASH *ERR_get_string_table(void);
+LHASH *ERR_get_err_state_table(void); /* even less thread-safe than
+ * ERR_get_string_table :-) */
#endif
-int ERR_get_next_error_library(void );
+int ERR_get_next_error_library(void);
#ifdef __cplusplus
}