Commit f61216ba authored by Alessandro Ghedini's avatar Alessandro Ghedini Committed by Emilia Kasper
Browse files

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: default avatarMatt Caswell <matt@openssl.org>
(cherry picked from commit 110f7b37)
parent c038e6b5
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@

#include <stdio.h>
#include "cryptlib.h"
#include <limits.h>
#include <openssl/buffer.h>

size_t BUF_strnlen(const char *str, size_t maxlen)
@@ -85,12 +86,18 @@ char *BUF_strndup(const char *str, size_t siz)

    siz = BUF_strnlen(str, siz);

    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);
}

+6 −0
Original line number Diff line number Diff line
@@ -86,7 +86,13 @@ int BUF_MEM_grow(BUF_MEM *str, size_t len);
int BUF_MEM_grow_clean(BUF_MEM *str, size_t len);
size_t BUF_strnlen(const char *str, size_t maxlen);
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);