From 2cad237f8bea862923bf9e7e2d7c55544f6248e0 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 2 Jan 2014 23:54:59 +0100 Subject: ta: check overflow in array realloc macros --- ta/ta.h | 1 + ta/ta_talloc.h | 9 ++++++--- ta/ta_utils.c | 11 +++++++++++ 3 files changed, 18 insertions(+), 3 deletions(-) (limited to 'ta') diff --git a/ta/ta.h b/ta/ta.h index c8a333f784..c21e0b0e39 100644 --- a/ta/ta.h +++ b/ta/ta.h @@ -54,6 +54,7 @@ void *ta_find_parent(void *ptr); // Utility functions size_t ta_calc_array_size(size_t element_size, size_t count); +size_t ta_calc_prealloc_elems(size_t nextidx); void *ta_new_context(void *ta_parent); void *ta_steal_(void *ta_parent, void *ptr); void *ta_memdup(void *ta_parent, void *ptr, size_t size); diff --git a/ta/ta_talloc.h b/ta/ta_talloc.h index ff131a610e..409949495a 100644 --- a/ta/ta_talloc.h +++ b/ta/ta_talloc.h @@ -77,14 +77,17 @@ char *ta_talloc_asprintf_append_buffer(char *s, const char *fmt, ...) TA_PRF(2, #define MP_TALLOC_ELEMS(p) (talloc_get_size(p) / sizeof((p)[0])) -#define MP_RESIZE_ARRAY(ctx, p, count) do { \ - (p) = talloc_realloc_size((ctx), p, (count) * sizeof((p)[0])); } while (0) +#define MP_RESIZE_ARRAY(ctx, p, count) \ + do { \ + (p) = ta_xrealloc_size(ctx, p, \ + ta_calc_array_size(sizeof((p)[0]), count)); \ + } while (0) #define MP_TARRAY_GROW(ctx, p, nextidx) \ do { \ size_t nextidx_ = (nextidx); \ if (nextidx_ >= MP_TALLOC_ELEMS(p)) \ - MP_RESIZE_ARRAY(ctx, p, (nextidx_ + 1) * 2);\ + MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \ } while (0) #define MP_GROW_ARRAY(p, nextidx) MP_TARRAY_GROW(NULL, p, nextidx) diff --git a/ta/ta_utils.c b/ta/ta_utils.c index 4d1e73fab6..a6b59f2e3d 100644 --- a/ta/ta_utils.c +++ b/ta/ta_utils.c @@ -30,6 +30,17 @@ size_t ta_calc_array_size(size_t element_size, size_t count) return element_size * count; } +// This is used when an array has to be enlarged for appending new elements. +// Return a "good" size for the new array (in number of elements). This returns +// a value >= nextidx, unless the calculation overflows, in which case SIZE_MAX +// is returned. +size_t ta_calc_prealloc_elems(size_t nextidx) +{ + if (nextidx >= ((size_t)-1) / 2 - 1) + return (size_t)-1; + return (nextidx + 1) * 2; +} + static void dummy_dtor(void *p){} /* Create an empty (size 0) TA allocation, which is prepared in a way such that -- cgit v1.2.3