From: Arran Cudbard-Bell Date: Wed, 28 Mar 2018 15:28:56 +0000 (+0100) Subject: Check for overflow when expanding X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=24ee006d41c7fe31ebc9f12909e185d321ca0cef;p=thirdparty%2Ffreeradius-server.git Check for overflow when expanding Provide errors Check for realloc failure More type fixes Formatting --- diff --git a/src/lib/util/heap.c b/src/lib/util/heap.c index c5967f732dc..b2367b5db89 100644 --- a/src/lib/util/heap.c +++ b/src/lib/util/heap.c @@ -50,12 +50,12 @@ struct fr_heap_t { * 2i+2. These macros wrap the logic, so the code is more * descriptive. */ -#define HEAP_PARENT(x) ( ( (x) - 1 ) / 2 ) -#define HEAP_LEFT(x) ( 2*(x) + 1 ) -/* #define HEAP_RIGHT(x) ( 2*(x) + 2 ) */ -#define HEAP_SWAP(a, b) { void *_tmp = a; a = b; b = _tmp; } +#define HEAP_PARENT(_x) (((_x) - 1 ) / 2) +#define HEAP_LEFT(_x) (2 * (_x) + 1) +/* #define HEAP_RIGHT(_x) (2 * (_x) + 2 ) */ +#define HEAP_SWAP(_a, _b) { void *_tmp = _a; _a = _b; _b = _tmp; } -static int fr_heap_bubble(fr_heap_t *hp, size_t child); +static int fr_heap_bubble(fr_heap_t *hp, int32_t child); fr_heap_t *_fr_heap_create(fr_heap_cmp_t cmp, char const *type, size_t offset) { @@ -108,22 +108,31 @@ int fr_heap_insert(fr_heap_t *hp, void *data) { size_t child = hp->num_elements; - /* - * heap_id is a 32-bit signed integer. If the heap will - * grow to contain more than 2B elements, disallow - * integer overflow. Tho TBH, that should really never - * happen. - */ - if (hp->size >= INT32_MAX) { - return 0; - } - /* * Heap is full. Double it's size. */ if (child == hp->size) { - hp->size *= 2; - hp->p = talloc_realloc(hp, hp->p, void *, hp->size); + void **n; + size_t n_size = hp->size * 2; + + /* + * heap_id is a 32-bit signed integer. If the heap will + * grow to contain more than 2B elements, disallow + * integer overflow. Tho TBH, that should really never + * happen. + */ + if (n_size >= INT32_MAX) { + fr_strerror_printf("Heap is full"); + return 0; + } + + n = talloc_realloc(hp, hp->p, void *, n_size); + if (!n) { + fr_strerror_printf("Failed expanding heap"); + return 0; + } + hp->size = n_size; + hp->p = n; } hp->p[child] = data; @@ -133,13 +142,13 @@ int fr_heap_insert(fr_heap_t *hp, void *data) } -static int fr_heap_bubble(fr_heap_t *hp, size_t child) +static int fr_heap_bubble(fr_heap_t *hp, int32_t child) { /* * Bubble up the element. */ while (child > 0) { - size_t parent = HEAP_PARENT(child); + int32_t parent = HEAP_PARENT(child); /* * Parent is smaller than the child. We're done. @@ -164,7 +173,7 @@ static int fr_heap_bubble(fr_heap_t *hp, size_t child) */ int fr_heap_extract(fr_heap_t *hp, void *data) { - int parent, child, max; + int32_t parent, child, max; if (!hp || (hp->num_elements == 0)) return 0; @@ -280,8 +289,8 @@ static bool fr_heap_check(fr_heap_t *hp, void *data) } typedef struct heap_thing { - int data; - int32_t heap_id; /* for the heap */ + int data; + int32_t heap; /* for the heap */ } heap_thing; @@ -338,7 +347,7 @@ int main(int argc, char **argv) #endif if (skip) { - int entry; + int32_t entry; printf("%d elements to remove\n", ARRAY_SIZE / skip);