line-log.c: prevent crash during union of too many ranges
commitaaae0bf787f09ba102f69c3cf85d37e6554ab9fd
authorAllan Xavier <allan.x.xavier@oracle.com>
Thu, 2 Mar 2017 17:29:02 +0000 (2 17:29 +0000)
committerJunio C Hamano <gitster@pobox.com>
Fri, 3 Mar 2017 19:16:20 +0000 (3 11:16 -0800)
tree16d8fb532ed7f5ade4b18711b94a7f75778237a2
parentc3808ca6982b0ad7ee9b87eca9b50b9a24ec08b0
line-log.c: prevent crash during union of too many ranges

The existing implementation of range_set_union does not correctly
reallocate memory, leading to a heap overflow when it attempts to union
more than 24 separate line ranges.

For struct range_set *out to grow correctly it must have out->nr set to
the current size of the buffer when it is passed to range_set_grow.
However, the existing implementation of range_set_union only updates
out->nr at the end of the function, meaning that it is always zero
before this. This results in range_set_grow never growing the buffer, as
well as some of the union logic itself being incorrect as !out->nr is
always true.

The reason why 24 is the limit is that the first allocation of size 1
ends up allocating a buffer of size 24 (due to the call to alloc_nr in
ALLOC_GROW). This goes some way to explain why this hasn't been
caught before.

Fix the problem by correctly updating out->nr after reallocating the
range_set. As this results in out->nr containing the same value as the
variable o, replace o with out->nr as well.

Finally, add a new test to help prevent the problem reoccurring in the
future. Thanks to Vegard Nossum for writing the test.

Signed-off-by: Allan Xavier <allan.x.xavier@oracle.com>
Reviewed-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
line-log.c
t/t4211-line-log.sh