diff options
author | Daiki Ueno <ueno@gnu.org> | 2021-03-30 12:54:04 +0000 |
---|---|---|
committer | Daiki Ueno <ueno@gnu.org> | 2021-03-30 12:54:04 +0000 |
commit | a6a45ad0a75e950119e8e529a5f7f505ce0311c7 (patch) | |
tree | 1be10204a0cd6e457965b0e3af1f6ae6c70d01f1 | |
parent | a28a915f4ad820360cdbaaa83d98df206e2f00b7 (diff) | |
parent | 043d1bc387238139a4c2b7f7a6fffdac97ab2b73 (diff) | |
download | gnutls-a6a45ad0a75e950119e8e529a5f7f505ce0311c7.tar.gz |
Merge branch 'wip/dueno/reallocarray' into 'master'
build: avoid potential integer overflow in array allocation
Closes #1179
See merge request gnutls/gnutls!1392
-rw-r--r-- | bootstrap.conf | 2 | ||||
-rw-r--r-- | lib/cert-cred-x509.c | 23 | ||||
-rw-r--r-- | lib/cert-cred.c | 23 | ||||
-rw-r--r-- | lib/hello_ext.c | 9 | ||||
-rw-r--r-- | lib/mem.c | 33 | ||||
-rw-r--r-- | lib/mem.h | 8 | ||||
-rw-r--r-- | lib/pcert.c | 3 | ||||
-rw-r--r-- | lib/pkcs11.c | 17 | ||||
-rw-r--r-- | lib/pkcs11x.c | 14 | ||||
-rw-r--r-- | lib/supplemental.c | 9 | ||||
-rw-r--r-- | lib/x509/crl.c | 7 | ||||
-rw-r--r-- | lib/x509/ocsp.c | 22 | ||||
-rw-r--r-- | lib/x509/pkcs12.c | 25 | ||||
-rw-r--r-- | lib/x509/verify-high.c | 83 | ||||
-rw-r--r-- | lib/x509/verify-high2.c | 6 | ||||
-rw-r--r-- | lib/x509/x509.c | 9 | ||||
-rw-r--r-- | lib/x509/x509_ext.c | 28 |
17 files changed, 219 insertions, 102 deletions
diff --git a/bootstrap.conf b/bootstrap.conf index 271b51f143..f7bdde1025 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -27,7 +27,7 @@ required_submodules="tests/suite/tls-fuzzer/python-ecdsa tests/suite/tls-fuzzer/ # Those modules are common to lib/ and src/. common_modules=" -alloca attribute byteswap c-ctype c-strcase explicit_bzero fopen-gnu func getline gettext-h gettimeofday hash hash-pjw-bare arpa_inet inet_ntop inet_pton intprops memmem-simple minmax netdb netinet_in read-file secure_getenv setsockopt snprintf stdint stpcpy strcase strdup-posix strndup strtok_r strverscmp sys_socket sys_stat sys_types threadlib time_r unistd valgrind-tests vasprintf verify vsnprintf +alloca attribute byteswap c-ctype c-strcase explicit_bzero fopen-gnu func getline gettext-h gettimeofday hash hash-pjw-bare arpa_inet inet_ntop inet_pton intprops memmem-simple minmax netdb netinet_in read-file secure_getenv setsockopt snprintf stdint stpcpy strcase strdup-posix strndup strtok_r strverscmp sys_socket sys_stat sys_types threadlib time_r unistd valgrind-tests vasprintf verify vsnprintf xalloc-oversized " gnulib_modules=" $common_modules extensions gendocs havelib ldd lib-msvc-compat lib-symbol-versions maintainer-makefile manywarnings pmccabe2html warnings diff --git a/lib/cert-cred-x509.c b/lib/cert-cred-x509.c index 1b44f3a634..543a1155f4 100644 --- a/lib/cert-cred-x509.c +++ b/lib/cert-cred-x509.c @@ -254,7 +254,7 @@ parse_pem_cert_mem(gnutls_certificate_credentials_t res, goto cleanup; } - pcerts = gnutls_malloc(sizeof(gnutls_pcert_st) * count); + pcerts = _gnutls_reallocarray(NULL, count, sizeof(gnutls_pcert_st)); if (pcerts == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; @@ -441,7 +441,8 @@ read_cert_url(gnutls_certificate_credentials_t res, gnutls_privkey_t key, const _gnutls_str_array_init(&names); - ccert = gnutls_malloc(sizeof(*ccert)*MAX_PKCS11_CERT_CHAIN); + ccert = _gnutls_reallocarray(NULL, MAX_PKCS11_CERT_CHAIN, + sizeof(*ccert)); if (ccert == NULL) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; @@ -770,7 +771,8 @@ gnutls_certificate_set_x509_key(gnutls_certificate_credentials_t res, } /* load certificates */ - pcerts = gnutls_malloc(sizeof(gnutls_pcert_st) * cert_list_size); + pcerts = _gnutls_reallocarray(NULL, cert_list_size, + sizeof(gnutls_pcert_st)); if (pcerts == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; @@ -901,8 +903,9 @@ gnutls_certificate_get_x509_crt(gnutls_certificate_credentials_t res, } *crt_list_size = res->certs[index].cert_list_length; - *crt_list = gnutls_malloc( - res->certs[index].cert_list_length * sizeof (gnutls_x509_crt_t)); + *crt_list = _gnutls_reallocarray(NULL, + res->certs[index].cert_list_length, + sizeof (gnutls_x509_crt_t)); if (*crt_list == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; @@ -1151,7 +1154,8 @@ gnutls_certificate_set_x509_trust(gnutls_certificate_credentials_t res, if (ca_list == NULL || ca_list_size < 1) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); - new_list = gnutls_malloc(ca_list_size * sizeof(gnutls_x509_crt_t)); + new_list = _gnutls_reallocarray(NULL, ca_list_size, + sizeof(gnutls_x509_crt_t)); if (!new_list) return GNUTLS_E_MEMORY_ERROR; @@ -1335,12 +1339,15 @@ gnutls_certificate_set_x509_crl(gnutls_certificate_credentials_t res, int crl_list_size) { int ret, i, j; - gnutls_x509_crl_t *new_crl = gnutls_malloc(crl_list_size * sizeof(gnutls_x509_crl_t)); - unsigned flags = GNUTLS_TL_USE_IN_TLS; + gnutls_x509_crl_t *new_crl; + unsigned flags; + flags = GNUTLS_TL_USE_IN_TLS; if (res->flags & GNUTLS_CERTIFICATE_VERIFY_CRLS) flags |= GNUTLS_TL_VERIFY_CRL|GNUTLS_TL_FAIL_ON_INVALID_CRL; + new_crl = _gnutls_reallocarray(NULL, crl_list_size, + sizeof(gnutls_x509_crl_t)); if (!new_crl) return GNUTLS_E_MEMORY_ERROR; diff --git a/lib/cert-cred.c b/lib/cert-cred.c index 28b67f60df..c9c5f6ed50 100644 --- a/lib/cert-cred.c +++ b/lib/cert-cred.c @@ -43,6 +43,7 @@ #include "x509/common.h" #include "dh.h" #include "cert-cred.h" +#include "intprops.h" /* @@ -55,15 +56,19 @@ _gnutls_certificate_credential_append_keypair(gnutls_certificate_credentials_t r gnutls_pcert_st * crt, int nr) { - res->sorted_cert_idx = gnutls_realloc_fast(res->sorted_cert_idx, - (1 + res->ncerts) * - sizeof(unsigned int)); + if (unlikely(INT_ADD_OVERFLOW(res->ncerts, 1))) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } + + res->sorted_cert_idx = _gnutls_reallocarray_fast(res->sorted_cert_idx, + res->ncerts + 1, + sizeof(unsigned int)); if (res->sorted_cert_idx == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); - res->certs = gnutls_realloc_fast(res->certs, - (1 + res->ncerts) * - sizeof(certs_st)); + res->certs = _gnutls_reallocarray_fast(res->certs, + res->ncerts + 1, + sizeof(certs_st)); if (res->certs == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); @@ -204,7 +209,8 @@ gnutls_certificate_set_key(gnutls_certificate_credentials_t res, gnutls_privkey_set_pin_function(key, res->pin.cb, res->pin.data); - new_pcert_list = gnutls_malloc(sizeof(gnutls_pcert_st) * pcert_list_size); + new_pcert_list = _gnutls_reallocarray(NULL, pcert_list_size, + sizeof(gnutls_pcert_st)); if (new_pcert_list == NULL) { return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); } @@ -451,7 +457,8 @@ static gnutls_pcert_st *alloc_and_load_x509_certs(gnutls_x509_crt_t * if (certs == NULL) return NULL; - local_certs = gnutls_malloc(sizeof(gnutls_pcert_st) * ncerts); + local_certs = _gnutls_reallocarray(NULL, ncerts, + sizeof(gnutls_pcert_st)); if (local_certs == NULL) { gnutls_assert(); return NULL; diff --git a/lib/hello_ext.c b/lib/hello_ext.c index dbe73fdeb3..32385f4c0e 100644 --- a/lib/hello_ext.c +++ b/lib/hello_ext.c @@ -57,6 +57,7 @@ #include <num.h> #include <ext/client_cert_type.h> #include <ext/server_cert_type.h> +#include "intprops.h" static void unset_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *, unsigned idx); @@ -923,7 +924,13 @@ gnutls_session_ext_register(gnutls_session_t session, tmp_mod.validity |= GNUTLS_EXT_FLAG_TLS; } - exts = gnutls_realloc(session->internals.rexts, (session->internals.rexts_size+1)*sizeof(*exts)); + if (unlikely(INT_ADD_OVERFLOW(session->internals.rexts_size, 1))) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } + + exts = _gnutls_reallocarray(session->internals.rexts, + session->internals.rexts_size + 1, + sizeof(*exts)); if (exts == NULL) { return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); } @@ -23,7 +23,7 @@ #include "gnutls_int.h" #include "errors.h" #include <num.h> -#include <xsize.h> +#include "xalloc-oversized.h" gnutls_alloc_function gnutls_secure_malloc = malloc; gnutls_alloc_function gnutls_malloc = malloc; @@ -33,27 +33,34 @@ gnutls_realloc_function gnutls_realloc = realloc; void *(*gnutls_calloc) (size_t, size_t) = calloc; char *(*gnutls_strdup) (const char *) = _gnutls_strdup; -void *_gnutls_calloc(size_t nmemb, size_t size) +/* This realloc will free ptr in case realloc + * fails. + */ +void *gnutls_realloc_fast(void *ptr, size_t size) { void *ret; - size_t n = xtimes(nmemb, size); - ret = (size_in_bounds_p(n) ? gnutls_malloc(n) : NULL); - if (ret != NULL) - memset(ret, 0, size); + + if (size == 0) + return ptr; + + ret = gnutls_realloc(ptr, size); + if (ret == NULL) { + gnutls_free(ptr); + } + return ret; } -/* This realloc will free ptr in case realloc - * fails. +/* This will free ptr in case reallocarray fails. */ -void *gnutls_realloc_fast(void *ptr, size_t size) +void *_gnutls_reallocarray_fast(void *ptr, size_t nmemb, size_t size) { void *ret; if (size == 0) return ptr; - ret = gnutls_realloc(ptr, size); + ret = _gnutls_reallocarray(ptr, nmemb, size); if (ret == NULL) { gnutls_free(ptr); } @@ -77,6 +84,12 @@ char *_gnutls_strdup(const char *str) return ret; } +void *_gnutls_reallocarray(void *ptr, size_t nmemb, size_t size) +{ + return xalloc_oversized(nmemb, size) ? NULL : + gnutls_realloc(ptr, nmemb * size); +} + #if 0 /* don't use them. They are included for documentation. */ @@ -25,14 +25,16 @@ #include <config.h> -/* this realloc function will return ptr if size==0, and - * will free the ptr if the new allocation failed. +/* These realloc functions will return ptr if size==0, and will free + * the ptr if the new allocation failed. */ void *gnutls_realloc_fast(void *ptr, size_t size); +void *_gnutls_reallocarray_fast(void *ptr, size_t nmemb, size_t size); -void *_gnutls_calloc(size_t nmemb, size_t size); char *_gnutls_strdup(const char *); +void *_gnutls_reallocarray(void *, size_t, size_t); + unsigned _gnutls_mem_is_zero(const uint8_t *ptr, unsigned size); #define zrelease_mpi_key(mpi) if (*mpi!=NULL) { \ diff --git a/lib/pcert.c b/lib/pcert.c index 89d3d40e63..e5057aec51 100644 --- a/lib/pcert.c +++ b/lib/pcert.c @@ -185,7 +185,8 @@ gnutls_pcert_list_import_x509_raw(gnutls_pcert_st *pcert_list, unsigned int i = 0, j; gnutls_x509_crt_t *crt; - crt = gnutls_malloc((*pcert_list_size) * sizeof(gnutls_x509_crt_t)); + crt = _gnutls_reallocarray(NULL, *pcert_list_size, + sizeof(gnutls_x509_crt_t)); if (crt == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); diff --git a/lib/pkcs11.c b/lib/pkcs11.c index 0d5e83a0c6..364c0c49a9 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -40,6 +40,7 @@ #include "x509/x509_int.h" #include <atfork.h> +#include "intprops.h" #define MAX_PROVIDERS 16 @@ -3059,8 +3060,8 @@ find_privkeys(struct pkcs11_session_info *sinfo, return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } - list->key_ids = - gnutls_malloc(sizeof(gnutls_buffer_st) * list->key_ids_size); + list->key_ids = _gnutls_reallocarray(NULL, list->key_ids_size, + sizeof(gnutls_buffer_st)); if (list->key_ids == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; @@ -3277,7 +3278,7 @@ find_multi_objs_cb(struct ck_function_list *module, struct pkcs11_session_info * return pkcs11_rv_to_err(rv); } - ctx = gnutls_malloc(OBJECTS_A_TIME*sizeof(ctx[0])); + ctx = _gnutls_reallocarray(NULL, OBJECTS_A_TIME, sizeof(ctx[0])); if (ctx == NULL) { ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); goto fail; @@ -3291,7 +3292,15 @@ find_multi_objs_cb(struct ck_function_list *module, struct pkcs11_session_info * unsigned j; gnutls_datum_t id; - find_data->p_list = gnutls_realloc_fast(find_data->p_list, (find_data->current+count)*sizeof(find_data->p_list[0])); + if (unlikely(INT_ADD_OVERFLOW(find_data->current, count))) { + ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + goto fail; + } + + find_data->p_list = + _gnutls_reallocarray_fast(find_data->p_list, + find_data->current + count, + sizeof(find_data->p_list[0])); if (find_data->p_list == NULL) { ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); goto fail; diff --git a/lib/pkcs11x.c b/lib/pkcs11x.c index 0041b924cb..dfaee58a39 100644 --- a/lib/pkcs11x.c +++ b/lib/pkcs11x.c @@ -28,6 +28,7 @@ #include <pkcs11_int.h> #include <p11-kit/p11-kit.h> #include "pkcs11x.h" +#include "intprops.h" struct find_ext_data_st { /* in */ @@ -217,10 +218,17 @@ find_ext_cb(struct ck_function_list *module, struct pkcs11_session_info *sinfo, rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, obj, CKA_VALUE, &ext); if (rv == CKR_OK) { - find_data->exts = gnutls_realloc_fast(find_data->exts, (1+find_data->exts_size)*sizeof(find_data->exts[0])); + if (unlikely(INT_ADD_OVERFLOW(find_data->exts_size, 1))) { + ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + goto cleanup; + } + + find_data->exts = + _gnutls_reallocarray_fast(find_data->exts, + find_data->exts_size + 1, + sizeof(find_data->exts[0])); if (find_data->exts == NULL) { - gnutls_assert(); - ret = pkcs11_rv_to_err(rv); + ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); goto cleanup; } diff --git a/lib/supplemental.c b/lib/supplemental.c index 07b38cc938..becb01e50c 100644 --- a/lib/supplemental.c +++ b/lib/supplemental.c @@ -48,6 +48,7 @@ #include "supplemental.h" #include "errors.h" #include "num.h" +#include "intprops.h" typedef struct gnutls_supplemental_entry_st { char *name; @@ -252,8 +253,12 @@ _gnutls_supplemental_register(gnutls_supplemental_entry_st *entry) return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED); } - p = gnutls_realloc_fast(suppfunc, - sizeof(*suppfunc) * (suppfunc_size + 1)); + if (unlikely(INT_ADD_OVERFLOW(suppfunc_size, 1))) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } + + p = _gnutls_reallocarray_fast(suppfunc, suppfunc_size + 1, + sizeof(*suppfunc)); if (!p) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; diff --git a/lib/x509/crl.c b/lib/x509/crl.c index 8705be3b6c..aea8bc6d33 100644 --- a/lib/x509/crl.c +++ b/lib/x509/crl.c @@ -1262,7 +1262,7 @@ gnutls_x509_crl_list_import2(gnutls_x509_crl_t ** crls, unsigned int init = 1024; int ret; - *crls = gnutls_malloc(sizeof(gnutls_x509_crl_t) * init); + *crls = _gnutls_reallocarray(NULL, init, sizeof(gnutls_x509_crl_t)); if (*crls == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; @@ -1272,9 +1272,8 @@ gnutls_x509_crl_list_import2(gnutls_x509_crl_t ** crls, gnutls_x509_crl_list_import(*crls, &init, data, format, flags | GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED); if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { - *crls = - gnutls_realloc_fast(*crls, - sizeof(gnutls_x509_crl_t) * init); + *crls = _gnutls_reallocarray_fast(*crls, init, + sizeof(gnutls_x509_crl_t)); if (*crls == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; diff --git a/lib/x509/ocsp.c b/lib/x509/ocsp.c index 0c71a6e462..e750ac4724 100644 --- a/lib/x509/ocsp.c +++ b/lib/x509/ocsp.c @@ -38,6 +38,7 @@ #include <auth/cert.h> #include <assert.h> +#include "intprops.h" typedef struct gnutls_ocsp_req_int { ASN1_TYPE req; @@ -1905,9 +1906,13 @@ gnutls_ocsp_resp_get_certs(gnutls_ocsp_resp_const_t resp, goto error; } - tmpcerts2 = - gnutls_realloc_fast(tmpcerts, - (ctr + 2) * sizeof(*tmpcerts)); + if (unlikely(INT_ADD_OVERFLOW(ctr, 2))) { + ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + goto error; + } + + tmpcerts2 = _gnutls_reallocarray_fast(tmpcerts, ctr + 2, + sizeof(*tmpcerts)); if (tmpcerts2 == NULL) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; @@ -2458,7 +2463,14 @@ gnutls_ocsp_resp_list_import2(gnutls_ocsp_resp_t **ocsps, goto fail; } - new_ocsps = gnutls_realloc(*ocsps, (*size + 1)*sizeof(gnutls_ocsp_resp_t)); + if (unlikely(INT_ADD_OVERFLOW(*size, 1))) { + ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + goto fail; + } + + new_ocsps = _gnutls_reallocarray(*ocsps, + *size + 1, + sizeof(gnutls_ocsp_resp_t)); if (new_ocsps == NULL) { resp = NULL; gnutls_assert(); @@ -2492,7 +2504,7 @@ gnutls_ocsp_resp_list_import2(gnutls_ocsp_resp_t **ocsps, goto cleanup; } - *ocsps = gnutls_malloc(1*sizeof(gnutls_ocsp_resp_t)); + *ocsps = gnutls_malloc(sizeof(gnutls_ocsp_resp_t)); if (*ocsps == NULL) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c index 2dc0823905..965de6fe02 100644 --- a/lib/x509/pkcs12.c +++ b/lib/x509/pkcs12.c @@ -37,6 +37,7 @@ #include "x509_int.h" #include "pkcs7_int.h" #include <random.h> +#include "intprops.h" /* Decodes the PKCS #12 auth_safe, and returns the allocated raw data, @@ -1455,10 +1456,13 @@ static int make_chain(gnutls_x509_crt_t ** chain, unsigned int *chain_len, != 0) goto skip; - *chain = - gnutls_realloc_fast(*chain, - sizeof((*chain)[0]) * - ++(*chain_len)); + if (unlikely(INT_ADD_OVERFLOW(*chain_len, 1))) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } + + *chain = _gnutls_reallocarray_fast(*chain, + ++(*chain_len), + sizeof((*chain)[0])); if (*chain == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; @@ -1778,12 +1782,15 @@ gnutls_pkcs12_simple_parse(gnutls_pkcs12_t p12, } if (memcmp(cert_id, key_id, cert_id_size) != 0) { /* they don't match - skip the certificate */ + if (unlikely(INT_ADD_OVERFLOW(_extra_certs_len, 1))) { + ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + goto done; + } + _extra_certs = - gnutls_realloc_fast - (_extra_certs, - sizeof(_extra_certs - [0]) * - ++_extra_certs_len); + _gnutls_reallocarray_fast(_extra_certs, + ++_extra_certs_len, + sizeof(_extra_certs[0])); if (!_extra_certs) { gnutls_assert(); ret = diff --git a/lib/x509/verify-high.c b/lib/x509/verify-high.c index 736326ee18..ab8e006ca7 100644 --- a/lib/x509/verify-high.c +++ b/lib/x509/verify-high.c @@ -34,6 +34,7 @@ #include <common.h> #include <gnutls/x509-ext.h> #include "verify-high.h" +#include "intprops.h" struct named_cert_st { gnutls_x509_crt_t cert; @@ -128,10 +129,14 @@ cert_set_add(struct cert_set_st *set, const gnutls_x509_crt_t cert) hash = hash_pjw_bare(cert->raw_dn.data, cert->raw_dn.size); hash %= set->size; + if (unlikely(INT_ADD_OVERFLOW(set->node[hash].size, 1))) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } + set->node[hash].certs = - gnutls_realloc_fast(set->node[hash].certs, - (set->node[hash].size + 1) * - sizeof(*set->node[hash].certs)); + _gnutls_reallocarray_fast(set->node[hash].certs, + set->node[hash].size + 1, + sizeof(*set->node[hash].certs)); if (!set->node[hash].certs) { return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); } @@ -297,11 +302,14 @@ static int trust_list_add_compat(gnutls_x509_trust_list_t list, gnutls_x509_crt_t cert) { + if (unlikely(INT_ADD_OVERFLOW(list->keep_certs_size, 1))) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } + list->keep_certs = - gnutls_realloc_fast(list->keep_certs, - (list->keep_certs_size + - 1) * - sizeof(list->keep_certs[0])); + _gnutls_reallocarray_fast(list->keep_certs, + list->keep_certs_size + 1, + sizeof(list->keep_certs[0])); if (list->keep_certs == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; @@ -379,12 +387,15 @@ gnutls_x509_trust_list_add_cas(gnutls_x509_trust_list_t list, } } + if (unlikely(INT_ADD_OVERFLOW(list->node[hash].trusted_ca_size, 1))) { + gnutls_assert(); + return i; + } + list->node[hash].trusted_cas = - gnutls_realloc_fast(list->node[hash].trusted_cas, - (list->node[hash].trusted_ca_size + - 1) * - sizeof(list->node[hash]. - trusted_cas[0])); + _gnutls_reallocarray_fast(list->node[hash].trusted_cas, + list->node[hash].trusted_ca_size + 1, + sizeof(list->node[hash].trusted_cas[0])); if (list->node[hash].trusted_cas == NULL) { gnutls_assert(); return i; @@ -666,14 +677,18 @@ gnutls_x509_trust_list_remove_cas(gnutls_x509_trust_list_t list, } } + if (unlikely(INT_ADD_OVERFLOW(list->blacklisted_size, 1))) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } + /* Add the CA (or plain) certificate to the black list as well. * This will prevent a subordinate CA from being valid, and * ensure that a server certificate will also get rejected. */ list->blacklisted = - gnutls_realloc_fast(list->blacklisted, - (list->blacklisted_size + 1) * - sizeof(list->blacklisted[0])); + _gnutls_reallocarray_fast(list->blacklisted, + list->blacklisted_size + 1, + sizeof(list->blacklisted[0])); if (list->blacklisted == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); @@ -728,11 +743,14 @@ gnutls_x509_trust_list_add_named_crt(gnutls_x509_trust_list_t list, cert->raw_issuer_dn.size); hash %= list->size; + if (unlikely(INT_ADD_OVERFLOW(list->node[hash].named_cert_size, 1))) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } + list->node[hash].named_certs = - gnutls_realloc_fast(list->node[hash].named_certs, - (list->node[hash].named_cert_size + - 1) * - sizeof(list->node[hash].named_certs[0])); + _gnutls_reallocarray_fast(list->node[hash].named_certs, + list->node[hash].named_cert_size + 1, + sizeof(list->node[hash].named_certs[0])); if (list->node[hash].named_certs == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); @@ -842,19 +860,17 @@ gnutls_x509_trust_list_add_crls(gnutls_x509_trust_list_t list, } } - tmp = - gnutls_realloc(list->node[hash].crls, - (list->node[hash].crl_size + - 1) * - sizeof(list->node[hash]. - crls[0])); + if (unlikely(INT_ADD_OVERFLOW(list->node[hash].crl_size, 1))) { + gnutls_assert(); + goto error; + } + + tmp = _gnutls_reallocarray(list->node[hash].crls, + list->node[hash].crl_size + 1, + sizeof(list->node[hash].crls[0])); if (tmp == NULL) { - ret = i; gnutls_assert(); - if (flags & GNUTLS_TL_NO_DUPLICATES) - while (i < crl_size) - gnutls_x509_crl_deinit(crl_list[i++]); - return ret; + goto error; } list->node[hash].crls = tmp; @@ -868,6 +884,13 @@ gnutls_x509_trust_list_add_crls(gnutls_x509_trust_list_t list, } return j; + + error: + ret = i; + if (flags & GNUTLS_TL_NO_DUPLICATES) + while (i < crl_size) + gnutls_x509_crl_deinit(crl_list[i++]); + return ret; } /* Takes a certificate list and shortens it if there are diff --git a/lib/x509/verify-high2.c b/lib/x509/verify-high2.c index 9820595e97..16d757cf8a 100644 --- a/lib/x509/verify-high2.c +++ b/lib/x509/verify-high2.c @@ -216,7 +216,8 @@ int add_trust_list_pkcs11_object_url(gnutls_x509_trust_list_t list, const char * goto cleanup; } - xcrt_list = gnutls_malloc(sizeof(gnutls_x509_crt_t) * pcrt_list_size); + xcrt_list = _gnutls_reallocarray(NULL, pcrt_list_size, + sizeof(gnutls_x509_crt_t)); if (xcrt_list == NULL) { ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; @@ -264,7 +265,8 @@ int remove_pkcs11_object_url(gnutls_x509_trust_list_t list, const char *url) goto cleanup; } - xcrt_list = gnutls_malloc(sizeof(gnutls_x509_crt_t) * pcrt_list_size); + xcrt_list = _gnutls_reallocarray(NULL, pcrt_list_size, + sizeof(gnutls_x509_crt_t)); if (xcrt_list == NULL) { ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; diff --git a/lib/x509/x509.c b/lib/x509/x509.c index c3801a83f2..4e494d10e0 100644 --- a/lib/x509/x509.c +++ b/lib/x509/x509.c @@ -3700,7 +3700,7 @@ gnutls_x509_crt_list_import2(gnutls_x509_crt_t ** certs, unsigned int init = 1024; int ret; - *certs = gnutls_malloc(sizeof(gnutls_x509_crt_t) * init); + *certs = _gnutls_reallocarray(NULL, init, sizeof(gnutls_x509_crt_t)); if (*certs == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; @@ -3710,9 +3710,8 @@ gnutls_x509_crt_list_import2(gnutls_x509_crt_t ** certs, gnutls_x509_crt_list_import(*certs, &init, data, format, flags | GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED); if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { - *certs = - gnutls_realloc_fast(*certs, - sizeof(gnutls_x509_crt_t) * init); + *certs = _gnutls_reallocarray_fast(*certs, init, + sizeof(gnutls_x509_crt_t)); if (*certs == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; @@ -4375,7 +4374,7 @@ gnutls_x509_crt_list_import_url(gnutls_x509_crt_t **certs, gnutls_free(issuer.data); } - *certs = gnutls_malloc(total*sizeof(gnutls_x509_crt_t)); + *certs = _gnutls_reallocarray(NULL, total, sizeof(gnutls_x509_crt_t)); if (*certs == NULL) { ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; diff --git a/lib/x509/x509_ext.c b/lib/x509/x509_ext.c index 6aeb159dba..387f5fbea2 100644 --- a/lib/x509/x509_ext.c +++ b/lib/x509/x509_ext.c @@ -31,6 +31,7 @@ #include "x509_ext_int.h" #include "virt-san.h" #include <gnutls/x509-ext.h> +#include "intprops.h" #define MAX_ENTRIES 64 struct gnutls_subject_alt_names_st { @@ -137,7 +138,11 @@ int subject_alt_names_set(struct name_st **names, void *tmp; int ret; - tmp = gnutls_realloc(*names, (*size + 1) * sizeof((*names)[0])); + if (unlikely(INT_ADD_OVERFLOW(*size, 1))) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } + + tmp = _gnutls_reallocarray(*names, *size + 1, sizeof((*names)[0])); if (tmp == NULL) { return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); } @@ -2316,10 +2321,13 @@ int crl_dist_points_set(gnutls_x509_crl_dist_points_t cdp, { void *tmp; + if (unlikely(INT_ADD_OVERFLOW(cdp->size, 1))) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } + /* new dist point */ - tmp = - gnutls_realloc(cdp->points, - (cdp->size + 1) * sizeof(cdp->points[0])); + tmp = _gnutls_reallocarray(cdp->points, cdp->size + 1, + sizeof(cdp->points[0])); if (tmp == NULL) { return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); } @@ -2734,7 +2742,11 @@ int gnutls_x509_aia_set(gnutls_x509_aia_t aia, void *tmp; unsigned indx; - tmp = gnutls_realloc(aia->aia, (aia->size + 1) * sizeof(aia->aia[0])); + if (unlikely(INT_ADD_OVERFLOW(aia->size, 1))) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } + + tmp = _gnutls_reallocarray(aia->aia, aia->size + 1, sizeof(aia->aia[0])); if (tmp == NULL) { return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); } @@ -2786,7 +2798,11 @@ static int parse_aia(ASN1_TYPE c2, gnutls_x509_aia_t aia) } indx = aia->size; - tmp = gnutls_realloc(aia->aia, (aia->size + 1) * sizeof(aia->aia[0])); + if (unlikely(INT_ADD_OVERFLOW(aia->size, 1))) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } + tmp = _gnutls_reallocarray(aia->aia, aia->size + 1, + sizeof(aia->aia[0])); if (tmp == NULL) { return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); } |