diff options
author | Daiki Ueno <ueno@gnu.org> | 2020-06-05 16:26:33 +0200 |
---|---|---|
committer | Dmitry Baryshkov <dbaryshkov@gmail.com> | 2020-06-14 20:33:17 +0300 |
commit | 8c07e817a1e2d7472cf52b08ae52d9f9a6a4625b (patch) | |
tree | 76cfaeebd0178ab0d5b7dd408503a42c76a2dee5 /lib | |
parent | 1cdf8d75ca1fd396049202d57b5ea545a2500acd (diff) | |
download | gnutls-8c07e817a1e2d7472cf52b08ae52d9f9a6a4625b.tar.gz |
crypto-api: always allocate memory when serializing iovec_ttmp-fix-iov-3_6
The AEAD iov interface falls back to serializing the input buffers if
the low-level cipher doesn't support scatter/gather encryption.
However, there was a bug in the functions used for the serialization,
which causes memory leaks under a certain condition (i.e. the number
of input buffers is 1).
This patch makes the logic of the functions simpler, by removing a
micro-optimization that tries to minimize the number of calls to
malloc/free.
The original problem was reported by Marius Steffen in:
https://bugzilla.samba.org/show_bug.cgi?id=14399
and the cause was investigated by Alexander Haase in:
https://gitlab.com/gnutls/gnutls/-/merge_requests/1277
Signed-off-by: Daiki Ueno <ueno@gnu.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/crypto-api.c | 36 |
1 files changed, 11 insertions, 25 deletions
diff --git a/lib/crypto-api.c b/lib/crypto-api.c index 45be64ed1f..8524f5ed4f 100644 --- a/lib/crypto-api.c +++ b/lib/crypto-api.c @@ -891,32 +891,23 @@ gnutls_aead_cipher_encrypt(gnutls_aead_cipher_hd_t handle, struct iov_store_st { void *data; size_t size; - unsigned allocated; }; static void iov_store_free(struct iov_store_st *s) { - if (s->allocated) { - gnutls_free(s->data); - s->allocated = 0; - } + gnutls_free(s->data); } static int iov_store_grow(struct iov_store_st *s, size_t length) { - if (s->allocated || s->data == NULL) { - s->size += length; - s->data = gnutls_realloc(s->data, s->size); - if (s->data == NULL) - return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); - s->allocated = 1; - } else { - void *data = s->data; - size_t size = s->size + length; - s->data = gnutls_malloc(size); - memcpy(s->data, data, s->size); - s->size += length; - } + void *data; + + s->size += length; + data = gnutls_realloc(s->data, s->size); + if (data == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + s->data = data; return 0; } @@ -926,11 +917,6 @@ copy_from_iov(struct iov_store_st *dst, const giovec_t *iov, int iovcnt) memset(dst, 0, sizeof(*dst)); if (iovcnt == 0) { return 0; - } else if (iovcnt == 1) { - dst->data = iov[0].iov_base; - dst->size = iov[0].iov_len; - /* implies: dst->allocated = 0; */ - return 0; } else { int i; uint8_t *p; @@ -944,11 +930,11 @@ copy_from_iov(struct iov_store_st *dst, const giovec_t *iov, int iovcnt) p = dst->data; for (i=0;i<iovcnt;i++) { - memcpy(p, iov[i].iov_base, iov[i].iov_len); + if (iov[i].iov_len > 0) + memcpy(p, iov[i].iov_base, iov[i].iov_len); p += iov[i].iov_len; } - dst->allocated = 1; return 0; } } |