summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorGuido Vranken <guidovranken@gmail.com>2016-09-08 10:43:37 +0100
committerMatt Caswell <matt@openssl.org>2016-09-19 23:31:03 +0100
commit05f754f6a6a2aaceef18069a6ce11aacdb86c84c (patch)
tree721d9c4e9b86dd15563c6aed5085670318d39b16 /crypto
parent322b739be5cae8b6cfb55e51d59c2f828ae3a993 (diff)
Prevent overflows in stack API
Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (cherry picked from commit 9731a9ce7d0f404d21ed418f9bc983b174e130cb)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/stack/stack.c50
1 files changed, 42 insertions, 8 deletions
diff --git a/crypto/stack/stack.c b/crypto/stack/stack.c
index acd350a220..25e2635fd7 100644
--- a/crypto/stack/stack.c
+++ b/crypto/stack/stack.c
@@ -39,6 +39,9 @@ OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, OPENSSL_sk_compfu
OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk)
{
OPENSSL_STACK *ret;
+ if ( sk->num_alloc < 0 || sk->num < 0 ) {
+ return NULL;
+ }
if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
return NULL;
@@ -62,6 +65,10 @@ OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk,
OPENSSL_STACK *ret;
int i;
+ if ( sk->num < 0 ) {
+ return NULL;
+ }
+
if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
return NULL;
@@ -113,21 +120,48 @@ OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc c)
int OPENSSL_sk_insert(OPENSSL_STACK *st, const void *data, int loc)
{
- const char **s;
-
- if (st == NULL)
+ if ( st == NULL || st->num < 0 || st->num == INT_MAX || st->num_alloc < 0 ) {
return 0;
+ }
+
if (st->num_alloc <= st->num + 1) {
- s = OPENSSL_realloc((char *)st->data,
- (unsigned int)sizeof(char *) * st->num_alloc * 2);
- if (s == NULL)
+
+ /* Overflow checks by Guido
+ * Cast to size_t to avoid triggering -ftrapv via overflow of st->num_alloc
+ */
+ if ( (size_t)(st->num_alloc) * 2 < (size_t)(st->num_alloc) ) {
+ return 0;
+ }
+
+ if ( (size_t)(st->num_alloc) * 2 > INT_MAX )
+ {
+ return 0;
+ }
+
+ /* Avond overflow due to multiplication by sizeof(char*) */
+ if ( (size_t)(st->num_alloc) * 2 > (~(size_t)0) / sizeof(char*) ) {
+ return 0;
+ }
+
+ /* Remove cast to unsigned int to avoid undersized allocations on > 32 bit. */
+ st->data = OPENSSL_realloc((char *)st->data,
+ sizeof(char *) * st->num_alloc * 2);
+ if (st->data == NULL) {
+ /* Reset these counters to prevent subsequent operations on
+ * (now non-existing) heap memory
+ */
+ st->num_alloc = 0;
+ st->num = 0;
return (0);
- st->data = s;
+ }
st->num_alloc *= 2;
}
if ((loc >= (int)st->num) || (loc < 0))
st->data[st->num] = data;
else {
+ if ( loc == INT_MAX ) {
+ return 0;
+ }
memmove(&st->data[loc + 1], &st->data[loc],
sizeof(st->data[0]) * (st->num - loc));
st->data[loc] = data;
@@ -151,7 +185,7 @@ void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc)
{
const char *ret;
- if (st == NULL || loc < 0 || loc >= st->num)
+ if (st == NULL || loc < 0 || loc >= st->num )
return NULL;
ret = st->data[loc];