@ -106,11 +106,15 @@
* ( eay @ cryptsoft . com ) . This product includes software written by Tim
* Hudson ( tjh @ cryptsoft . com ) . */
// Ensure we can't call OPENSSL_malloc circularly.
# define _BORINGSSL_PROHIBIT_OPENSSL_MALLOC
# include <openssl/err.h>
# include <assert.h>
# include <errno.h>
# include <inttypes.h>
# include <limits.h>
# include <stdarg.h>
# include <string.h>
# if defined(OPENSSL_WINDOWS)
@ -129,8 +133,8 @@ OPENSSL_MSVC_PRAGMA(warning(pop))
struct err_error_st {
// file contains the filename where the error occurred.
const char * file ;
// data contains a NUL-terminated string with optional data. It must be fre ed
// with |OPENSSL_free|.
// data contains a NUL-terminated string with optional data. It is allocat ed
// with system |malloc| and must be freed with |free| (not |OPENSSL_free|)
char * data ;
// packed contains the error library and reason, as packed by ERR_PACK.
uint32_t packed ;
@ -162,7 +166,7 @@ extern const char kOpenSSLReasonStringData[];
// err_clear clears the given queued error.
static void err_clear ( struct err_error_st * error ) {
OPENSSL_ free( error - > data ) ;
free ( error - > data ) ;
OPENSSL_memset ( error , 0 , sizeof ( struct err_error_st ) ) ;
}
@ -170,12 +174,19 @@ static void err_copy(struct err_error_st *dst, const struct err_error_st *src) {
err_clear ( dst ) ;
dst - > file = src - > file ;
if ( src - > data ! = NULL ) {
dst - > data = OPENSSL_strdup ( src - > data ) ;
// Disable deprecated functions on msvc so it doesn't complain about strdup.
OPENSSL_MSVC_PRAGMA ( warning ( push ) )
OPENSSL_MSVC_PRAGMA ( warning ( disable : 4996 ) )
// We can't use OPENSSL_strdup because we don't want to call OPENSSL_malloc,
// which can affect the error stack.
dst - > data = strdup ( src - > data ) ;
OPENSSL_MSVC_PRAGMA ( warning ( pop ) )
}
dst - > packed = src - > packed ;
dst - > line = src - > line ;
}
// global_next_library contains the next custom library value to return.
static int global_next_library = ERR_NUM_LIBS ;
@ -194,15 +205,15 @@ static void err_state_free(void *statep) {
for ( unsigned i = 0 ; i < ERR_NUM_ERRORS ; i + + ) {
err_clear ( & state - > errors [ i ] ) ;
}
OPENSSL_ free( state - > to_free ) ;
OPENSSL_ free( state ) ;
free ( state - > to_free ) ;
free ( state ) ;
}
// err_get_state gets the ERR_STATE object for the current thread.
static ERR_STATE * err_get_state ( void ) {
ERR_STATE * state = CRYPTO_get_thread_local ( OPENSSL_THREAD_LOCAL_ERR ) ;
if ( state = = NULL ) {
state = OPENSSL_ malloc( sizeof ( ERR_STATE ) ) ;
state = malloc ( sizeof ( ERR_STATE ) ) ;
if ( state = = NULL ) {
return NULL ;
}
@ -258,7 +269,10 @@ static uint32_t get_error_values(int inc, int top, const char **file, int *line,
} else {
* data = error - > data ;
if ( flags ! = NULL ) {
* flags = ERR_FLAG_STRING ;
// Without |ERR_FLAG_MALLOCED|, rust-openssl assumes the string has a
// static lifetime. In both cases, we retain ownership of the string,
// and the caller is not expected to free it.
* flags = ERR_FLAG_STRING | ERR_FLAG_MALLOCED ;
}
// If this error is being removed, take ownership of data from
// the error. The semantics are such that the caller doesn't
@ -267,7 +281,7 @@ static uint32_t get_error_values(int inc, int top, const char **file, int *line,
// error queue.
if ( inc ) {
if ( error - > data ! = NULL ) {
OPENSSL_ free( state - > to_free ) ;
free ( state - > to_free ) ;
state - > to_free = error - > data ;
}
error - > data = NULL ;
@ -335,7 +349,7 @@ void ERR_clear_error(void) {
for ( i = 0 ; i < ERR_NUM_ERRORS ; i + + ) {
err_clear ( & state - > errors [ i ] ) ;
}
OPENSSL_ free( state - > to_free ) ;
free ( state - > to_free ) ;
state - > to_free = NULL ;
state - > top = state - > bottom = 0 ;
@ -629,13 +643,13 @@ static void err_set_error_data(char *data) {
struct err_error_st * error ;
if ( state = = NULL | | state - > top = = state - > bottom ) {
OPENSSL_ free( data ) ;
free ( data ) ;
return ;
}
error = & state - > errors [ state - > top ] ;
OPENSSL_ free( error - > data ) ;
free ( error - > data ) ;
error - > data = data ;
}
@ -672,48 +686,42 @@ void ERR_put_error(int library, int unused, int reason, const char *file,
// concatenates them and sets the result as the data on the most recent
// error.
static void err_add_error_vdata ( unsigned num , va_list args ) {
size_t alloced , new_len , len = 0 , substr_len ;
char * buf ;
size_t total_size = 0 ;
const char * substr ;
unsigned i ;
char * buf ;
alloced = 80 ;
buf = OPENSSL_malloc ( alloced + 1 ) ;
if ( buf = = NULL ) {
va_list args_copy ;
va_copy ( args_copy , args ) ;
for ( size_t i = 0 ; i < num ; i + + ) {
substr = va_arg ( args_copy , const char * ) ;
if ( substr = = NULL ) {
continue ;
}
size_t substr_len = strlen ( substr ) ;
if ( SIZE_MAX - total_size < substr_len ) {
return ; // Would overflow.
}
total_size + = substr_len ;
}
va_end ( args_copy ) ;
if ( total_size = = SIZE_MAX ) {
return ; // Would overflow.
}
total_size + = 1 ; // NUL terminator.
if ( ( buf = malloc ( total_size ) ) = = NULL ) {
return ;
}
for ( i = 0 ; i < num ; i + + ) {
buf [ 0 ] = ' \0 ' ;
for ( size_t i = 0 ; i < num ; i + + ) {
substr = va_arg ( args , const char * ) ;
if ( substr = = NULL ) {
continue ;
}
substr_len = strlen ( substr ) ;
new_len = len + substr_len ;
if ( new_len > alloced ) {
char * new_buf ;
if ( alloced + 20 + 1 < alloced ) {
// overflow.
OPENSSL_free ( buf ) ;
return ;
}
alloced = new_len + 20 ;
new_buf = OPENSSL_realloc ( buf , alloced + 1 ) ;
if ( new_buf = = NULL ) {
OPENSSL_free ( buf ) ;
return ;
}
buf = new_buf ;
if ( OPENSSL_strlcat ( buf , substr , total_size ) > = total_size ) {
assert ( 0 ) ; // should not be possible.
}
OPENSSL_memcpy ( buf + len , substr , substr_len ) ;
len = new_len ;
}
buf [ len ] = 0 ;
va_end ( args ) ;
err_set_error_data ( buf ) ;
}
@ -725,21 +733,13 @@ void ERR_add_error_data(unsigned count, ...) {
}
void ERR_add_error_dataf ( const char * format , . . . ) {
char * buf = NULL ;
va_list ap ;
char * buf ;
static const unsigned buf_len = 256 ;
// A fixed-size buffer is used because va_copy (which would be needed in
// order to call vsnprintf twice and measure the buffer) wasn't defined until
// C99.
buf = OPENSSL_malloc ( buf_len + 1 ) ;
if ( buf = = NULL ) {
va_start ( ap , format ) ;
if ( OPENSSL_vasprintf_internal ( & buf , format , ap , /*system_malloc=*/ 1 ) = = - 1 ) {
return ;
}
va_start ( ap , format ) ;
BIO_vsnprintf ( buf , buf_len , format , ap ) ;
buf [ buf_len ] = 0 ;
va_end ( ap ) ;
err_set_error_data ( buf ) ;
@ -751,13 +751,20 @@ void ERR_set_error_data(char *data, int flags) {
assert ( 0 ) ;
return ;
}
// Disable deprecated functions on msvc so it doesn't complain about strdup.
OPENSSL_MSVC_PRAGMA ( warning ( push ) )
OPENSSL_MSVC_PRAGMA ( warning ( disable : 4996 ) )
// We can not use OPENSSL_strdup because we don't want to call OPENSSL_malloc,
// which can affect the error stack.
char * copy = strdup ( data ) ;
OPENSSL_MSVC_PRAGMA ( warning ( pop ) )
if ( copy ! = NULL ) {
err_set_error_data ( copy ) ;
}
if ( flags & ERR_FLAG_MALLOCED ) {
err_set_error_data ( data ) ;
} else {
char * copy = OPENSSL_strdup ( data ) ;
if ( copy ! = NULL ) {
err_set_error_data ( copy ) ;
}
// We can not take ownership of |data| directly because it is allocated with
// |OPENSSL_malloc| and we will free it with system |free| later.
OPENSSL_free ( data ) ;
}
}
@ -819,8 +826,8 @@ void ERR_SAVE_STATE_free(ERR_SAVE_STATE *state) {
for ( size_t i = 0 ; i < state - > num_errors ; i + + ) {
err_clear ( & state - > errors [ i ] ) ;
}
OPENSSL_ free( state - > errors ) ;
OPENSSL_ free( state ) ;
free ( state - > errors ) ;
free ( state ) ;
}
ERR_SAVE_STATE * ERR_save_state ( void ) {
@ -829,7 +836,7 @@ ERR_SAVE_STATE *ERR_save_state(void) {
return NULL ;
}
ERR_SAVE_STATE * ret = OPENSSL_ malloc( sizeof ( ERR_SAVE_STATE ) ) ;
ERR_SAVE_STATE * ret = malloc ( sizeof ( ERR_SAVE_STATE ) ) ;
if ( ret = = NULL ) {
return NULL ;
}
@ -839,9 +846,9 @@ ERR_SAVE_STATE *ERR_save_state(void) {
? state - > top - state - > bottom
: ERR_NUM_ERRORS + state - > top - state - > bottom ;
assert ( num_errors < ERR_NUM_ERRORS ) ;
ret - > errors = OPENSSL_ malloc( num_errors * sizeof ( struct err_error_st ) ) ;
ret - > errors = malloc ( num_errors * sizeof ( struct err_error_st ) ) ;
if ( ret - > errors = = NULL ) {
OPENSSL_ free( ret ) ;
free ( ret ) ;
return NULL ;
}
OPENSSL_memset ( ret - > errors , 0 , num_errors * sizeof ( struct err_error_st ) ) ;