{"thread":{"id":"7095","subject":"[PATCH 2/2] fast-import: Fail if a non-existant commit is used for merge","startedAt":"2007-03-05T17:46:10Z","lastAt":"2007-03-05T17:46:10Z","messageCount":1,"participants":["Shawn O. Pearce"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"36346","messageId":"20070305174610.GB22304@spearce.org","threadId":"7095","inReplyTo":null,"subject":"[PATCH 2/2] fast-import: Fail if a non-existant commit is used for merge","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-03-05T17:46:10Z","receivedAt":"2007-03-05T17:46:10Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Johannes Sixt noticed during one of his own imports that fast-import\ndid not fail if a non-existant commit is referenced by SHA-1 value\nas an argument to the 'merge' command.  This allowed the user to\nunknowingly create commits that would fail in fsck, as the commit\ncontents would not be completely reachable.\n\nA side effect of this bug was that a frontend process could mark\nany SHA-1 object (blob, tree, tag) as a parent of a merge commit.\nThis should also fail in fsck, as the commit is not a valid commit.\n\nWe now use the same rule as the 'from' command.  If a commit is\nreferenced in the 'merge' command by hex formatted SHA-1 then the\nSHA-1 must be a commit or a tag that can be peeled back to a commit,\nthe commit must already exist, and must be readable by the core Git\ninfrastructure code.  This requirement means that the commit must\nhave existed prior to fast-import starting, or the commit must have\nbeen flushed out by a prior 'checkpoint' command.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n fast-import.c |    9 ++++++++-\n 1 files changed, 8 insertions(+), 1 deletions(-)\n\ndiff --git a/fast-import.c b/fast-import.c\nindex 490f640..d9492b9 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -1752,7 +1752,14 @@ static struct hash_list *cmd_merge(unsigned int *count)\n \t\t\tif (oe->type != OBJ_COMMIT)\n \t\t\t\tdie(\"Mark :%\" PRIuMAX \" not a commit\", idnum);\n \t\t\thashcpy(n->sha1, oe->sha1);\n-\t\t} else if (get_sha1(from, n->sha1))\n+\t\t} else if (!get_sha1(from, n->sha1)) {\n+\t\t\tunsigned long size;\n+\t\t\tchar *buf = read_object_with_reference(n->sha1,\n+\t\t\t\ttype_names[OBJ_COMMIT], &size, n->sha1);\n+\t\t\tif (!buf || size < 46)\n+\t\t\t\tdie(\"Not a valid commit: %s\", from);\n+\t\t\tfree(buf);\n+\t\t} else\n \t\t\tdie(\"Invalid ref name or SHA1 expression: %s\", from);\n \n \t\tn->next = NULL;\n-- \n1.5.0.3.862.g71037\n"}]}