git name-rev writes beyond the end of malloc() with large generations
commitcf606e3ddd8666b990a6560be77eb9f28af0e47d
authorAndy Whitcroft <apw@shadowen.org>
Tue, 15 May 2007 16:33:25 +0000 (15 17:33 +0100)
committerJunio C Hamano <junkio@cox.net>
Wed, 16 May 2007 01:14:42 +0000 (15 18:14 -0700)
tree4cf1c85058ac12ff55e61870b5220b5f7c2d000a
parent045fe3ccdaeb81f12f657b44b5a117b65d9d38e2
git name-rev writes beyond the end of malloc() with large generations

When using git name-rev on my kernel tree I triggered a malloc()
corruption warning from glibc.

apw@pinky$ git log --pretty=one $N/base.. | git name-rev --stdin
*** glibc detected *** malloc(): memory corruption: 0x0bff8950 ***
Aborted

This comes from name_rev() which is building the name of the revision
in a malloc'd string, which it sprintf's into:

char *new_name = xmalloc(len + 8);
[...]
sprintf(new_name, "%.*s~%d^%d", len, tip_name,
generation, parent_number);

This allocation is only sufficient if the generation number is
less than 5 digits, in my case generation was 13432.  In reality
parent_number can be up to 16 so that also can require two digits,
reducing us to 3 digits before we are at risk of blowing this
allocation.

This patch introduces a decimal_length() which approximates the
number of digits a type may hold, it produces the following:

Type                 Longest Value          Len  Est
----                 -------------          ---  ---
unsigned char        256                      3    4
unsigned short       65536                    5    6
unsigned long        4294967296              10   11
unsigned long long   18446744073709551616    20   21
char                 -128                     4    4
short                -32768                   6    6
long                 -2147483648             11   11
long long            -9223372036854775808    20   21

This is then used to size the new_name.

Signed-off-by: Andy Whitcroft <apw@shadowen.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
builtin-name-rev.c
git-compat-util.h