Merge pull request #454 from brodie/parsing-fixes Improvements to tag, commit, and signature parsing
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
diff --git a/src/commit.c b/src/commit.c
index 0ee3854..ced457e 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -221,10 +221,10 @@ int git_commit__parse_buffer(git_commit *commit, const void *data, size_t len)
}
/* parse commit message */
- while (buffer < buffer_end && *buffer == '\n')
+ while (buffer < buffer_end - 1 && *buffer == '\n')
buffer++;
- if (buffer < buffer_end) {
+ if (buffer <= buffer_end) {
commit->message = git__strndup(buffer, buffer_end - buffer);
if (!commit->message)
return GIT_ENOMEM;
diff --git a/src/signature.c b/src/signature.c
index ebb56d7..388e8d9 100644
--- a/src/signature.c
+++ b/src/signature.c
@@ -279,7 +279,7 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
if ((name_end = strchr(buffer, '<')) == NULL)
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Cannot find '<' in signature");
- if ((email_end = strchr(buffer, '>')) == NULL)
+ if ((email_end = strchr(name_end, '>')) == NULL)
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Cannot find '>' in signature");
if (email_end < name_end)
diff --git a/src/tag.c b/src/tag.c
index fc9f8b5..ba75104 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -122,14 +122,15 @@ static int parse_tag_buffer(git_tag *tag, const char *buffer, const char *buffer
buffer = search + 1;
- tag->tagger = git__malloc(sizeof(git_signature));
- if (tag->tagger == NULL)
- return GIT_ENOMEM;
-
- if ((error = git_signature__parse(tag->tagger, &buffer, buffer_end, "tagger ", '\n')) != 0) {
- free(tag->tag_name);
- git_signature_free(tag->tagger);
- return git__rethrow(error, "Failed to parse tag");
+ tag->tagger = NULL;
+ if (*buffer != '\n') {
+ tag->tagger = git__malloc(sizeof(git_signature));
+ if (tag->tagger == NULL)
+ return GIT_ENOMEM;
+
+ if ((error = git_signature__parse(tag->tagger, &buffer, buffer_end, "tagger ", '\n') != 0)) {
+ return git__rethrow(error, "Failed to parse tag");
+ }
}
if( *buffer != '\n' )
diff --git a/tests/resources/bad_tag.git/HEAD b/tests/resources/bad_tag.git/HEAD
new file mode 100644
index 0000000..cb089cd
--- /dev/null
+++ b/tests/resources/bad_tag.git/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/tests/resources/bad_tag.git/config b/tests/resources/bad_tag.git/config
new file mode 100644
index 0000000..2f89580
--- /dev/null
+++ b/tests/resources/bad_tag.git/config
@@ -0,0 +1,5 @@
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = true
+ logallrefupdates = true
diff --git a/tests/resources/bad_tag.git/objects/pack/pack-7a28f4e000a17f49a41d7a79fc2f762a8a7d9164.idx b/tests/resources/bad_tag.git/objects/pack/pack-7a28f4e000a17f49a41d7a79fc2f762a8a7d9164.idx
new file mode 100644
index 0000000..c404aa1
Binary files /dev/null and b/tests/resources/bad_tag.git/objects/pack/pack-7a28f4e000a17f49a41d7a79fc2f762a8a7d9164.idx differ
diff --git a/tests/resources/bad_tag.git/objects/pack/pack-7a28f4e000a17f49a41d7a79fc2f762a8a7d9164.pack b/tests/resources/bad_tag.git/objects/pack/pack-7a28f4e000a17f49a41d7a79fc2f762a8a7d9164.pack
new file mode 100644
index 0000000..90eac50
Binary files /dev/null and b/tests/resources/bad_tag.git/objects/pack/pack-7a28f4e000a17f49a41d7a79fc2f762a8a7d9164.pack differ
diff --git a/tests/resources/bad_tag.git/packed-refs b/tests/resources/bad_tag.git/packed-refs
new file mode 100644
index 0000000..f9fd2fd
--- /dev/null
+++ b/tests/resources/bad_tag.git/packed-refs
@@ -0,0 +1,3 @@
+# pack-refs with: peeled
+eda9f45a2a98d4c17a09d681d88569fa4ea91755 refs/tags/e90810b
+^e90810b8df3e80c413d903f631643c716887138d
diff --git a/tests/resources/testrepo.git/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc b/tests/resources/testrepo.git/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc
new file mode 100644
index 0000000..9bb5b62
Binary files /dev/null and b/tests/resources/testrepo.git/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc differ
diff --git a/tests/resources/testrepo.git/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 b/tests/resources/testrepo.git/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162
new file mode 100644
index 0000000..4cc3f4d
--- /dev/null
+++ b/tests/resources/testrepo.git/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162
@@ -0,0 +1 @@
+x+)JMU044b040031QrutueXlmmAṃJ}G;UTWRQ`6Kǥ^/-*|W3Py`%E\&g|0{Ӎ1X
\ No newline at end of file
diff --git a/tests/resources/testrepo.git/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 b/tests/resources/testrepo.git/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750
new file mode 100644
index 0000000..29c8e82
--- /dev/null
+++ b/tests/resources/testrepo.git/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750
@@ -0,0 +1,3 @@
+xQ
+!@sBQ" ٱ
r{<xƪ
+HlJSer!ZPTe*jUEo^2(XSEDO<Yj$2s_&},}[~p7~<: Zp?1_C0
\ No newline at end of file
diff --git a/tests/resources/testrepo.git/refs/heads/master b/tests/resources/testrepo.git/refs/heads/master
index 9536ad8..3d8f0a4 100644
--- a/tests/resources/testrepo.git/refs/heads/master
+++ b/tests/resources/testrepo.git/refs/heads/master
@@ -1 +1 @@
-be3563ae3f795b2b4353bcce3a527ad0a4f7f644
+a65fedf39aefe402d3bb6e24df4d4f5fe4547750
diff --git a/tests/t04-commit.c b/tests/t04-commit.c
index 88c7efd..3fb4d37 100644
--- a/tests/t04-commit.c
+++ b/tests/t04-commit.c
@@ -412,6 +412,14 @@ BEGIN_TEST(parse1, "parse the signature line in a commit")
1234567890,
0);
+ TEST_SIGNATURE_PASS(
+ "author A U Thor> <author@example.com> and others 1234567890\n",
+ "author ",
+ "A U Thor>",
+ "author@example.com",
+ 1234567890,
+ 0);
+
TEST_SIGNATURE_FAIL(
"committer Vicent Marti tanoku@gmail.com> 123456 -0100 \n",
"committer ");
@@ -560,6 +568,7 @@ static const char *commit_ids[] = {
"c47800c7266a2be04c571c04d5a6614691ea99bd", /* 3 */
"8496071c1b46c854b31185ea97743be6a8774479", /* 4 */
"5b5b025afb0b4c913b4c338a42934a3863bf3644", /* 5 */
+ "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", /* 6 */
};
BEGIN_TEST(details0, "query the details on a parsed commit")
@@ -594,6 +603,7 @@ BEGIN_TEST(details0, "query the details on a parsed commit")
must_be_true(strcmp(author->email, "schacon@gmail.com") == 0);
must_be_true(strcmp(committer->name, "Scott Chacon") == 0);
must_be_true(strcmp(committer->email, "schacon@gmail.com") == 0);
+ must_be_true(message != NULL);
must_be_true(strchr(message, '\n') != NULL);
must_be_true(commit_time > 0);
must_be_true(parents <= 2);
diff --git a/tests/t08-tag.c b/tests/t08-tag.c
index b0d4af8..216fb9d 100644
--- a/tests/t08-tag.c
+++ b/tests/t08-tag.c
@@ -30,6 +30,8 @@
static const char *tag1_id = "b25fa35b38051e4ae45d4222e795f9df2e43f1d1";
static const char *tag2_id = "7b4384978d2493e851f9cca7858815fac9b10980";
static const char *tagged_commit = "e90810b8df3e80c413d903f631643c716887138d";
+static const char *bad_tag_id = "eda9f45a2a98d4c17a09d681d88569fa4ea91755";
+static const char *badly_tagged_commit = "e90810b8df3e80c413d903f631643c716887138d";
BEGIN_TEST(read0, "read and parse a tag from the repository")
git_repository *repo;
@@ -106,6 +108,37 @@ BEGIN_TEST(read2, "list all tag names from the repository matching a specified p
git_repository_free(repo);
END_TEST
+#define BAD_TAG_REPOSITORY_FOLDER TEST_RESOURCES "/bad_tag.git/"
+
+BEGIN_TEST(read3, "read and parse a tag without a tagger field")
+ git_repository *repo;
+ git_tag *bad_tag;
+ git_commit *commit;
+ git_oid id, id_commit;
+
+ must_pass(git_repository_open(&repo, BAD_TAG_REPOSITORY_FOLDER));
+
+ git_oid_fromstr(&id, bad_tag_id);
+ git_oid_fromstr(&id_commit, badly_tagged_commit);
+
+ must_pass(git_tag_lookup(&bad_tag, repo, &id));
+ must_be_true(bad_tag != NULL);
+
+ must_be_true(strcmp(git_tag_name(bad_tag), "e90810b") == 0);
+ must_be_true(git_oid_cmp(&id, git_tag_id(bad_tag)) == 0);
+ must_be_true(bad_tag->tagger == NULL);
+
+ must_pass(git_tag_target((git_object **)&commit, bad_tag));
+ must_be_true(commit != NULL);
+
+ must_be_true(git_oid_cmp(&id_commit, git_commit_id(commit)) == 0);
+
+ git_tag_close(bad_tag);
+ git_commit_close(commit);
+
+ git_repository_free(repo);
+END_TEST
+
#define TAGGER_NAME "Vicent Marti"
#define TAGGER_EMAIL "vicent@github.com"
@@ -304,6 +337,7 @@ BEGIN_SUITE(tag)
ADD_TEST(read0);
ADD_TEST(read1);
ADD_TEST(read2);
+ ADD_TEST(read3);
ADD_TEST(write0);
ADD_TEST(write2);
diff --git a/tests/t10-refs.c b/tests/t10-refs.c
index 6703415..1b3e0a3 100644
--- a/tests/t10-refs.c
+++ b/tests/t10-refs.c
@@ -70,7 +70,7 @@ END_TEST
static const char *head_tracker_sym_ref_name = "head-tracker";
static const char *current_head_target = "refs/heads/master";
-static const char *current_master_tip = "be3563ae3f795b2b4353bcce3a527ad0a4f7f644";
+static const char *current_master_tip = "a65fedf39aefe402d3bb6e24df4d4f5fe4547750";
BEGIN_TEST(readsym0, "lookup a symbolic reference")
git_repository *repo;