Index: CVE-2008-5516.patch
===================================================================
RCS file: CVE-2008-5516.patch
diff -N CVE-2008-5516.patch
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ CVE-2008-5516.patch	12 Jan 2009 23:00:06 -0000
@@ -0,0 +1,143 @@
+From 8f8bfb38271775770cd1da8fb7cfd1e2d7ef2481 Mon Sep 17 00:00:00 2001
+From: Jakub Narebski <jnareb@gmail.com>
+Date: Wed, 5 Mar 2008 09:31:55 +0100
+Subject: [PATCH 1/2] gitweb: Fix and simplify pickaxe search
+
+Instead of using "git-rev-list | git-diff-tree" pipeline for pickaxe
+search, use git-log with appropriate options.  Besides reducing number
+of forks by one, this allows to use list form of open, which in turn
+allow to not worry about quoting arguments and to avoid forking shell.
+
+The options to git-log were chosen to reduce required changes in
+pickaxe git command output parsing; gitweb still parses returned
+commits one by one.
+
+Parsing "pickaxe" output is simplified: git_search now reuses
+parse_difftree_raw_line and writes affected files as they arrive using
+the fact that commit name goes always before [raw] diff.
+
+While at it long bug of pickaxe search was fixed, namely that the last
+commit found by pickaxe search was never shown.
+
+Signed-off-by: Jakub Narebski <jnareb@gmail.com>
+Signed-off-by: Junio C Hamano <gitster@pobox.com>
+
+Note: This patch was backported to 1.5.4.7 by Todd Zullinger
+<tmz@pobox.com>.  Any blame for problems should come to me, not the
+upstream authors. :)
+---
+ gitweb/gitweb.perl |   83 ++++++++++++++++++++++++++-------------------------
+ 1 files changed, 42 insertions(+), 41 deletions(-)
+
+diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
+index 86a6ced..e011393 100755
+--- a/gitweb/gitweb.perl
++++ b/gitweb/gitweb.perl
+@@ -5199,50 +5199,18 @@ sub git_search {
+ 		print "<table class=\"pickaxe search\">\n";
+ 		my $alternate = 1;
+ 		$/ = "\n";
+-		my $git_command = git_cmd_str();
+-		my $searchqtext = $searchtext;
+-		$searchqtext =~ s/'/'\\''/;
+-		open my $fd, "-|", "$git_command rev-list $hash | " .
+-			"$git_command diff-tree -r --stdin -S\'$searchqtext\'";
++		open my $fd, '-|', git_cmd(), '--no-pager', 'log', @diff_opts,
++			'--pretty=format:%H', '--no-abbrev', '--raw', "-S$searchtext";
+ 		undef %co;
+ 		my @files;
+ 		while (my $line = <$fd>) {
+-			if (%co && $line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$/) {
+-				my %set;
+-				$set{'file'} = $6;
+-				$set{'from_id'} = $3;
+-				$set{'to_id'} = $4;
+-				$set{'id'} = $set{'to_id'};
+-				if ($set{'id'} =~ m/0{40}/) {
+-					$set{'id'} = $set{'from_id'};
+-				}
+-				if ($set{'id'} =~ m/0{40}/) {
+-					next;
+-				}
+-				push @files, \%set;
+-			} elsif ($line =~ m/^([0-9a-fA-F]{40})$/){
++			chomp $line;
++			next unless $line;
++
++			my %set = parse_difftree_raw_line($line);
++			if (defined $set{'commit'}) {
++				# finish previous commit
+ 				if (%co) {
+-					if ($alternate) {
+-						print "<tr class=\"dark\">\n";
+-					} else {
+-						print "<tr class=\"light\">\n";
+-					}
+-					$alternate ^= 1;
+-					my $author = chop_and_escape_str($co{'author_name'}, 15, 5);
+-					print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
+-					      "<td><i>" . $author . "</i></td>\n" .
+-					      "<td>" .
+-					      $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}),
+-					              -class => "list subject"},
+-					              chop_and_escape_str($co{'title'}, 50) . "<br/>");
+-					while (my $setref = shift @files) {
+-						my %set = %$setref;
+-						print $cgi->a({-href => href(action=>"blob", hash_base=>$co{'id'},
+-						                             hash=>$set{'id'}, file_name=>$set{'file'}),
+-						              -class => "list"},
+-						              "<span class=\"match\">" . esc_path($set{'file'}) . "</span>") .
+-						      "<br/>\n";
+-					}
+ 					print "</td>\n" .
+ 					      "<td class=\"link\">" .
+ 					      $cgi->a({-href => href(action=>"commit", hash=>$co{'id'})}, "commit") .
+@@ -5251,11 +5219,44 @@ sub git_search {
+ 					print "</td>\n" .
+ 					      "</tr>\n";
+ 				}
+-				%co = parse_commit($1);
++
++				if ($alternate) {
++					print "<tr class=\"dark\">\n";
++				} else {
++					print "<tr class=\"light\">\n";
++				}
++				$alternate ^= 1;
++				%co = parse_commit($set{'commit'});
++				my $author = chop_and_escape_str($co{'author_name'}, 15, 5);
++				print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
++				      "<td><i>$author</i></td>\n" .
++				      "<td>" .
++				      $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}),
++				              -class => "list subject"},
++				              chop_and_escape_str($co{'title'}, 50) . "<br/>");
++			} elsif (defined $set{'to_id'}) {
++				next if ($set{'to_id'} =~ m/^0{40}$/);
++
++				print $cgi->a({-href => href(action=>"blob", hash_base=>$co{'id'},
++				                             hash=>$set{'to_id'}, file_name=>$set{'to_file'}),
++				              -class => "list"},
++				              "<span class=\"match\">" . esc_path($set{'file'}) . "</span>") .
++				      "<br/>\n";
+ 			}
+ 		}
+ 		close $fd;
+ 
++		# finish last commit (warning: repetition!)
++		if (%co) {
++			print "</td>\n" .
++			      "<td class=\"link\">" .
++			      $cgi->a({-href => href(action=>"commit", hash=>$co{'id'})}, "commit") .
++			      " | " .
++			      $cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$co{'id'})}, "tree");
++			print "</td>\n" .
++			      "</tr>\n";
++		}
++
+ 		print "</table>\n";
+ 	}
+ 
+-- 
+1.6.1
+
Index: CVE-2008-5517.patch
===================================================================
RCS file: CVE-2008-5517.patch
diff -N CVE-2008-5517.patch
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ CVE-2008-5517.patch	12 Jan 2009 23:00:06 -0000
@@ -0,0 +1,75 @@
+From 2813e6cef24a8b363a97ea0c86bf4494fc453f32 Mon Sep 17 00:00:00 2001
+From: Lea Wiemann <lewiemann@gmail.com>
+Date: Tue, 17 Jun 2008 23:46:35 +0200
+Subject: [PATCH 2/2] gitweb: quote commands properly when calling the shell
+
+This eliminates the function git_cmd_str, which was used for composing
+command lines, and adds a quote_command function, which quotes all of
+its arguments (as in quote.c).
+
+Signed-off-by: Lea Wiemann <LeWiemann@gmail.com>
+Signed-off-by: Junio C Hamano <gitster@pobox.com>
+---
+ gitweb/gitweb.perl |   24 ++++++++++++++----------
+ 1 files changed, 14 insertions(+), 10 deletions(-)
+
+diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
+index e011393..bd50c07 100755
+--- a/gitweb/gitweb.perl
++++ b/gitweb/gitweb.perl
+@@ -1396,9 +1396,13 @@ sub git_cmd {
+ 	return $GIT, '--git-dir='.$git_dir;
+ }
+ 
+-# returns path to the core git executable and the --git-dir parameter as string
+-sub git_cmd_str {
+-	return join(' ', git_cmd());
++# quote the given arguments for passing them to the shell
++# quote_command("command", "arg 1", "arg with ' and ! characters")
++# => "'command' 'arg 1' 'arg with '\'' and '\!' characters'"
++# Try to avoid using this function wherever possible.
++sub quote_command {
++	return join(' ',
++		    map( { my $a = $_; $a =~ s/(['!])/'\\$1'/g; "'$a'" } @_ ));
+ }
+ 
+ # get HEAD ref of given project as hash
+@@ -4477,7 +4481,6 @@ sub git_snapshot {
+ 		$hash = git_get_head_hash($project);
+ 	}
+ 
+-	my $git_command = git_cmd_str();
+ 	my $name = $project;
+ 	$name =~ s,([^/])/*\.git$,$1,;
+ 	$name = basename($name);
+@@ -4485,11 +4488,12 @@ sub git_snapshot {
+ 	$name =~ s/\047/\047\\\047\047/g;
+ 	my $cmd;
+ 	$filename .= "-$hash$known_snapshot_formats{$format}{'suffix'}";
+-	$cmd = "$git_command archive " .
+-		"--format=$known_snapshot_formats{$format}{'format'} " .
+-		"--prefix=\'$name\'/ $hash";
++	$cmd = quote_command(
++		git_cmd(), 'archive',
++		"--format=$known_snapshot_formats{$format}{'format'}",
++		"--prefix=$name/", $hash);
+ 	if (exists $known_snapshot_formats{$format}{'compressor'}) {
+-		$cmd .= ' | ' . join ' ', @{$known_snapshot_formats{$format}{'compressor'}};
++		$cmd .= ' | ' . quote_command(@{$known_snapshot_formats{$format}{'compressor'}});
+ 	}
+ 
+ 	print $cgi->header(
+@@ -4702,8 +4706,8 @@ sub git_object {
+ 	if ($hash || ($hash_base && !defined $file_name)) {
+ 		my $object_id = $hash || $hash_base;
+ 
+-		my $git_command = git_cmd_str();
+-		open my $fd, "-|", "$git_command cat-file -t $object_id 2>/dev/null"
++		open my $fd, "-|", quote_command(
++			git_cmd(), 'cat-file', '-t', $object_id) . ' 2> /dev/null'
+ 			or die_error('404 Not Found', "Object does not exist");
+ 		$type = <$fd>;
+ 		chomp $type;
+-- 
+1.6.1
+
Index: git.spec
===================================================================
RCS file: /cvs/extras/rpms/git/EL-4/git.spec,v
retrieving revision 1.32
diff -u -p -r1.32 git.spec
--- git.spec	20 Dec 2008 18:15:48 -0000	1.32
+++ git.spec	12 Jan 2009 23:00:06 -0000
@@ -1,7 +1,7 @@
 # Pass --without docs to rpmbuild if you don't want the documentation
 Name: 		git
 Version: 	1.5.4.7
-Release: 	1%{?dist}
+Release: 	2%{?dist}
 Summary:  	Git core and tools
 License: 	GPL
 Group: 		Development/Tools
@@ -10,6 +10,8 @@ Source: 	http://kernel.org/pub/software/
 Source1:	git.xinetd
 Source2:	git.conf.httpd
 Patch0:		git-1.5-gitweb-home-link.patch
+Patch1:         CVE-2008-5516.patch
+Patch2:         CVE-2008-5517.patch
 BuildRequires:	perl, zlib-devel >= 1.2, openssl-devel, curl-devel, expat-devel, gettext %{!?_without_docs:, xmlto, asciidoc > 6.0.3}
 BuildRoot:	%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 Requires:	git-core, git-svn, git-cvs, git-email, gitk, git-gui, perl-Git
@@ -93,6 +95,8 @@ Perl interface to Git
 %prep
 %setup -q
 %patch0 -p1
+%patch1 -p1 -b .CVE-2008-5516
+%patch2 -p1 -b .CVE-2008-5517
 
 %build
 make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" \
@@ -196,6 +200,9 @@ rm -rf $RPM_BUILD_ROOT
 
 
 %changelog
+* Mon Jan 12 2009 Todd Zullinger <tmz@pobox.com> 1.5.4.7-2
+- Backport fixes for CVE-2008-5516 and CVE-2008-5517 (bug 479715)
+
 * Sat Dec 20 2008 James Bowes <jbowes@redhat.com> 1.5.4.7-1
 - Update to latest maintenence release.
 
