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 <tobias@stoeckmann.org>
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@47d348a631)
This commit is contained in:
Tobias Stoeckmann 2019-04-16 21:12:21 +02:00 committed by Azat Khuzhin
parent 1810497394
commit 8c89976823
No known key found for this signature in database
GPG Key ID: B86086848EF8686D

View File

@ -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;