{"thread":{"id":"21835","subject":"[PATCH for v1.6.6] Fix crasher on encountering SHA1-like non-note in notes tree","startedAt":"2009-12-03T03:53:54Z","lastAt":"2009-12-03T03:53:54Z","messageCount":1,"participants":["Johan Herland"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"129096","messageId":"1259812434-24471-1-git-send-email-johan@herland.net","threadId":"21835","inReplyTo":null,"subject":"[PATCH for v1.6.6] Fix crasher on encountering SHA1-like non-note in notes tree","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-12-03T03:53:54Z","receivedAt":"2009-12-03T03:53:54Z","isPatch":true,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"When loading a notes tree, the code primarily looks for SHA1-like paths\nwhose total length (discounting directory separators) are 40 chars\n(interpreted as valid note entries) or less (interpreted as subtree\nentries that may in turn contain note entries when unpacked).\n\nHowever, there is an additional condition that must hold for valid\nsubtree entries: They must be _tree_ objects (duh).\n\nThis patch adds an appropriate test for this condition, thereby fixing\nthe crash that occured when passing a non-tree object to the tree-walk\nAPI.\n\nThe patch also adds another selftest verifying correct behaviour of\nnon-notes in note trees.\n\nSigned-off-by: Johan Herland <johan@herland.net>\n---\n\nJunio,\n\nI believe this should be included in v1.6.6. It fixes an existing crasher in\nthe early part of the notes series.\n\n\n...Johan\n\n notes.c                |    2 +\n t/t3304-notes-mixed.sh |  172 ++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 174 insertions(+), 0 deletions(-)\n create mode 100755 t/t3304-notes-mixed.sh\n\ndiff --git a/notes.c b/notes.c\nindex 50a4672..023adce 100644\n--- a/notes.c\n+++ b/notes.c\n@@ -331,6 +331,8 @@ static void load_subtree(struct leaf_node *subtree, struct int_node *node,\n \t\t\thashcpy(l->key_sha1, commit_sha1);\n \t\t\thashcpy(l->val_sha1, entry.sha1);\n \t\t\tif (len < 20) {\n+\t\t\t\tif (!S_ISDIR(entry.mode))\n+\t\t\t\t\tcontinue; /* entry cannot be subtree */\n \t\t\t\tl->key_sha1[19] = (unsigned char) len;\n \t\t\t\ttype = PTR_TYPE_SUBTREE;\n \t\t\t}\ndiff --git a/t/t3304-notes-mixed.sh b/t/t3304-notes-mixed.sh\nnew file mode 100755\nindex 0000000..256687f\n--- /dev/null\n+++ b/t/t3304-notes-mixed.sh\n@@ -0,0 +1,172 @@\n+#!/bin/sh\n+\n+test_description='Test notes trees that also contain non-notes'\n+\n+. ./test-lib.sh\n+\n+number_of_commits=100\n+\n+start_note_commit () {\n+\ttest_tick &&\n+\tcat <<INPUT_END\n+commit refs/notes/commits\n+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+data <<COMMIT\n+notes\n+COMMIT\n+\n+from refs/notes/commits^0\n+deleteall\n+INPUT_END\n+\n+}\n+\n+verify_notes () {\n+\tgit log | grep \"^    \" > output &&\n+\ti=$number_of_commits &&\n+\twhile [ $i -gt 0 ]; do\n+\t\techo \"    commit #$i\" &&\n+\t\techo \"    note for commit #$i\" &&\n+\t\ti=$(($i-1));\n+\tdone > expect &&\n+\ttest_cmp expect output\n+}\n+\n+test_expect_success \"setup: create a couple of commits\" '\n+\n+\ttest_tick &&\n+\tcat <<INPUT_END >input &&\n+commit refs/heads/master\n+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+data <<COMMIT\n+commit #1\n+COMMIT\n+\n+M 644 inline file\n+data <<EOF\n+file in commit #1\n+EOF\n+\n+INPUT_END\n+\n+\ttest_tick &&\n+\tcat <<INPUT_END >>input &&\n+commit refs/heads/master\n+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+data <<COMMIT\n+commit #2\n+COMMIT\n+\n+M 644 inline file\n+data <<EOF\n+file in commit #2\n+EOF\n+\n+INPUT_END\n+\tgit fast-import --quiet <input\n+'\n+\n+test_expect_success \"create a notes tree with both notes and non-notes\" '\n+\n+\tcommit1=$(git rev-parse refs/heads/master^) &&\n+\tcommit2=$(git rev-parse refs/heads/master) &&\n+\ttest_tick &&\n+\tcat <<INPUT_END >input &&\n+commit refs/notes/commits\n+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+data <<COMMIT\n+notes commit #1\n+COMMIT\n+\n+N inline $commit1\n+data <<EOF\n+note for commit #1\n+EOF\n+\n+N inline $commit2\n+data <<EOF\n+note for commit #2\n+EOF\n+\n+INPUT_END\n+\ttest_tick &&\n+\tcat <<INPUT_END >>input &&\n+commit refs/notes/commits\n+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+data <<COMMIT\n+notes commit #2\n+COMMIT\n+\n+M 644 inline foobar/non-note.txt\n+data <<EOF\n+A non-note in a notes tree\n+EOF\n+\n+N inline $commit2\n+data <<EOF\n+edited note for commit #2\n+EOF\n+\n+INPUT_END\n+\ttest_tick &&\n+\tcat <<INPUT_END >>input &&\n+commit refs/notes/commits\n+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+data <<COMMIT\n+notes commit #3\n+COMMIT\n+\n+N inline $commit1\n+data <<EOF\n+edited note for commit #1\n+EOF\n+\n+M 644 inline deadbeef\n+data <<EOF\n+non-note with SHA1-like name\n+EOF\n+\n+M 644 inline de/adbeef\n+data <<EOF\n+another non-note with SHA1-like name\n+EOF\n+\n+INPUT_END\n+\tgit fast-import --quiet <input &&\n+\tgit config core.notesRef refs/notes/commits\n+'\n+\n+cat >expect <<EXPECT_END\n+    commit #2\n+    edited note for commit #2\n+    commit #1\n+    edited note for commit #1\n+EXPECT_END\n+\n+test_expect_success \"verify contents of notes\" '\n+\n+\tgit log | grep \"^    \" > actual &&\n+\ttest_cmp expect actual\n+'\n+\n+cat >expect_nn1 <<EXPECT_END\n+A non-note in a notes tree\n+EXPECT_END\n+cat >expect_nn2 <<EXPECT_END\n+non-note with SHA1-like name\n+EXPECT_END\n+cat >expect_nn3 <<EXPECT_END\n+another non-note with SHA1-like name\n+EXPECT_END\n+\n+test_expect_success \"verify contents of non-notes\" '\n+\n+\tgit cat-file -p refs/notes/commits:foobar/non-note.txt > actual_nn1 &&\n+\ttest_cmp expect_nn1 actual_nn1 &&\n+\tgit cat-file -p refs/notes/commits:deadbeef > actual_nn2 &&\n+\ttest_cmp expect_nn2 actual_nn2 &&\n+\tgit cat-file -p refs/notes/commits:de/adbeef > actual_nn3 &&\n+\ttest_cmp expect_nn3 actual_nn3\n+'\n+\n+test_done\n--\n1.6.5.3.433.g11067\n"}]}