Commit cf83809b9d4b142ec1250b19a902b3eb7744e014

Patrick Steinhardt 2018-11-13T14:26:26

Merge pull request #4883 from pks-t/pks/signature-tz-oob signature: fix out-of-bounds read when parsing timezone offset

diff --git a/src/signature.c b/src/signature.c
index 91864bb..11416d7 100644
--- a/src/signature.c
+++ b/src/signature.c
@@ -248,7 +248,7 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
 
 			if ((tz_start[0] != '-' && tz_start[0] != '+') ||
 			    git__strntol32(&offset, tz_start + 1,
-					   buffer_end - tz_start + 1, &tz_end, 10) < 0) {
+					   buffer_end - tz_start - 1, &tz_end, 10) < 0) {
 				/* malformed timezone, just assume it's zero */
 				offset = 0;
 			}
diff --git a/tests/commit/signature.c b/tests/commit/signature.c
index 78ddbbe..a915514 100644
--- a/tests/commit/signature.c
+++ b/tests/commit/signature.c
@@ -43,6 +43,26 @@ void test_commit_signature__leading_and_trailing_crud_is_trimmed(void)
 	assert_name_and_email("nulltoken \xe2\x98\xba", "emeric.fermas@gmail.com", "nulltoken \xe2\x98\xba", "emeric.fermas@gmail.com");
 }
 
+void test_commit_signature__timezone_does_not_read_oob(void)
+{
+	const char *header = "A <a@example.com> 1461698487 +1234", *header_end;
+	git_signature *sig;
+
+	/* Let the buffer end midway between the timezone offeset's "+12" and "34" */
+	header_end = header + strlen(header) - 2;
+
+	sig = git__calloc(1, sizeof(git_signature));
+	cl_assert(sig);
+
+	cl_git_pass(git_signature__parse(sig, &header, header_end, NULL, '\0'));
+	cl_assert_equal_s(sig->name, "A");
+	cl_assert_equal_s(sig->email, "a@example.com");
+	cl_assert_equal_i(sig->when.time, 1461698487);
+	cl_assert_equal_i(sig->when.offset, 12);
+
+	git_signature_free(sig);
+}
+
 void test_commit_signature__angle_brackets_in_names_are_not_supported(void)
 {
 	cl_git_fail(try_build_signature("<Phil Haack", "phil@haack", 1234567890, 60));