git/list[1] front-page[2] threads[3] people[4] search[5] about
 

merge: fix NULL pointer dereference when merging nothing into void

From
Junio C Hamano <gitster@pobox.com>
Date
Mar 21, 2016, 19:01 UTC
Message-ID
<xmqq7fgvmz8o.fsf_-_@gitster.mtv.corp.google.com>
In-Reply-To
<1458519102-32621-1-git-send-email-joseivan@lavid.ufpb.br>

When we are on an unborn branch and merging only one foreign parent, we allow "git merge" to fast-forward to that foreign parent commit.

This codepath incorrectly attempted to dereference the list of parents that the merge is going to record even when the list is empty. It must refuse to operate instead when there is no parent.

All other codepaths make sure the list is not empty before they dereference it, and are safe.

Reported by Jose Ivan B. Vilarouca Filho
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 * So here is what I came up with as a suggestion.  The original
   check to see if remote_head is empty is simply bogus (an empty
   list would to have a single element whose item is NULL), so I
   rewrote it to clarify what is going on in this codepath.
 builtin/merge.c  | 10 +++++-----
 t/t7600-merge.sh | 10 ++++++++++
 2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/builtin/merge.c b/builtin/merge.c
index 101ffef..bf2f261 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1257,12 +1257,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			builtin_merge_options);
 
 	if (!head_commit) {
-		struct commit *remote_head;
 		/*
 		 * If the merged head is a valid one there is no reason
 		 * to forbid "git merge" into a branch yet to be born.
 		 * We do the same for "git pull".
 		 */
+		unsigned char *remote_head_sha1;
 		if (squash)
 			die(_("Squash commit into empty head not supported yet"));
 		if (fast_forward == FF_NO)
@@ -1270,13 +1270,13 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			    "an empty head"));
 		remoteheads = collect_parents(head_commit, &head_subsumed,
 					      argc, argv, NULL);
-		remote_head = remoteheads->item;
-		if (!remote_head)
+		if (!remoteheads)
 			die(_("%s - not something we can merge"), argv[0]);
 		if (remoteheads->next)
 			die(_("Can merge only exactly one commit into empty head"));
-		read_empty(remote_head->object.oid.hash, 0);
-		update_ref("initial pull", "HEAD", remote_head->object.oid.hash,
+		remote_head_sha1 = remoteheads->item->object.oid.hash;
+		read_empty(remote_head_sha1, 0);
+		update_ref("initial pull", "HEAD", remote_head_sha1,
 			   NULL, 0, UPDATE_REFS_DIE_ON_ERR);
 		goto done;
 	}
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 302e238..9d7952f 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -725,4 +725,14 @@ test_expect_success 'merge detects mod-256 conflicts (resolve)' '
 	test_must_fail git merge -s resolve master
 '
 
+test_expect_success 'merge nothing into void' '
+	git init void &&
+	(
+		cd void &&
+		git remote add up .. &&
+		git fetch up &&
+		test_must_fail git merge FETCH_HEAD
+	)
+'
+
 test_done
Previous: Eric SunshineNext: Eric Sunshine
Message 5 of 6 in “Fixing segmentation fault when merging FETCH_HEAD”
  1. Fixing segmentation fault when merging FETCH_HEADJose Ivan B. Vilarouca Filho, Mar 19, 2016
  2. Eric SunshineMar 20, 2016
  3. Jose Ivan B. Vilarouca FilhoMar 21, 2016
  4. Eric SunshineMar 21, 2016
  5. merge: fix NULL pointer dereference when merging nothing into voidJunio C Hamano, Mar 21, 2016
  6. Eric SunshineMar 21, 2016

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.