Skip to content

Commit bed6bc5

Browse files
committed
commit: fix parsing of mergetag headers
Git contains some multiline headers, including `gpgsig`, `gpgsig-sha256`, and `mergetag` headers. These headers start with a normal line of data and then are continued after a newline by indentation with a single space, which is stripped when computing the body. Our header parsing for commits could misparse these because we use `strings.Fields`, which strips leading space. As a result, if the mergetag message contains a line starting with "tree " and then a non-hex character, we'd fail parsing since we'd attempt to parse it as a tree header. Let's fix this by using `strings.Split` instead, which doesn't strip space and therefore won't try to misparse this. The fake commit is synthesized from be122abe4bcd6d39b37892daae28c8bf5e4030fc in the Linux kernel repository. Identifying information and most of the text are removed for privacy and license reasons.
1 parent 1a9c7f6 commit bed6bc5

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

commit.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func (c *Commit) Decode(hash hash.Hash, from io.Reader, size int64) (n int, err
107107
continue
108108
}
109109

110-
if fields := strings.Fields(text); !finishedHeaders {
110+
if fields := strings.Split(text, " "); !finishedHeaders {
111111
if len(fields) == 0 {
112112
// Executing in this block means that we got a
113113
// whitespace-only line, while parsing a header.

commit_test.go

+59
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,65 @@ func TestCommitDecodingMultilineHeader(t *testing.T) {
238238
strings.Split(hdr.V, "\n"))
239239
}
240240

241+
func TestCommitDecodingMessageWithLineStartingWithTree(t *testing.T) {
242+
from := new(bytes.Buffer)
243+
244+
// The tricky part here that we're testing is the "tree support" in the
245+
// `mergetag` header, which we should not try to parse as a tree header.
246+
// Note also that this entry contains trailing whitespace which must not
247+
// be trimmed.
248+
fmt.Fprintf(from, `tree e8ad84c41c2acde27c77fa212b8865cd3acfe6fb
249+
parent b343c8beec664ef6f0e9964d3001c7c7966331ae
250+
parent 1e8a52e18cfb381bc9cc1f0b720540364d2a6edd
251+
author Pat Doe <[email protected]> 1337892984 -0700
252+
committer Pat Doe <[email protected]> 1337892984 -0700
253+
mergetag object 1e8a52e18cfb381bc9cc1f0b720540364d2a6edd
254+
type commit
255+
tag random
256+
tagger J. Roe <[email protected]> 1337889148 -0600
257+
258+
Random changes
259+
260+
This text contains some
261+
tree support code.
262+
-----BEGIN PGP SIGNATURE-----
263+
Version: GnuPG v1.4.11 (GNU/Linux)
264+
265+
Not a real signature
266+
-----END PGP SIGNATURE-----
267+
268+
Merge tag 'random' of git://git.example.ca/git/
269+
`)
270+
271+
flen := from.Len()
272+
273+
commit := new(Commit)
274+
n, err := commit.Decode(sha1.New(), from, int64(flen))
275+
276+
require.Nil(t, err)
277+
require.Equal(t, flen, n)
278+
require.Equal(t, commit.ExtraHeaders, []*ExtraHeader{
279+
{
280+
K: "mergetag",
281+
V: `object 1e8a52e18cfb381bc9cc1f0b720540364d2a6edd
282+
type commit
283+
tag random
284+
tagger J. Roe <[email protected]> 1337889148 -0600
285+
286+
Random changes
287+
288+
This text contains some
289+
tree support code.
290+
-----BEGIN PGP SIGNATURE-----
291+
Version: GnuPG v1.4.11 (GNU/Linux)
292+
293+
Not a real signature
294+
-----END PGP SIGNATURE-----`},
295+
},
296+
)
297+
require.Equal(t, commit.Message, "Merge tag 'random' of git://git.example.ca/git/")
298+
}
299+
241300
func assertLine(t *testing.T, buf *bytes.Buffer, wanted string, args ...interface{}) {
242301
got, err := buf.ReadString('\n')
243302
if err == io.EOF {

0 commit comments

Comments
 (0)