From 8c899768236842fcc3c8141f208b917a066713fb Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Tue, 16 Apr 2019 21:12:21 +0200 Subject: [PATCH] Protect min_heap_push_ against integer overflow. On 64 bit systems with a lot of memory it is possible to overflow the counter s->n (unsigned int) which keeps track of the amount of elements within the heap. On 32 bit systems with tightly packed memory layout (and adding the same pointer again and again) an integer overflow could occur if "a" reaches 2^30 because the multiplication with sizeof *p (4) would overflow, effectively freeing memory of s->p which eventually leads to a double free. No sign of issue for any sane setup and therefore a purely defensive measurement. Signed-off-by: Tobias Stoeckmann Refs: #799 (first version of the patch for backporting to 2.1.x only) See-also: 181049739478d57500bd564539f17407437bfe8f ("Revert "Protect min_heap_push_ against integer overflow."") (cherry picked from commit stoeckmann/libevent@47d348a63130c91f2a6aadef291ff5687275df72) --- minheap-internal.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/minheap-internal.h b/minheap-internal.h index b3b6f1fd..b3a0eb1f 100644 --- a/minheap-internal.h +++ b/minheap-internal.h @@ -70,7 +70,7 @@ struct event* min_heap_top_(min_heap_t* s) { return s->n ? *s->p : 0; } int min_heap_push_(min_heap_t* s, struct event* e) { - if (min_heap_reserve_(s, s->n + 1)) + if (s->n == UINT32_MAX || min_heap_reserve_(s, s->n + 1)) return -1; min_heap_shift_up_(s, s->n++, e); return 0; @@ -138,6 +138,10 @@ int min_heap_reserve_(min_heap_t* s, unsigned n) unsigned a = s->a ? s->a * 2 : 8; if (a < n) a = n; +#if (SIZE_MAX == UINT32_MAX) + if (a > SIZE_MAX / sizeof *p) + return -1; +#endif if (!(p = (struct event**)mm_realloc(s->p, a * sizeof *p))) return -1; s->p = p; -- 2.40.0