Hi,
attached is a patch for an NMU to fix this.
It is also archived on:
http://people.debian.org/~nion/nmu-diff/git-core-1.5.6.3-1_1.5.6.3-1.1.patch

Cheers
Nico

-- 
Nico Golde - http://www.ngolde.de - [EMAIL PROTECTED] - GPG: 0x73647CFF
For security reasons, all text in this mail is double-rot13 encrypted.
diff -u git-core-1.5.6.3/debian/changelog git-core-1.5.6.3/debian/changelog
--- git-core-1.5.6.3/debian/changelog
+++ git-core-1.5.6.3/debian/changelog
@@ -1,3 +1,13 @@
+git-core (1:1.5.6.3-1.1) unstable; urgency=high
+
+  * Non-maintainer upload by the Security Team.
+  * Fix various stack-based buffer overflows when processing overly long
+    repository pathnames which can be exploited to execute arbitrary code if
+    a victim is tricked into using git-grep or git-diff on a crafted
+    repository (CVE-2008-3546; Closes: #494097).
+
+ -- Nico Golde <[EMAIL PROTECTED]>  Sat, 09 Aug 2008 13:53:13 +0200
+
 git-core (1:1.5.6.3-1) unstable; urgency=low
 
   * new upstream point release.
only in patch2:
unchanged:
--- git-core-1.5.6.3.orig/debian/diff/0005-bug-494097-CVE-2008-3546.diff
+++ git-core-1.5.6.3/debian/diff/0005-bug-494097-CVE-2008-3546.diff
@@ -0,0 +1,234 @@
+From: Dmitry Potapov <[EMAIL PROTECTED]>
+Date: Wed, 16 Jul 2008 14:54:02 +0000 (+0400)
+Subject: Fix buffer overflow in git diff
+X-Git-Tag: v1.5.6.4~16
+X-Git-Url: http://git.kernel.org/?p=git%2Fgit.git;a=commitdiff_plain;h=fd55a19eb1d49ae54008d932a65f79cd6fda45c9
+
+Fix buffer overflow in git diff
+
+If PATH_MAX on your system is smaller than a path stored, it may cause
+buffer overflow and stack corruption in diff_addremove() and diff_change()
+functions when running git-diff
+
+Signed-off-by: Dmitry Potapov <[EMAIL PROTECTED]>
+Signed-off-by: Junio C Hamano <[EMAIL PROTECTED]>
+---
+
+diff --git a/diff-lib.c b/diff-lib.c
+index b17722d..e7eaff9 100644
+--- a/diff-lib.c
++++ b/diff-lib.c
+@@ -171,7 +171,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
+ 			if (silent_on_removed)
+ 				continue;
+ 			diff_addremove(&revs->diffopt, '-', ce->ce_mode,
+-				       ce->sha1, ce->name, NULL);
++				       ce->sha1, ce->name);
+ 			continue;
+ 		}
+ 		changed = ce_match_stat(ce, &st, ce_option);
+@@ -184,7 +184,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
+ 		newmode = ce_mode_from_stat(ce, st.st_mode);
+ 		diff_change(&revs->diffopt, oldmode, newmode,
+ 			    ce->sha1, (changed ? null_sha1 : ce->sha1),
+-			    ce->name, NULL);
++			    ce->name);
+ 
+ 	}
+ 	diffcore_std(&revs->diffopt);
+@@ -208,7 +208,7 @@ static void diff_index_show_file(struct rev_info *revs,
+ 				 const unsigned char *sha1, unsigned int mode)
+ {
+ 	diff_addremove(&revs->diffopt, prefix[0], mode,
+-		       sha1, ce->name, NULL);
++		       sha1, ce->name);
+ }
+ 
+ static int get_stat_data(struct cache_entry *ce,
+@@ -312,7 +312,7 @@ static int show_modified(struct oneway_unpack_data *cbdata,
+ 		return 0;
+ 
+ 	diff_change(&revs->diffopt, oldmode, mode,
+-		    old->sha1, sha1, old->name, NULL);
++		    old->sha1, sha1, old->name);
+ 	return 0;
+ }
+ 
+diff --git a/diff.c b/diff.c
+index 78c4d3a..386de82 100644
+--- a/diff.c
++++ b/diff.c
+@@ -3356,9 +3356,8 @@ int diff_result_code(struct diff_options *opt, int status)
+ void diff_addremove(struct diff_options *options,
+ 		    int addremove, unsigned mode,
+ 		    const unsigned char *sha1,
+-		    const char *base, const char *path)
++		    const char *concatpath)
+ {
+-	char concatpath[PATH_MAX];
+ 	struct diff_filespec *one, *two;
+ 
+ 	if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(mode))
+@@ -3380,9 +3379,6 @@ void diff_addremove(struct diff_options *options,
+ 		addremove = (addremove == '+' ? '-' :
+ 			     addremove == '-' ? '+' : addremove);
+ 
+-	if (!path) path = "";
+-	sprintf(concatpath, "%s%s", base, path);
+-
+ 	if (options->prefix &&
+ 	    strncmp(concatpath, options->prefix, options->prefix_length))
+ 		return;
+@@ -3403,9 +3399,8 @@ void diff_change(struct diff_options *options,
+ 		 unsigned old_mode, unsigned new_mode,
+ 		 const unsigned char *old_sha1,
+ 		 const unsigned char *new_sha1,
+-		 const char *base, const char *path)
++		 const char *concatpath)
+ {
+-	char concatpath[PATH_MAX];
+ 	struct diff_filespec *one, *two;
+ 
+ 	if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(old_mode)
+@@ -3418,8 +3413,6 @@ void diff_change(struct diff_options *options,
+ 		tmp = old_mode; old_mode = new_mode; new_mode = tmp;
+ 		tmp_c = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_c;
+ 	}
+-	if (!path) path = "";
+-	sprintf(concatpath, "%s%s", base, path);
+ 
+ 	if (options->prefix &&
+ 	    strncmp(concatpath, options->prefix, options->prefix_length))
+diff --git a/diff.h b/diff.h
+index 5dc0cb5..50fb5dd 100644
+--- a/diff.h
++++ b/diff.h
+@@ -14,12 +14,12 @@ typedef void (*change_fn_t)(struct diff_options *options,
+ 		 unsigned old_mode, unsigned new_mode,
+ 		 const unsigned char *old_sha1,
+ 		 const unsigned char *new_sha1,
+-		 const char *base, const char *path);
++		 const char *fullpath);
+ 
+ typedef void (*add_remove_fn_t)(struct diff_options *options,
+ 		    int addremove, unsigned mode,
+ 		    const unsigned char *sha1,
+-		    const char *base, const char *path);
++		    const char *fullpath);
+ 
+ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
+ 		struct diff_options *options, void *data);
+@@ -164,14 +164,13 @@ extern void diff_addremove(struct diff_options *,
+ 			   int addremove,
+ 			   unsigned mode,
+ 			   const unsigned char *sha1,
+-			   const char *base,
+-			   const char *path);
++			   const char *fullpath);
+ 
+ extern void diff_change(struct diff_options *,
+ 			unsigned mode1, unsigned mode2,
+ 			const unsigned char *sha1,
+ 			const unsigned char *sha2,
+-			const char *base, const char *path);
++			const char *fullpath);
+ 
+ extern void diff_unmerge(struct diff_options *,
+ 			 const char *path,
+diff --git a/revision.c b/revision.c
+index fc66755..8dc3ca7 100644
+--- a/revision.c
++++ b/revision.c
+@@ -259,7 +259,7 @@ static int tree_difference = REV_TREE_SAME;
+ static void file_add_remove(struct diff_options *options,
+ 		    int addremove, unsigned mode,
+ 		    const unsigned char *sha1,
+-		    const char *base, const char *path)
++		    const char *fullpath)
+ {
+ 	int diff = REV_TREE_DIFFERENT;
+ 
+@@ -285,7 +285,7 @@ static void file_change(struct diff_options *options,
+ 		 unsigned old_mode, unsigned new_mode,
+ 		 const unsigned char *old_sha1,
+ 		 const unsigned char *new_sha1,
+-		 const char *base, const char *path)
++		 const char *fullpath)
+ {
+ 	tree_difference = REV_TREE_DIFFERENT;
+ 	DIFF_OPT_SET(options, HAS_CHANGES);
+diff --git a/tree-diff.c b/tree-diff.c
+index e1e2e6c..bbb126f 100644
+--- a/tree-diff.c
++++ b/tree-diff.c
+@@ -15,6 +15,15 @@ static char *malloc_base(const char *base, int baselen, const char *path, int pa
+ 	return newbase;
+ }
+ 
++static char *malloc_fullname(const char *base, int baselen, const char *path, int pathlen)
++{
++	char *fullname = xmalloc(baselen + pathlen + 1);
++	memcpy(fullname, base, baselen);
++	memcpy(fullname + baselen, path, pathlen);
++	fullname[baselen + pathlen] = 0;
++	return fullname;
++}
++
+ static void show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc,
+ 		       const char *base, int baselen);
+ 
+@@ -24,6 +33,7 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
+ 	const char *path1, *path2;
+ 	const unsigned char *sha1, *sha2;
+ 	int cmp, pathlen1, pathlen2;
++	char *fullname;
+ 
+ 	sha1 = tree_entry_extract(t1, &path1, &mode1);
+ 	sha2 = tree_entry_extract(t2, &path2, &mode2);
+@@ -55,15 +65,20 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
+ 	if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode1)) {
+ 		int retval;
+ 		char *newbase = malloc_base(base, baselen, path1, pathlen1);
+-		if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE))
++		if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) {
++			newbase[baselen + pathlen1] = 0;
+ 			opt->change(opt, mode1, mode2,
+-				    sha1, sha2, base, path1);
++				    sha1, sha2, newbase);
++			newbase[baselen + pathlen1] = '/';
++		}
+ 		retval = diff_tree_sha1(sha1, sha2, newbase, opt);
+ 		free(newbase);
+ 		return retval;
+ 	}
+ 
+-	opt->change(opt, mode1, mode2, sha1, sha2, base, path1);
++	fullname = malloc_fullname(base, baselen, path1, pathlen1);
++	opt->change(opt, mode1, mode2, sha1, sha2, fullname);
++	free(fullname);
+ 	return 0;
+ }
+ 
+@@ -205,10 +220,10 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree
+ 	unsigned mode;
+ 	const char *path;
+ 	const unsigned char *sha1 = tree_entry_extract(desc, &path, &mode);
++	int pathlen = tree_entry_len(path, sha1);
+ 
+ 	if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode)) {
+ 		enum object_type type;
+-		int pathlen = tree_entry_len(path, sha1);
+ 		char *newbase = malloc_base(base, baselen, path, pathlen);
+ 		struct tree_desc inner;
+ 		void *tree;
+@@ -224,7 +239,9 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree
+ 		free(tree);
+ 		free(newbase);
+ 	} else {
+-		opt->add_remove(opt, prefix[0], mode, sha1, base, path);
++		char *fullname = malloc_fullname(base, baselen, path, pathlen);
++		opt->add_remove(opt, prefix[0], mode, sha1, fullname);
++		free(fullname);
+ 	}
+ }
+

Attachment: pgpkTu2eDTtWE.pgp
Description: PGP signature

Reply via email to