From 1f9329aaf55f9beb7c95550f5f1fffc395a5f859 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Fri, 13 May 2016 17:00:49 -0400 Subject: [PATCH] Add BUF_MEM_reserve. BUF_MEM is actually a rather silly API for the SSL stack. There's separate length and max fields, but init_buf effectively treats length as max and max as nothing. We possibly don't want to be using it long-term anyway (if nothing else, the char*/uint8_t* thing is irritating), but in the meantime, it'll be easier to separately fix up get_message's book-keeping and state tracking from where the handshake gets its messages from. Change-Id: I9e56ea008173991edc8312ec707505ead410a9ee Reviewed-on: https://boringssl-review.googlesource.com/7947 Reviewed-by: Adam Langley --- crypto/buf/buf.c | 46 +++++++++++++++++++++++-------------------- include/openssl/buf.h | 4 ++++ 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/crypto/buf/buf.c b/crypto/buf/buf.c index b918f01f..efe9952a 100644 --- a/crypto/buf/buf.c +++ b/crypto/buf/buf.c @@ -88,34 +88,26 @@ void BUF_MEM_free(BUF_MEM *buf) { OPENSSL_free(buf); } -static size_t buf_mem_grow(BUF_MEM *buf, size_t len, char clean) { - char *new_buf; - size_t n, alloc_size; - - if (buf->length >= len) { - buf->length = len; - return len; - } - if (buf->max >= len) { - memset(&buf->data[buf->length], 0, len - buf->length); - buf->length = len; - return len; +static int buf_mem_reserve(BUF_MEM *buf, size_t cap, int clean) { + if (buf->max >= cap) { + return 1; } - n = len + 3; - if (n < len) { + size_t n = cap + 3; + if (n < cap) { /* overflow */ OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE); return 0; } n = n / 3; - alloc_size = n * 4; + size_t alloc_size = n * 4; if (alloc_size / 4 != n) { /* overflow */ OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE); return 0; } + char *new_buf; if (buf->data == NULL) { new_buf = OPENSSL_malloc(alloc_size); } else { @@ -128,14 +120,26 @@ static size_t buf_mem_grow(BUF_MEM *buf, size_t len, char clean) { if (new_buf == NULL) { OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE); - len = 0; - } else { - buf->data = new_buf; - buf->max = alloc_size; - memset(&buf->data[buf->length], 0, len - buf->length); - buf->length = len; + return 0; } + buf->data = new_buf; + buf->max = alloc_size; + return 1; +} + +int BUF_MEM_reserve(BUF_MEM *buf, size_t cap) { + return buf_mem_reserve(buf, cap, 0 /* don't clear old buffer contents. */); +} + +static size_t buf_mem_grow(BUF_MEM *buf, size_t len, int clean) { + if (!buf_mem_reserve(buf, len, clean)) { + return 0; + } + if (buf->length < len) { + memset(&buf->data[buf->length], 0, len - buf->length); + } + buf->length = len; return len; } diff --git a/include/openssl/buf.h b/include/openssl/buf.h index f4e315cd..8ae856b6 100644 --- a/include/openssl/buf.h +++ b/include/openssl/buf.h @@ -80,6 +80,10 @@ OPENSSL_EXPORT BUF_MEM *BUF_MEM_new(void); /* BUF_MEM_free frees |buf->data| if needed and then frees |buf| itself. */ OPENSSL_EXPORT void BUF_MEM_free(BUF_MEM *buf); +/* BUF_MEM_reserve ensures |buf| has capacity |cap| and allocates memory if + * needed. It returns one on success and zero on error. */ +OPENSSL_EXPORT int BUF_MEM_reserve(BUF_MEM *buf, size_t cap); + /* BUF_MEM_grow ensures that |buf| has length |len| and allocates memory if * needed. If the length of |buf| increased, the new bytes are filled with * zeros. It returns the length of |buf|, or zero if there's an error. */