Add malloc failure tests.
This commit fixes a number of crashes caused by malloc failures. They were found using the -malloc-test=0 option to runner.go which runs tests many times, causing a different allocation call to fail in each case. (This test only works on Linux and only looks for crashes caused by allocation failures, not memory leaks or other errors.) This is not the complete set of crashes! More can be found by collecting core dumps from running with -malloc-test=0. Change-Id: Ia61d19f51e373bccb7bc604642c51e043a74bd83 Reviewed-on: https://boringssl-review.googlesource.com/2320 Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
parent
deb5284138
commit
69a01608f3
@ -126,7 +126,13 @@ static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it)
|
||||
{
|
||||
BIGNUM *bn;
|
||||
if(!*pval) bn_new(pval, it);
|
||||
if(!*pval)
|
||||
{
|
||||
if (!bn_new(pval, it))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
bn = (BIGNUM *)*pval;
|
||||
if(!BN_bin2bn(cont, len, bn)) {
|
||||
bn_free(pval, it);
|
||||
|
@ -175,8 +175,7 @@ static uint32_t get_error_values(int inc, int top, const char **file, int *line,
|
||||
uint32_t ret;
|
||||
|
||||
state = err_get_state();
|
||||
|
||||
if (state->bottom == state->top) {
|
||||
if (state == NULL || state->bottom == state->top) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -282,6 +281,10 @@ void ERR_clear_error(void) {
|
||||
ERR_STATE *const state = err_get_state();
|
||||
unsigned i;
|
||||
|
||||
if (state == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ERR_NUM_ERRORS; i++) {
|
||||
err_clear(&state->errors[i]);
|
||||
}
|
||||
@ -481,7 +484,7 @@ static void err_set_error_data(char *data, int flags) {
|
||||
ERR_STATE *const state = err_get_state();
|
||||
struct err_error_st *error;
|
||||
|
||||
if (state->top == state->bottom) {
|
||||
if (state == NULL || state->top == state->bottom) {
|
||||
if (flags & ERR_FLAG_MALLOCED) {
|
||||
OPENSSL_free(data);
|
||||
}
|
||||
@ -500,6 +503,10 @@ void ERR_put_error(int library, int func, int reason, const char *file,
|
||||
ERR_STATE *const state = err_get_state();
|
||||
struct err_error_st *error;
|
||||
|
||||
if (state == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (library == ERR_LIB_SYS && reason == 0) {
|
||||
#if defined(WIN32)
|
||||
reason = GetLastError();
|
||||
@ -600,7 +607,7 @@ void ERR_add_error_dataf(const char *format, ...) {
|
||||
int ERR_set_mark(void) {
|
||||
ERR_STATE *const state = err_get_state();
|
||||
|
||||
if (state->bottom == state->top) {
|
||||
if (state == NULL || state->bottom == state->top) {
|
||||
return 0;
|
||||
}
|
||||
state->errors[state->top].flags |= ERR_FLAG_MARK;
|
||||
@ -611,6 +618,10 @@ int ERR_pop_to_mark(void) {
|
||||
ERR_STATE *const state = err_get_state();
|
||||
struct err_error_st *error;
|
||||
|
||||
if (state == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (state->bottom != state->top) {
|
||||
error = &state->errors[state->top];
|
||||
|
||||
|
@ -231,6 +231,11 @@ static ERR_STATE *err_get_state(void) {
|
||||
CRYPTO_r_lock(CRYPTO_LOCK_ERR);
|
||||
}
|
||||
|
||||
if (state_hash == NULL) {
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state = lh_ERR_STATE_retrieve(state_hash, &pattern);
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
|
||||
if (state != NULL) {
|
||||
|
@ -124,7 +124,10 @@ static EVP_PKEY_CTX *evp_pkey_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) {
|
||||
|
||||
if (pmeth->init) {
|
||||
if (pmeth->init(ret) <= 0) {
|
||||
EVP_PKEY_CTX_free(ret);
|
||||
if (pkey) {
|
||||
EVP_PKEY_free(ret->pkey);
|
||||
}
|
||||
OPENSSL_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -176,17 +179,25 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx) {
|
||||
|
||||
if (pctx->pkey) {
|
||||
rctx->pkey = EVP_PKEY_dup(pctx->pkey);
|
||||
if (rctx->pkey == NULL) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (pctx->peerkey) {
|
||||
rctx->peerkey = EVP_PKEY_dup(pctx->peerkey);
|
||||
if (rctx->peerkey == NULL) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (pctx->pmeth->copy(rctx, pctx) > 0) {
|
||||
return rctx;
|
||||
}
|
||||
|
||||
err:
|
||||
EVP_PKEY_CTX_free(rctx);
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_PKEY_CTX_dup, ERR_LIB_EVP);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -485,6 +496,10 @@ int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) {
|
||||
|
||||
if (!*ppkey) {
|
||||
*ppkey = EVP_PKEY_new();
|
||||
if (!*ppkey) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_PKEY_keygen, ERR_LIB_EVP);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ctx->pmeth->keygen(ctx, *ppkey)) {
|
||||
|
@ -20,6 +20,7 @@ const ERR_STRING_DATA EVP_error_string_data[] = {
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DigestSignAlgorithm, 0), "EVP_DigestSignAlgorithm"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DigestVerifyInitFromAlgorithm, 0), "EVP_DigestVerifyInitFromAlgorithm"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_ctrl, 0), "EVP_PKEY_CTX_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_dup, 0), "EVP_PKEY_CTX_dup"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_copy_parameters, 0), "EVP_PKEY_copy_parameters"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_decrypt, 0), "EVP_PKEY_decrypt"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_decrypt_init, 0), "EVP_PKEY_decrypt_init"},
|
||||
|
@ -109,6 +109,10 @@ static int pkey_hmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) {
|
||||
static void pkey_hmac_cleanup(EVP_PKEY_CTX *ctx) {
|
||||
HMAC_PKEY_CTX *hctx = ctx->data;
|
||||
|
||||
if (hctx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
HMAC_CTX_cleanup(&hctx->ctx);
|
||||
if (hctx->ktmp.data) {
|
||||
if (hctx->ktmp.length) {
|
||||
|
@ -193,8 +193,10 @@ static LHASH_OF(EX_CLASS_ITEM) *get_classes(void) {
|
||||
static void cleanup(void) {
|
||||
LHASH_OF(EX_CLASS_ITEM) *classes = get_classes();
|
||||
|
||||
lh_EX_CLASS_ITEM_doall(classes, class_free);
|
||||
lh_EX_CLASS_ITEM_free(classes);
|
||||
if (classes != NULL) {
|
||||
lh_EX_CLASS_ITEM_doall(classes, class_free);
|
||||
lh_EX_CLASS_ITEM_free(classes);
|
||||
}
|
||||
|
||||
global_classes = NULL;
|
||||
}
|
||||
@ -204,6 +206,10 @@ static EX_CLASS_ITEM *get_class(int class_value) {
|
||||
EX_CLASS_ITEM template, *class_item;
|
||||
int ok = 0;
|
||||
|
||||
if (classes == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
|
||||
template.class_value = class_value;
|
||||
class_item = lh_EX_CLASS_ITEM_retrieve(classes, &template);
|
||||
|
@ -2247,38 +2247,26 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
|
||||
STACK_OF(X509) *chain)
|
||||
{
|
||||
int ret = 1;
|
||||
int ex_data_allocated = 0;
|
||||
|
||||
memset(ctx, 0, sizeof(X509_STORE_CTX));
|
||||
ctx->ctx=store;
|
||||
ctx->current_method=0;
|
||||
ctx->cert=x509;
|
||||
ctx->untrusted=chain;
|
||||
ctx->crls = NULL;
|
||||
ctx->last_untrusted=0;
|
||||
ctx->other_ctx=NULL;
|
||||
ctx->valid=0;
|
||||
ctx->chain=NULL;
|
||||
ctx->error=0;
|
||||
ctx->explicit_policy=0;
|
||||
ctx->error_depth=0;
|
||||
ctx->current_cert=NULL;
|
||||
ctx->current_issuer=NULL;
|
||||
ctx->current_crl=NULL;
|
||||
ctx->current_crl_score=0;
|
||||
ctx->current_reasons=0;
|
||||
ctx->tree = NULL;
|
||||
ctx->parent = NULL;
|
||||
|
||||
if(!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
|
||||
&ctx->ex_data))
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
ex_data_allocated = 1;
|
||||
|
||||
ctx->param = X509_VERIFY_PARAM_new();
|
||||
|
||||
if (!ctx->param)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_init, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
goto err;
|
||||
|
||||
/* Inherit callbacks and flags from X509_STORE if not set
|
||||
* use defaults.
|
||||
*/
|
||||
|
||||
* use defaults. */
|
||||
|
||||
if (store)
|
||||
ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param);
|
||||
@ -2298,10 +2286,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
|
||||
X509_VERIFY_PARAM_lookup("default"));
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_init, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
goto err;
|
||||
|
||||
if (store && store->check_issued)
|
||||
ctx->check_issued = store->check_issued;
|
||||
@ -2355,19 +2340,21 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
|
||||
|
||||
ctx->check_policy = check_policy;
|
||||
|
||||
|
||||
/* This memset() can't make any sense anyway, so it's removed. As
|
||||
* X509_STORE_CTX_cleanup does a proper "free" on the ex_data, we put a
|
||||
* corresponding "new" here and remove this bogus initialisation. */
|
||||
/* memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA)); */
|
||||
if(!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
|
||||
&(ctx->ex_data)))
|
||||
{
|
||||
OPENSSL_free(ctx);
|
||||
OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_init, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
||||
err:
|
||||
if (ex_data_allocated)
|
||||
{
|
||||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &ctx->ex_data);
|
||||
}
|
||||
if (ctx->param != NULL)
|
||||
{
|
||||
X509_VERIFY_PARAM_free(ctx->param);
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(X509_STORE_CTX));
|
||||
OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_init, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set alternative lookup method: just a STACK of trusted certificates.
|
||||
|
@ -354,10 +354,15 @@ static int x509_name_canon(X509_NAME *a)
|
||||
if(!entries)
|
||||
goto err;
|
||||
if(!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries))
|
||||
{
|
||||
sk_X509_NAME_ENTRY_free(entries);
|
||||
goto err;
|
||||
}
|
||||
set = entry->set;
|
||||
}
|
||||
tmpentry = X509_NAME_ENTRY_new();
|
||||
if (tmpentry == NULL)
|
||||
goto err;
|
||||
tmpentry->object = OBJ_dup(entry->object);
|
||||
if (!asn1_string_canon(tmpentry->value, entry->value))
|
||||
goto err;
|
||||
|
@ -829,6 +829,7 @@ struct evp_pkey_st {
|
||||
#define EVP_F_EVP_DigestVerifyInitFromAlgorithm 155
|
||||
#define EVP_F_EVP_DigestSignAlgorithm 156
|
||||
#define EVP_F_rsa_digest_verify_init_from_algorithm 157
|
||||
#define EVP_F_EVP_PKEY_CTX_dup 158
|
||||
#define EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE 100
|
||||
#define EVP_R_UNSUPPORTED_SIGNATURE_TYPE 101
|
||||
#define EVP_R_INVALID_DIGEST_TYPE 102
|
||||
|
@ -242,7 +242,12 @@ int dtls1_connect(SSL *s)
|
||||
s->shutdown=0;
|
||||
|
||||
/* every DTLS ClientHello resets Finished MAC */
|
||||
ssl3_init_finished_mac(s);
|
||||
if (!ssl3_init_finished_mac(s))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, dtls1_connect, ERR_R_INTERNAL_ERROR);
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
dtls1_start_timer(s);
|
||||
ret=ssl3_send_client_hello(s);
|
||||
|
@ -239,9 +239,15 @@ int dtls1_accept(SSL *s)
|
||||
* the output is sent in a way that TCP likes :-)
|
||||
* ...but not with SCTP :-)
|
||||
*/
|
||||
if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; }
|
||||
if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; }
|
||||
|
||||
if (!ssl3_init_finished_mac(s))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, dtls1_accept, ERR_R_INTERNAL_ERROR);
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ssl3_init_finished_mac(s);
|
||||
s->state=SSL3_ST_SR_CLNT_HELLO_A;
|
||||
s->ctx->stats.sess_accept++;
|
||||
}
|
||||
@ -267,7 +273,12 @@ int dtls1_accept(SSL *s)
|
||||
s->state=SSL3_ST_SW_FLUSH;
|
||||
s->init_num=0;
|
||||
|
||||
ssl3_init_finished_mac(s);
|
||||
if (!ssl3_init_finished_mac(s))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, dtls1_accept, ERR_R_INTERNAL_ERROR);
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
|
||||
case SSL3_ST_SW_HELLO_REQ_C:
|
||||
@ -301,7 +312,12 @@ int dtls1_accept(SSL *s)
|
||||
s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A;
|
||||
|
||||
/* HelloVerifyRequest resets Finished MAC */
|
||||
ssl3_init_finished_mac(s);
|
||||
if (!ssl3_init_finished_mac(s))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, dtls1_accept, ERR_R_INTERNAL_ERROR);
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
@ -188,7 +188,12 @@ int ssl23_connect(SSL *s)
|
||||
|
||||
if (!ssl3_setup_buffers(s)) { ret= -1; goto end; }
|
||||
|
||||
ssl3_init_finished_mac(s);
|
||||
if (!ssl3_init_finished_mac(s))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl23_connect, ERR_R_INTERNAL_ERROR);
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
s->state=SSL23_ST_CW_CLNT_HELLO_A;
|
||||
s->ctx->stats.sess_connect++;
|
||||
|
@ -191,7 +191,12 @@ int ssl23_accept(SSL *s)
|
||||
s->init_buf=buf;
|
||||
}
|
||||
|
||||
ssl3_init_finished_mac(s);
|
||||
if (!ssl3_init_finished_mac(s))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl23_accept, ERR_R_INTERNAL_ERROR);
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
s->state=SSL23_ST_SR_CLNT_HELLO;
|
||||
s->ctx->stats.sess_accept++;
|
||||
|
21
ssl/s3_cbc.c
21
ssl/s3_cbc.c
@ -333,7 +333,7 @@ char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx)
|
||||
* ctx: the EVP_MD_CTX from which we take the hash function.
|
||||
* ssl3_cbc_record_digest_supported must return true for this EVP_MD_CTX.
|
||||
* md_out: the digest output. At most EVP_MAX_MD_SIZE bytes will be written.
|
||||
* md_out_size: if non-NULL, the number of output bytes is written here.
|
||||
* md_out_size: the number of output bytes is written here.
|
||||
* header: the 13-byte, TLS record header.
|
||||
* data: the record data itself, less any preceeding explicit IV.
|
||||
* data_plus_mac_size: the secret, reported length of the data and MAC
|
||||
@ -346,7 +346,7 @@ char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx)
|
||||
* functions, above, we know that data_plus_mac_size is large enough to contain
|
||||
* a padding byte and MAC. (If the padding was invalid, it might contain the
|
||||
* padding too. ) */
|
||||
void ssl3_cbc_digest_record(
|
||||
int ssl3_cbc_digest_record(
|
||||
const EVP_MD_CTX *ctx,
|
||||
unsigned char* md_out,
|
||||
size_t* md_out_size,
|
||||
@ -409,9 +409,8 @@ void ssl3_cbc_digest_record(
|
||||
* called first to check that the hash function is
|
||||
* supported. */
|
||||
assert(0);
|
||||
if (md_out_size)
|
||||
*md_out_size = -1;
|
||||
return;
|
||||
*md_out_size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES);
|
||||
@ -591,7 +590,12 @@ void ssl3_cbc_digest_record(
|
||||
}
|
||||
|
||||
EVP_MD_CTX_init(&md_ctx);
|
||||
EVP_DigestInit_ex(&md_ctx, ctx->digest, NULL /* engine */);
|
||||
if (!EVP_DigestInit_ex(&md_ctx, ctx->digest, NULL /* engine */))
|
||||
{
|
||||
EVP_MD_CTX_cleanup(&md_ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_sslv3)
|
||||
{
|
||||
/* We repurpose |hmac_pad| to contain the SSLv3 pad2 block. */
|
||||
@ -611,7 +615,8 @@ void ssl3_cbc_digest_record(
|
||||
EVP_DigestUpdate(&md_ctx, mac_out, md_size);
|
||||
}
|
||||
EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u);
|
||||
if (md_out_size)
|
||||
*md_out_size = md_out_size_u;
|
||||
*md_out_size = md_out_size_u;
|
||||
EVP_MD_CTX_cleanup(&md_ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -276,7 +276,12 @@ int ssl3_connect(SSL *s)
|
||||
|
||||
/* don't push the buffering BIO quite yet */
|
||||
|
||||
ssl3_init_finished_mac(s);
|
||||
if (!ssl3_init_finished_mac(s))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_connect, ERR_R_INTERNAL_ERROR);
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
s->state=SSL3_ST_CW_CLNT_HELLO_A;
|
||||
s->ctx->stats.sess_connect++;
|
||||
|
88
ssl/s3_enc.c
88
ssl/s3_enc.c
@ -185,7 +185,11 @@ static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num)
|
||||
for (j=0; j<k; j++)
|
||||
buf[j]=c;
|
||||
c++;
|
||||
EVP_DigestInit_ex(&s1,EVP_sha1(), NULL);
|
||||
if (!EVP_DigestInit_ex(&s1,EVP_sha1(), NULL))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_generate_key_block, ERR_LIB_EVP);
|
||||
return 0;
|
||||
}
|
||||
EVP_DigestUpdate(&s1,buf,k);
|
||||
EVP_DigestUpdate(&s1,s->session->master_key,
|
||||
s->session->master_key_length);
|
||||
@ -193,7 +197,11 @@ static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num)
|
||||
EVP_DigestUpdate(&s1,s->s3->client_random,SSL3_RANDOM_SIZE);
|
||||
EVP_DigestFinal_ex(&s1,smd,NULL);
|
||||
|
||||
EVP_DigestInit_ex(&m5,EVP_md5(), NULL);
|
||||
if (!EVP_DigestInit_ex(&m5,EVP_md5(), NULL))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_generate_key_block, ERR_LIB_EVP);
|
||||
return 0;
|
||||
}
|
||||
EVP_DigestUpdate(&m5,s->session->master_key,
|
||||
s->session->master_key_length);
|
||||
EVP_DigestUpdate(&m5,smd,SHA_DIGEST_LENGTH);
|
||||
@ -470,12 +478,17 @@ int ssl3_enc(SSL *s, int send)
|
||||
return(1);
|
||||
}
|
||||
|
||||
void ssl3_init_finished_mac(SSL *s)
|
||||
int ssl3_init_finished_mac(SSL *s)
|
||||
{
|
||||
if (s->s3->handshake_buffer) BIO_free(s->s3->handshake_buffer);
|
||||
if (s->s3->handshake_dgst) ssl3_free_digest_list(s);
|
||||
s->s3->handshake_buffer=BIO_new(BIO_s_mem());
|
||||
s->s3->handshake_buffer = BIO_new(BIO_s_mem());
|
||||
if (s->s3->handshake_buffer == NULL) {
|
||||
return 0;
|
||||
}
|
||||
(void)BIO_set_close(s->s3->handshake_buffer,BIO_CLOSE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ssl3_free_digest_list(SSL *s)
|
||||
@ -521,6 +534,12 @@ int ssl3_digest_cached_records(SSL *s, enum should_free_handshake_buffer_t shoul
|
||||
/* Allocate handshake_dgst array */
|
||||
ssl3_free_digest_list(s);
|
||||
s->s3->handshake_dgst = OPENSSL_malloc(SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *));
|
||||
if (s->s3->handshake_dgst == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_digest_cached_records, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(s->s3->handshake_dgst,0,SSL_MAX_DIGEST *sizeof(EVP_MD_CTX *));
|
||||
if (!BIO_mem_contents(s->s3->handshake_buffer, &hdata, &hdatalen))
|
||||
{
|
||||
@ -533,8 +552,18 @@ int ssl3_digest_cached_records(SSL *s, enum should_free_handshake_buffer_t shoul
|
||||
{
|
||||
if ((mask & ssl_get_algorithm2(s)) && md)
|
||||
{
|
||||
s->s3->handshake_dgst[i]=EVP_MD_CTX_create();
|
||||
EVP_DigestInit_ex(s->s3->handshake_dgst[i],md,NULL);
|
||||
s->s3->handshake_dgst[i] = EVP_MD_CTX_create();
|
||||
if (s->s3->handshake_dgst[i] == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_digest_cached_records, ERR_LIB_EVP);
|
||||
return 0;
|
||||
}
|
||||
if (!EVP_DigestInit_ex(s->s3->handshake_dgst[i], md, NULL))
|
||||
{
|
||||
EVP_MD_CTX_destroy(s->s3->handshake_dgst[i]);
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_digest_cached_records, ERR_LIB_EVP);
|
||||
return 0;
|
||||
}
|
||||
EVP_DigestUpdate(s->s3->handshake_dgst[i],hdata,hdatalen);
|
||||
}
|
||||
else
|
||||
@ -603,7 +632,12 @@ static int ssl3_handshake_mac(SSL *s, int md_nid,
|
||||
return 0;
|
||||
}
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
EVP_MD_CTX_copy_ex(&ctx,d);
|
||||
if (!EVP_MD_CTX_copy_ex(&ctx,d))
|
||||
{
|
||||
EVP_MD_CTX_cleanup(&ctx);
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_generate_key_block, ERR_LIB_EVP);
|
||||
return 0;
|
||||
}
|
||||
n=EVP_MD_CTX_size(&ctx);
|
||||
if (n < 0)
|
||||
return 0;
|
||||
@ -616,7 +650,12 @@ static int ssl3_handshake_mac(SSL *s, int md_nid,
|
||||
EVP_DigestUpdate(&ctx,ssl3_pad_1,npad);
|
||||
EVP_DigestFinal_ex(&ctx,md_buf,&i);
|
||||
|
||||
EVP_DigestInit_ex(&ctx,EVP_MD_CTX_md(&ctx), NULL);
|
||||
if (!EVP_DigestInit_ex(&ctx,EVP_MD_CTX_md(&ctx), NULL))
|
||||
{
|
||||
EVP_MD_CTX_cleanup(&ctx);
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_generate_key_block, ERR_LIB_EVP);
|
||||
return 0;
|
||||
}
|
||||
EVP_DigestUpdate(&ctx,s->session->master_key,
|
||||
s->session->master_key_length);
|
||||
EVP_DigestUpdate(&ctx,ssl3_pad_2,npad);
|
||||
@ -691,13 +730,16 @@ int n_ssl3_mac(SSL *ssl, unsigned char *md, int send)
|
||||
header[j++] = rec->length >> 8;
|
||||
header[j++] = rec->length & 0xff;
|
||||
|
||||
ssl3_cbc_digest_record(
|
||||
if (!ssl3_cbc_digest_record(
|
||||
hash,
|
||||
md, &md_size,
|
||||
header, rec->input,
|
||||
rec->length + md_size, orig_len,
|
||||
mac_sec, md_size,
|
||||
1 /* is SSLv3 */);
|
||||
1 /* is SSLv3 */))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -705,7 +747,11 @@ int n_ssl3_mac(SSL *ssl, unsigned char *md, int send)
|
||||
/* Chop the digest off the end :-) */
|
||||
EVP_MD_CTX_init(&md_ctx);
|
||||
|
||||
EVP_MD_CTX_copy_ex( &md_ctx,hash);
|
||||
if (!EVP_MD_CTX_copy_ex(&md_ctx,hash))
|
||||
{
|
||||
EVP_MD_CTX_cleanup(&md_ctx);
|
||||
return -1;
|
||||
}
|
||||
EVP_DigestUpdate(&md_ctx,mac_sec,md_size);
|
||||
EVP_DigestUpdate(&md_ctx,ssl3_pad_1,npad);
|
||||
EVP_DigestUpdate(&md_ctx,seq,8);
|
||||
@ -717,7 +763,11 @@ int n_ssl3_mac(SSL *ssl, unsigned char *md, int send)
|
||||
EVP_DigestUpdate(&md_ctx,rec->input,rec->length);
|
||||
EVP_DigestFinal_ex( &md_ctx,md,NULL);
|
||||
|
||||
EVP_MD_CTX_copy_ex( &md_ctx,hash);
|
||||
if (!EVP_MD_CTX_copy_ex(&md_ctx,hash))
|
||||
{
|
||||
EVP_MD_CTX_cleanup(&md_ctx);
|
||||
return -1;
|
||||
}
|
||||
EVP_DigestUpdate(&md_ctx,mac_sec,md_size);
|
||||
EVP_DigestUpdate(&md_ctx,ssl3_pad_2,npad);
|
||||
EVP_DigestUpdate(&md_ctx,md,md_size);
|
||||
@ -761,7 +811,12 @@ int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
for (i=0; i<3; i++)
|
||||
{
|
||||
EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL);
|
||||
if (!EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL))
|
||||
{
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
EVP_DigestUpdate(&ctx,salt[i],strlen((const char *)salt[i]));
|
||||
EVP_DigestUpdate(&ctx,p,len);
|
||||
EVP_DigestUpdate(&ctx,&(s->s3->client_random[0]),
|
||||
@ -770,7 +825,12 @@ int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
|
||||
SSL3_RANDOM_SIZE);
|
||||
EVP_DigestFinal_ex(&ctx,buf,&n);
|
||||
|
||||
EVP_DigestInit_ex(&ctx, EVP_md5(), NULL);
|
||||
if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL))
|
||||
{
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
EVP_DigestUpdate(&ctx,p,len);
|
||||
EVP_DigestUpdate(&ctx,buf,n);
|
||||
EVP_DigestFinal_ex(&ctx,out,&n);
|
||||
|
@ -294,7 +294,12 @@ int ssl3_accept(SSL *s)
|
||||
*/
|
||||
if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; }
|
||||
|
||||
ssl3_init_finished_mac(s);
|
||||
if (!ssl3_init_finished_mac(s))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_accept, ERR_R_INTERNAL_ERROR);
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
s->state=SSL3_ST_SR_CLNT_HELLO_A;
|
||||
s->ctx->stats.sess_accept++;
|
||||
}
|
||||
@ -329,7 +334,12 @@ int ssl3_accept(SSL *s)
|
||||
s->state=SSL3_ST_SW_FLUSH;
|
||||
s->init_num=0;
|
||||
|
||||
ssl3_init_finished_mac(s);
|
||||
if (!ssl3_init_finished_mac(s))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_accept, ERR_R_INTERNAL_ERROR);
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
|
||||
case SSL3_ST_SW_HELLO_REQ_C:
|
||||
@ -2578,16 +2588,22 @@ int ssl3_send_new_session_ticket(SSL *s)
|
||||
&hctx, 1) < 0)
|
||||
{
|
||||
OPENSSL_free(session);
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
HMAC_CTX_cleanup(&hctx);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RAND_pseudo_bytes(iv, 16);
|
||||
EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
|
||||
tctx->tlsext_tick_aes_key, iv);
|
||||
HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
|
||||
tlsext_tick_md(), NULL);
|
||||
if (!EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, tctx->tlsext_tick_aes_key, iv) ||
|
||||
!HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(), NULL))
|
||||
{
|
||||
OPENSSL_free(session);
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
HMAC_CTX_cleanup(&hctx);
|
||||
return -1;
|
||||
}
|
||||
memcpy(key_name, tctx->tlsext_tick_key_name, 16);
|
||||
}
|
||||
|
||||
|
@ -3167,7 +3167,10 @@ EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md)
|
||||
{
|
||||
ssl_clear_hash_ctx(hash);
|
||||
*hash = EVP_MD_CTX_create();
|
||||
if (md) EVP_DigestInit_ex(*hash,md,NULL);
|
||||
if (md != NULL && *hash != NULL)
|
||||
{
|
||||
EVP_DigestInit_ex(*hash,md,NULL);
|
||||
}
|
||||
return *hash;
|
||||
}
|
||||
void ssl_clear_hash_ctx(EVP_MD_CTX **hash)
|
||||
|
@ -819,7 +819,7 @@ int ssl_fill_hello_random(SSL *s, int server, unsigned char *field, int len);
|
||||
|
||||
const SSL_CIPHER *ssl3_get_cipher_by_value(uint16_t value);
|
||||
uint16_t ssl3_get_cipher_value(const SSL_CIPHER *c);
|
||||
void ssl3_init_finished_mac(SSL *s);
|
||||
int ssl3_init_finished_mac(SSL *s);
|
||||
int ssl3_send_server_certificate(SSL *s);
|
||||
int ssl3_send_new_session_ticket(SSL *s);
|
||||
int ssl3_send_cert_status(SSL *s);
|
||||
@ -1120,7 +1120,7 @@ int tls1_cbc_remove_padding(const SSL* s,
|
||||
unsigned block_size,
|
||||
unsigned mac_size);
|
||||
char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx);
|
||||
void ssl3_cbc_digest_record(
|
||||
int ssl3_cbc_digest_record(
|
||||
const EVP_MD_CTX *ctx,
|
||||
unsigned char* md_out,
|
||||
size_t* md_out_size,
|
||||
|
33
ssl/t1_enc.c
33
ssl/t1_enc.c
@ -447,6 +447,8 @@ static int tls1_change_cipher_state_cipher(
|
||||
|
||||
cipher_ctx = s->enc_read_ctx;
|
||||
mac_ctx = ssl_replace_hash(&s->read_hash, NULL);
|
||||
if (mac_ctx == NULL)
|
||||
goto err;
|
||||
|
||||
memcpy(s->s3->read_mac_secret, mac_secret, mac_secret_len);
|
||||
s->s3->read_mac_secret_size = mac_secret_len;
|
||||
@ -476,7 +478,11 @@ static int tls1_change_cipher_state_cipher(
|
||||
s->write_hash = mac_ctx;
|
||||
}
|
||||
else
|
||||
{
|
||||
mac_ctx = ssl_replace_hash(&s->write_hash, NULL);
|
||||
if (mac_ctx == NULL)
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy(s->s3->write_mac_secret, mac_secret, mac_secret_len);
|
||||
s->s3->write_mac_secret_size = mac_secret_len;
|
||||
@ -487,10 +493,15 @@ static int tls1_change_cipher_state_cipher(
|
||||
NULL, mac_secret, mac_secret_len);
|
||||
if (!mac_key)
|
||||
return 0;
|
||||
EVP_DigestSignInit(mac_ctx, NULL, s->s3->tmp.new_hash, NULL, mac_key);
|
||||
if (!EVP_DigestSignInit(mac_ctx, NULL, s->s3->tmp.new_hash, NULL, mac_key))
|
||||
{
|
||||
EVP_PKEY_free(mac_key);
|
||||
goto err;
|
||||
}
|
||||
EVP_PKEY_free(mac_key);
|
||||
|
||||
EVP_CipherInit_ex(cipher_ctx, cipher, NULL /* engine */, key, iv, !is_read);
|
||||
if (!EVP_CipherInit_ex(cipher_ctx, cipher, NULL /* engine */, key, iv, !is_read))
|
||||
goto err;
|
||||
|
||||
return 1;
|
||||
|
||||
@ -1063,7 +1074,7 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send)
|
||||
unsigned char *seq;
|
||||
EVP_MD_CTX *hash;
|
||||
size_t md_size, orig_len;
|
||||
int i;
|
||||
int i, ok;
|
||||
EVP_MD_CTX hmac, *mac_ctx;
|
||||
unsigned char header[13];
|
||||
int t;
|
||||
@ -1085,9 +1096,9 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send)
|
||||
assert(t >= 0);
|
||||
md_size=t;
|
||||
|
||||
if (!EVP_MD_CTX_copy(&hmac,hash))
|
||||
return -1;
|
||||
mac_ctx = &hmac;
|
||||
if (!EVP_MD_CTX_copy(mac_ctx, hash))
|
||||
return -1;
|
||||
|
||||
if (SSL_IS_DTLS(ssl))
|
||||
{
|
||||
@ -1119,7 +1130,7 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send)
|
||||
* timing-side channel information about how many blocks of
|
||||
* data we are hashing because that gives an attacker a
|
||||
* timing-oracle. */
|
||||
ssl3_cbc_digest_record(
|
||||
ok = ssl3_cbc_digest_record(
|
||||
mac_ctx,
|
||||
md, &md_size,
|
||||
header, rec->input,
|
||||
@ -1132,11 +1143,13 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send)
|
||||
{
|
||||
EVP_DigestSignUpdate(mac_ctx,header,sizeof(header));
|
||||
EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length);
|
||||
t=EVP_DigestSignFinal(mac_ctx,md,&md_size);
|
||||
assert(t > 0);
|
||||
ok = EVP_DigestSignFinal(mac_ctx,md,&md_size);
|
||||
}
|
||||
|
||||
EVP_MD_CTX_cleanup(&hmac);
|
||||
EVP_MD_CTX_cleanup(mac_ctx);
|
||||
|
||||
if (!ok)
|
||||
return -1;
|
||||
|
||||
if (!SSL_IS_DTLS(ssl))
|
||||
{
|
||||
@ -1147,7 +1160,7 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send)
|
||||
}
|
||||
}
|
||||
|
||||
return(md_size);
|
||||
return md_size;
|
||||
}
|
||||
|
||||
int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
|
||||
|
@ -5,8 +5,9 @@ add_executable(
|
||||
|
||||
async_bio.cc
|
||||
bssl_shim.cc
|
||||
malloc.cc
|
||||
packeted_bio.cc
|
||||
test_config.cc
|
||||
)
|
||||
|
||||
target_link_libraries(bssl_shim ssl crypto)
|
||||
target_link_libraries(bssl_shim ssl crypto dl)
|
||||
|
@ -41,8 +41,8 @@ static int usage(const char *program) {
|
||||
|
||||
static int g_ex_data_index = 0;
|
||||
|
||||
static void SetConfigPtr(SSL *ssl, const TestConfig *config) {
|
||||
SSL_set_ex_data(ssl, g_ex_data_index, (void *)config);
|
||||
static bool SetConfigPtr(SSL *ssl, const TestConfig *config) {
|
||||
return SSL_set_ex_data(ssl, g_ex_data_index, (void *)config) == 1;
|
||||
}
|
||||
|
||||
static const TestConfig *GetConfigPtr(SSL *ssl) {
|
||||
@ -267,7 +267,8 @@ static SSL_CTX *setup_ctx(const TestConfig *config) {
|
||||
}
|
||||
|
||||
dh = DH_get_2048_256(NULL);
|
||||
if (!SSL_CTX_set_tmp_dh(ssl_ctx, dh)) {
|
||||
if (dh == NULL ||
|
||||
!SSL_CTX_set_tmp_dh(ssl_ctx, dh)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -335,7 +336,10 @@ static int do_exchange(SSL_SESSION **out_session,
|
||||
return 1;
|
||||
}
|
||||
|
||||
SetConfigPtr(ssl, config);
|
||||
if (!SetConfigPtr(ssl, config)) {
|
||||
BIO_print_errors_fp(stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (config->fallback_scsv) {
|
||||
if (!SSL_enable_fallback_scsv(ssl)) {
|
||||
|
126
ssl/test/malloc.cc
Normal file
126
ssl/test/malloc.cc
Normal file
@ -0,0 +1,126 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#if defined(__linux__)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
|
||||
/* This file defines overrides for the standard allocation functions that allow
|
||||
* a given allocation to be made to fail for testing. If the program is run
|
||||
* with MALLOC_NUMBER_TO_FAIL set to a base-10 number then that allocation will
|
||||
* return NULL. If MALLOC_ABORT_ON_FAIL is also defined then the allocation
|
||||
* will abort() rather than return NULL.
|
||||
*
|
||||
* This code is not thread safe. */
|
||||
|
||||
static uint64_t current_malloc_count = 0;
|
||||
static uint64_t malloc_number_to_fail = 0;
|
||||
static char failure_enabled = 0, abort_on_fail = 0;
|
||||
static int in_call = 0;
|
||||
|
||||
extern "C" {
|
||||
/* These are other names for the standard allocation functions. */
|
||||
extern void *__libc_malloc(size_t size);
|
||||
extern void *__libc_calloc(size_t num_elems, size_t size);
|
||||
extern void *__libc_realloc(void *ptr, size_t size);
|
||||
}
|
||||
|
||||
static void exit_handler(void) {
|
||||
if (failure_enabled && current_malloc_count > malloc_number_to_fail) {
|
||||
_exit(88);
|
||||
}
|
||||
}
|
||||
|
||||
static void cpp_new_handler() {
|
||||
// Return to try again. It won't fail a second time.
|
||||
return;
|
||||
}
|
||||
|
||||
/* should_fail_allocation returns true if the current allocation should fail. */
|
||||
static int should_fail_allocation() {
|
||||
static int init = 0;
|
||||
char should_fail;
|
||||
|
||||
if (in_call) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
in_call = 1;
|
||||
|
||||
if (!init) {
|
||||
const char *env = getenv("MALLOC_NUMBER_TO_FAIL");
|
||||
if (env != NULL && env[0] != 0) {
|
||||
char *endptr;
|
||||
malloc_number_to_fail = strtoull(env, &endptr, 10);
|
||||
if (*endptr == 0) {
|
||||
failure_enabled = 1;
|
||||
atexit(exit_handler);
|
||||
std::set_new_handler(cpp_new_handler);
|
||||
}
|
||||
}
|
||||
abort_on_fail = (NULL != getenv("MALLOC_ABORT_ON_FAIL"));
|
||||
init = 1;
|
||||
}
|
||||
|
||||
in_call = 0;
|
||||
|
||||
if (!failure_enabled) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
should_fail = (current_malloc_count == malloc_number_to_fail);
|
||||
current_malloc_count++;
|
||||
|
||||
if (should_fail && abort_on_fail) {
|
||||
abort();
|
||||
}
|
||||
return should_fail;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
void *malloc(size_t size) {
|
||||
if (should_fail_allocation()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return __libc_malloc(size);
|
||||
}
|
||||
|
||||
void *calloc(size_t num_elems, size_t size) {
|
||||
if (should_fail_allocation()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return __libc_calloc(num_elems, size);
|
||||
}
|
||||
|
||||
void *realloc(void *ptr, size_t size) {
|
||||
if (should_fail_allocation()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return __libc_realloc(ptr, size);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#endif /* defined(linux) */
|
@ -67,7 +67,9 @@ static int packeted_read(BIO *bio, char *out, int outl) {
|
||||
uint32_t len = (len_bytes[0] << 24) | (len_bytes[1] << 16) |
|
||||
(len_bytes[2] << 8) | len_bytes[3];
|
||||
char *buf = (char *)OPENSSL_malloc(len);
|
||||
assert(buf != NULL);
|
||||
if (buf == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ret = BIO_read(bio->next_bio, buf, len);
|
||||
assert(ret == (int)len);
|
||||
|
||||
|
@ -16,14 +16,19 @@ import (
|
||||
"os/exec"
|
||||
"path"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind")
|
||||
var useGDB = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
|
||||
var flagDebug *bool = flag.Bool("debug", false, "Hexdump the contents of the connection")
|
||||
var (
|
||||
useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind")
|
||||
useGDB = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
|
||||
flagDebug *bool = flag.Bool("debug", false, "Hexdump the contents of the connection")
|
||||
mallocTest *int64 = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
|
||||
mallocTestDebug *bool = flag.Bool("malloc-test-debug", false, "If true, ask bssl_shim to abort rather than fail a malloc. This can be used with a specific value for --malloc-test to identity the malloc failing that is causing problems.")
|
||||
)
|
||||
|
||||
const (
|
||||
rsaCertificateFile = "cert.pem"
|
||||
@ -703,7 +708,15 @@ func openSocketPair() (shimEnd *os.File, conn net.Conn) {
|
||||
return shimEnd, conn
|
||||
}
|
||||
|
||||
func runTest(test *testCase, buildDir string) error {
|
||||
type moreMallocsError struct{}
|
||||
|
||||
func (moreMallocsError) Error() string {
|
||||
return "child process did not exhaust all allocation calls"
|
||||
}
|
||||
|
||||
var errMoreMallocs = moreMallocsError{}
|
||||
|
||||
func runTest(test *testCase, buildDir string, mallocNumToFail int64) error {
|
||||
if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
|
||||
panic("Error expected without shouldFail in " + test.name)
|
||||
}
|
||||
@ -758,6 +771,13 @@ func runTest(test *testCase, buildDir string) error {
|
||||
var stdoutBuf, stderrBuf bytes.Buffer
|
||||
shim.Stdout = &stdoutBuf
|
||||
shim.Stderr = &stderrBuf
|
||||
if mallocNumToFail >= 0 {
|
||||
shim.Env = []string{"MALLOC_NUMBER_TO_FAIL=" + strconv.FormatInt(mallocNumToFail, 10)}
|
||||
if *mallocTestDebug {
|
||||
shim.Env = append(shim.Env, "MALLOC_ABORT_ON_FAIL=1")
|
||||
}
|
||||
shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
|
||||
}
|
||||
|
||||
if err := shim.Start(); err != nil {
|
||||
panic(err)
|
||||
@ -805,6 +825,11 @@ func runTest(test *testCase, buildDir string) error {
|
||||
connResume.Close()
|
||||
|
||||
childErr := shim.Wait()
|
||||
if exitError, ok := childErr.(*exec.ExitError); ok {
|
||||
if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
|
||||
return errMoreMallocs
|
||||
}
|
||||
}
|
||||
|
||||
stdout := string(stdoutBuf.Bytes())
|
||||
stderr := string(stderrBuf.Bytes())
|
||||
@ -2142,8 +2167,22 @@ func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sy
|
||||
defer wg.Done()
|
||||
|
||||
for test := range c {
|
||||
statusChan <- statusMsg{test: test, started: true}
|
||||
err := runTest(test, buildDir)
|
||||
var err error
|
||||
|
||||
if *mallocTest < 0 {
|
||||
statusChan <- statusMsg{test: test, started: true}
|
||||
err = runTest(test, buildDir, -1)
|
||||
} else {
|
||||
for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
|
||||
statusChan <- statusMsg{test: test, started: true}
|
||||
if err = runTest(test, buildDir, mallocNumToFail); err != errMoreMallocs {
|
||||
if err != nil {
|
||||
fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
statusChan <- statusMsg{test: test, err: err}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user