X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=crypto%2Fex_data.c;h=78162b5c092098163512a775c64300efb887e619;hb=1687aa760cdd164b12c5b70e65cadcbce1e7ccfa;hp=0666393900b4852012a76ac26722c594fd0ec5e9;hpb=aa6bb1352b1026b20a23b49da4efdcf171926eb0;p=oweals%2Fopenssl.git diff --git a/crypto/ex_data.c b/crypto/ex_data.c index 0666393900..78162b5c09 100644 --- a/crypto/ex_data.c +++ b/crypto/ex_data.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,7 +8,7 @@ */ #include "internal/cryptlib_int.h" -#include +#include "internal/thread_once.h" /* * Each structure type (sometimes called a class), that supports @@ -35,9 +35,11 @@ static EX_CALLBACKS ex_data[CRYPTO_EX_INDEX__COUNT]; static CRYPTO_RWLOCK *ex_data_lock = NULL; static CRYPTO_ONCE ex_data_init = CRYPTO_ONCE_STATIC_INIT; -static void do_ex_data_init(void) +DEFINE_RUN_ONCE_STATIC(do_ex_data_init) { - ex_data_lock = CRYPTO_THREAD_lock_new(); + OPENSSL_init_crypto(0, NULL); + ex_data_lock = CRYPTO_THREAD_glock_new("ex_data"); + return ex_data_lock != NULL; } /* @@ -53,7 +55,10 @@ static EX_CALLBACKS *get_and_lock(int class_index) return NULL; } - CRYPTO_THREAD_run_once(&ex_data_init, do_ex_data_init); + if (!RUN_ONCE(&ex_data_init, do_ex_data_init)) { + CRYPTOerr(CRYPTO_F_GET_AND_LOCK, ERR_R_MALLOC_FAILURE); + return NULL; + } if (ex_data_lock == NULL) { /* @@ -114,11 +119,11 @@ static void dummy_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, { } -static int dummy_dup(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, +static int dummy_dup(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from, void *from_d, int idx, long argl, void *argp) { - return 0; + return 1; } int CRYPTO_free_ex_index(int class_index, int idx) @@ -245,13 +250,14 @@ int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) * for each index in the class used by this variable */ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, - CRYPTO_EX_DATA *from) + const CRYPTO_EX_DATA *from) { int mx, j, i; - char *ptr; + void *ptr; EX_CALLBACK *stack[10]; EX_CALLBACK **storage = NULL; EX_CALLBACKS *ip; + int toret = 0; if (from->sk == NULL) /* Nothing to copy over */ @@ -274,21 +280,35 @@ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, } CRYPTO_THREAD_unlock(ex_data_lock); - if (mx > 0 && storage == NULL) { + if (mx == 0) + return 1; + if (storage == NULL) { CRYPTOerr(CRYPTO_F_CRYPTO_DUP_EX_DATA, ERR_R_MALLOC_FAILURE); return 0; } + /* + * Make sure the ex_data stack is at least |mx| elements long to avoid + * issues in the for loop that follows; so go get the |mx|'th element + * (if it does not exist CRYPTO_get_ex_data() returns NULL), and assign + * to itself. This is normally a no-op; but ensures the stack is the + * proper size + */ + if (!CRYPTO_set_ex_data(to, mx - 1, CRYPTO_get_ex_data(to, mx - 1))) + goto err; for (i = 0; i < mx; i++) { ptr = CRYPTO_get_ex_data(from, i); if (storage[i] && storage[i]->dup_func) - storage[i]->dup_func(to, from, &ptr, i, - storage[i]->argl, storage[i]->argp); + if (!storage[i]->dup_func(to, from, &ptr, i, + storage[i]->argl, storage[i]->argp)) + goto err; CRYPTO_set_ex_data(to, i, ptr); } + toret = 1; + err: if (storage != stack) OPENSSL_free(storage); - return 1; + return toret; } @@ -301,11 +321,12 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) int mx, i; EX_CALLBACKS *ip; void *ptr; + EX_CALLBACK *f; EX_CALLBACK *stack[10]; EX_CALLBACK **storage = NULL; if ((ip = get_and_lock(class_index)) == NULL) - return; + goto err; mx = sk_EX_CALLBACK_num(ip->meth); if (mx > 0) { @@ -319,20 +340,23 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) } CRYPTO_THREAD_unlock(ex_data_lock); - if (mx > 0 && storage == NULL) { - CRYPTOerr(CRYPTO_F_CRYPTO_FREE_EX_DATA, ERR_R_MALLOC_FAILURE); - return; - } for (i = 0; i < mx; i++) { - if (storage[i] && storage[i]->free_func) { + if (storage != NULL) + f = storage[i]; + else { + CRYPTO_THREAD_write_lock(ex_data_lock); + f = sk_EX_CALLBACK_value(ip->meth, i); + CRYPTO_THREAD_unlock(ex_data_lock); + } + if (f != NULL && f->free_func != NULL) { ptr = CRYPTO_get_ex_data(ad, i); - storage[i]->free_func(obj, ptr, ad, i, - storage[i]->argl, storage[i]->argp); + f->free_func(obj, ptr, ad, i, f->argl, f->argp); } } if (storage != stack) OPENSSL_free(storage); + err: sk_void_free(ad->sk); ad->sk = NULL; }