We inspect commit objects pretty much in detail in git-fsck, but we just glanced over the tag objects. Let's be stricter. This work was sponsored by GitHub Inc. Signed-off-by: Johannes Schindelin <johannes.schindelin@xxxxxx> --- fsck.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/fsck.c b/fsck.c index db6aaa4..d30946b 100644 --- a/fsck.c +++ b/fsck.c @@ -6,6 +6,7 @@ #include "commit.h" #include "tag.h" #include "fsck.h" +#include "refs.h" static int fsck_walk_tree(struct tree *tree, fsck_walk_func walk, void *data) { @@ -355,6 +356,90 @@ static int fsck_commit(struct commit *commit, const char *data, return ret; } +static int fsck_tag_buffer(struct tag *tag, const char *data, + unsigned long size, fsck_error error_func) +{ + unsigned char commit_sha1[20]; + int ret = 0; + const char *buffer; + char *tmp = NULL, *eol; + + if (data) + buffer = data; + else { + enum object_type type; + + buffer = tmp = read_sha1_file(tag->object.sha1, &type, &size); + if (!buffer) + return error_func(&tag->object, FSCK_ERROR, + "cannot read tag object"); + + if (type != OBJ_TAG) { + ret = error_func(&tag->object, FSCK_ERROR, + "expected tag got %s", + typename(type)); + goto done; + } + } + + if (must_have_empty_line(buffer, size, &tag->object, error_func)) + goto done; + + if (!skip_prefix(buffer, "object ", &buffer)) { + ret = error_func(&tag->object, FSCK_ERROR, "invalid format - expected 'object' line"); + goto done; + } + if (get_sha1_hex(buffer, commit_sha1) || buffer[40] != '\n') { + ret = error_func(&tag->object, FSCK_ERROR, "invalid 'object' line format - bad sha1"); + goto done; + } + buffer += 41; + + if (!skip_prefix(buffer, "type ", &buffer)) { + ret = error_func(&tag->object, FSCK_ERROR, "invalid format - expected 'type' line"); + goto done; + } + eol = strchr(buffer, '\n'); + if (!eol) { + ret = error_func(&tag->object, FSCK_ERROR, "invalid format - unexpected end after 'type' line"); + goto done; + } + *eol = '\0'; + if (type_from_string_gently(buffer) < 0) + ret = error_func(&tag->object, FSCK_ERROR, "invalid 'type' value"); + *eol = '\n'; + if (ret) + goto done; + buffer = eol + 1; + + if (!skip_prefix(buffer, "tag ", &buffer)) { + ret = error_func(&tag->object, FSCK_ERROR, "invalid format - expected 'tag' line"); + goto done; + } + eol = strchr(buffer, '\n'); + if (!eol) { + ret = error_func(&tag->object, FSCK_ERROR, "invalid format - unexpected end after 'type' line"); + goto done; + } + *eol = '\0'; + if (check_refname_format(buffer, REFNAME_ALLOW_ONELEVEL)) + ret = error_func(&tag->object, FSCK_ERROR, "invalid 'tag' name: %s", buffer); + *eol = '\n'; + if (ret) + goto done; + buffer = eol + 1; + + if (!skip_prefix(buffer, "tagger ", &buffer)) { + /* early tags do not contain 'tagger' lines; warn only */ + error_func(&tag->object, FSCK_WARN, "invalid format - expected 'tagger' line"); + } + ret = fsck_ident(&buffer, &tag->object, error_func); + +done: + free(tmp); + return ret; +} + static int fsck_tag(struct tag *tag, const char *data, unsigned long size, fsck_error error_func) { @@ -362,7 +447,8 @@ static int fsck_tag(struct tag *tag, const char *data, if (!tagged) return error_func(&tag->object, FSCK_ERROR, "could not load tagged object"); - return 0; + + return fsck_tag_buffer(tag, data, size, error_func); } int fsck_object(struct object *obj, void *data, unsigned long size, -- 2.0.0.rc3.9669.g840d1f9 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html