Skip to content

Commit

Permalink
git name-rev writes beyond the end of malloc() with large generations
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
  • Loading branch information
awhitcroft authored and Junio C Hamano committed May 16, 2007
1 parent 045fe3c commit cf606e3
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 1 deletion.
5 changes: 4 additions & 1 deletion builtin-name-rev.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 58,10 @@ static void name_rev(struct commit *commit,
parents = parents->next, parent_number ) {
if (parent_number > 1) {
int len = strlen(tip_name);
char *new_name = xmalloc(len 8);
char *new_name = xmalloc(len
1 decimal_length(generation) /* ~<n> */
1 2 /* ^NN */
1);

if (len > 2 && !strcmp(tip_name len - 2, "^0"))
len -= 2;
Expand Down
3 changes: 3 additions & 0 deletions git-compat-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 13,9 @@

#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))

/* Approximation of the length of the decimal representation of this type. */
#define decimal_length(x) ((int)(sizeof(x) * 2.56 0.5) 1)

#if !defined(__APPLE__) && !defined(__FreeBSD__)
#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
Expand Down

0 comments on commit cf606e3

Please sign in to comment.