Commit 7655b2d89e8275853d9921dd903dcdad9b3d4a7b

Patrick Steinhardt 2018-10-19T10:29:19

commit: fix reading out of bounds when parsing encoding The commit message encoding is currently being parsed by the `git__prefixcmp` function. As this function does not accept a buffer length, it will happily skip over a buffer's end if it is not `NUL` terminated. Fix the issue by using `git__prefixncmp` instead. Add a test that verifies that we are unable to parse the encoding field if it's cut off by the supplied buffer length.

diff --git a/src/commit.c b/src/commit.c
index 97ac2a1..bda5a8b 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -444,7 +444,7 @@ int git_commit__parse_raw(void *_commit, const char *data, size_t size)
 		while (eoln < buffer_end && *eoln != '\n')
 			++eoln;
 
-		if (git__prefixcmp(buffer, "encoding ") == 0) {
+		if (git__prefixncmp(buffer, buffer_end - buffer, "encoding ") == 0) {
 			buffer += strlen("encoding ");
 
 			commit->message_encoding = git__strndup(buffer, eoln - buffer);
diff --git a/tests/object/commit/parse.c b/tests/object/commit/parse.c
index 9ba8767..a99110f 100644
--- a/tests/object/commit/parse.c
+++ b/tests/object/commit/parse.c
@@ -211,3 +211,22 @@ void test_object_commit_parse__parsing_commit_without_committer_fails(void)
 		"Message";
 	assert_commit_fails(commit, 0);
 }
+
+void test_object_commit_parse__parsing_encoding_will_not_cause_oob_read(void)
+{
+	const char *commit =
+		"tree 3e7ac388cadacccdf1c6c5f3445895b71d9cb0f8\n"
+		"author <>\n"
+		"committer <>\n"
+		"encoding foo\n";
+	/*
+	 * As we ignore unknown fields, the cut-off encoding field will be
+	 * parsed just fine.
+	 */
+	assert_commit_parses(commit, strlen(commit) - strlen("ncoding foo\n"),
+		"3e7ac388cadacccdf1c6c5f3445895b71d9cb0f8",
+		"<>",
+		"<>",
+		NULL,
+		"", 0);
+}