Avoid leaking memory in thread_hash (and enable memory leak detection
for it).
This commit is contained in:
parent
b222eb6443
commit
dcba2534fa
6
CHANGES
6
CHANGES
@ -4,6 +4,12 @@
|
|||||||
|
|
||||||
Changes between 0.9.5a and 0.9.6 [xx XXX 2000]
|
Changes between 0.9.5a and 0.9.6 [xx XXX 2000]
|
||||||
|
|
||||||
|
*) Avoid 'thread_hash' memory leak in crypto/err/err.c by freeing
|
||||||
|
it in ERR_remove_state if appropriate, and change ERR_get_state
|
||||||
|
accordingly to avoid race conditions (this is necessary because
|
||||||
|
thread_hash is no longer constant once set).
|
||||||
|
[Bodo Moeller]
|
||||||
|
|
||||||
*) Bugfix for linux-elf makefile.one.
|
*) Bugfix for linux-elf makefile.one.
|
||||||
[Ulf Möller]
|
[Ulf Möller]
|
||||||
|
|
||||||
|
@ -116,9 +116,8 @@
|
|||||||
#include <openssl/crypto.h>
|
#include <openssl/crypto.h>
|
||||||
#include "cryptlib.h"
|
#include "cryptlib.h"
|
||||||
#include <openssl/buffer.h>
|
#include <openssl/buffer.h>
|
||||||
#include <openssl/err.h>
|
|
||||||
#include <openssl/crypto.h>
|
|
||||||
#include <openssl/bio.h>
|
#include <openssl/bio.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
|
|
||||||
static LHASH *error_hash=NULL;
|
static LHASH *error_hash=NULL;
|
||||||
@ -545,6 +544,7 @@ LHASH *ERR_get_string_table(void)
|
|||||||
return(error_hash);
|
return(error_hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* not thread-safe */
|
||||||
LHASH *ERR_get_err_state_table(void)
|
LHASH *ERR_get_err_state_table(void)
|
||||||
{
|
{
|
||||||
return(thread_hash);
|
return(thread_hash);
|
||||||
@ -652,6 +652,12 @@ void ERR_remove_state(unsigned long pid)
|
|||||||
tmp.pid=pid;
|
tmp.pid=pid;
|
||||||
CRYPTO_w_lock(CRYPTO_LOCK_ERR);
|
CRYPTO_w_lock(CRYPTO_LOCK_ERR);
|
||||||
p=(ERR_STATE *)lh_delete(thread_hash,&tmp);
|
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);
|
CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
|
||||||
|
|
||||||
if (p != NULL) ERR_STATE_free(p);
|
if (p != NULL) ERR_STATE_free(p);
|
||||||
@ -661,33 +667,19 @@ ERR_STATE *ERR_get_state(void)
|
|||||||
{
|
{
|
||||||
static ERR_STATE fallback;
|
static ERR_STATE fallback;
|
||||||
ERR_STATE *ret=NULL,tmp,*tmpp;
|
ERR_STATE *ret=NULL,tmp,*tmpp;
|
||||||
|
int thread_state_exists;
|
||||||
int i;
|
int i;
|
||||||
unsigned long pid;
|
unsigned long pid;
|
||||||
|
|
||||||
pid=(unsigned long)CRYPTO_thread_id();
|
pid=(unsigned long)CRYPTO_thread_id();
|
||||||
|
|
||||||
CRYPTO_r_lock(CRYPTO_LOCK_ERR);
|
CRYPTO_r_lock(CRYPTO_LOCK_ERR);
|
||||||
if (thread_hash == NULL)
|
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
|
|
||||||
{
|
{
|
||||||
tmp.pid=pid;
|
tmp.pid=pid;
|
||||||
ret=(ERR_STATE *)lh_retrieve(thread_hash,&tmp);
|
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 */
|
/* ret == the error state, if NULL, make a new one */
|
||||||
if (ret == NULL)
|
if (ret == NULL)
|
||||||
@ -702,9 +694,29 @@ ERR_STATE *ERR_get_state(void)
|
|||||||
ret->err_data[i]=NULL;
|
ret->err_data[i]=NULL;
|
||||||
ret->err_data_flags[i]=0;
|
ret->err_data_flags[i]=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CRYPTO_w_lock(CRYPTO_LOCK_ERR);
|
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);
|
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 */
|
if (tmpp != NULL) /* old entry - should not happen */
|
||||||
{
|
{
|
||||||
ERR_STATE_free(tmpp);
|
ERR_STATE_free(tmpp);
|
||||||
|
@ -253,14 +253,12 @@ void ERR_remove_state(unsigned long pid); /* if zero we look it up */
|
|||||||
ERR_STATE *ERR_get_state(void);
|
ERR_STATE *ERR_get_state(void);
|
||||||
|
|
||||||
#ifdef HEADER_LHASH_H
|
#ifdef HEADER_LHASH_H
|
||||||
LHASH *ERR_get_string_table(void );
|
LHASH *ERR_get_string_table(void);
|
||||||
LHASH *ERR_get_err_state_table(void );
|
LHASH *ERR_get_err_state_table(void); /* even less thread-safe than
|
||||||
#else
|
* ERR_get_string_table :-) */
|
||||||
char *ERR_get_string_table(void );
|
|
||||||
char *ERR_get_err_state_table(void );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int ERR_get_next_error_library(void );
|
int ERR_get_next_error_library(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user