From 69051874889696c2064b556ad4614d2f3644258a Mon Sep 17 00:00:00 2001 From: Alessandro Ghedini Date: Wed, 16 Sep 2015 17:54:05 +0200 Subject: [PATCH] Make BUF_strndup() read-safe on arbitrary inputs BUF_strndup was calling strlen through BUF_strlcpy, and ended up reading past the input if the input was not a C string. Make it explicitly part of BUF_strndup's contract to never read more than |siz| input bytes. This augments the standard strndup contract to be safer. The commit also adds a check for siz overflow and some brief documentation for BUF_strndup(). Reviewed-by: Matt Caswell (cherry picked from commit 110f7b37de9feecfb64950601cc7cec77cf6130b) (cherry picked from commit f61216ba9d17430fb5eb3e2b202a209960b9d51b) --- crypto/buffer/buf_str.c | 9 ++++++++- crypto/buffer/buffer.h | 6 ++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/crypto/buffer/buf_str.c b/crypto/buffer/buf_str.c index fdde3d7db4..da1fea9c67 100644 --- a/crypto/buffer/buf_str.c +++ b/crypto/buffer/buf_str.c @@ -58,6 +58,7 @@ #include #include "cryptlib.h" +#include #include char *BUF_strdup(const char *str) @@ -74,12 +75,18 @@ char *BUF_strndup(const char *str, size_t siz) if (str == NULL) return (NULL); + if (siz >= INT_MAX) + return (NULL); + ret = OPENSSL_malloc(siz + 1); if (ret == NULL) { BUFerr(BUF_F_BUF_STRNDUP, ERR_R_MALLOC_FAILURE); return (NULL); } - BUF_strlcpy(ret, str, siz + 1); + + memcpy(ret, str, siz); + ret[siz] = '\0'; + return (ret); } diff --git a/crypto/buffer/buffer.h b/crypto/buffer/buffer.h index 632df93c65..0958b454be 100644 --- a/crypto/buffer/buffer.h +++ b/crypto/buffer/buffer.h @@ -85,7 +85,13 @@ void BUF_MEM_free(BUF_MEM *a); int BUF_MEM_grow(BUF_MEM *str, size_t len); int BUF_MEM_grow_clean(BUF_MEM *str, size_t len); char *BUF_strdup(const char *str); + +/* + * Returns a pointer to a new string which is a duplicate of the string |str|, + * but guarantees to never read past the first |siz| bytes of |str|. + */ char *BUF_strndup(const char *str, size_t siz); + void *BUF_memdup(const void *data, size_t siz); void BUF_reverse(unsigned char *out, const unsigned char *in, size_t siz); -- 2.25.1