Rename parse_tag_buffer_internal() to parse_and_verify_tag_buffer() since it now does tag object verification as well. Add a new parameter 'thorough_verify' for turning on/off the extra code to be run when verifying tag objects (as opposed to general parsing). verify_tag() and parse_and_verify_tag_buffer() are now functionally equivalent, provided that parse_and_verify_tag_buffer() is called with item == NULL and thorough_verification != 0. Signed-off-by: Johan Herland <johan@xxxxxxxxxxx> --- tag.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 48 insertions(+), 2 deletions(-) diff --git a/tag.c b/tag.c index b134967..3896e45 100644 --- a/tag.c +++ b/tag.c @@ -33,7 +33,26 @@ struct tag *lookup_tag(const unsigned char *sha1) return (struct tag *) obj; } -static int parse_tag_buffer_internal(struct tag *item, const char *data, const unsigned long size) +/* + * We refuse to tag something we can't verify. Just because. + */ +static int verify_object(unsigned char *sha1, const char *expected_type) +{ + int ret = -1; + enum object_type type; + unsigned long size; + void *buffer = read_sha1_file(sha1, &type, &size); + + if (buffer) { + if (type == type_from_string(expected_type)) + ret = check_sha1_signature(sha1, buffer, size, expected_type); + free(buffer); + } + return ret; +} + +static int parse_and_verify_tag_buffer(struct tag *item, + const char *data, const unsigned long size, int thorough_verify) { #ifdef NO_C99_FORMAT #define PD_FMT "%d" @@ -79,6 +98,10 @@ static int parse_tag_buffer_internal(struct tag *item, const char *data, const u tagger_line = strchr(tag_line, '\n'); if (!tagger_line++) return error("char" PD_FMT ": could not find next \"\\n\"", tag_line - data); + if (thorough_verify) { + if (memcmp(tagger_line, "tagger ", 7) || (tagger_line[7] == '\n')) + return error("char" PD_FMT ": could not find \"tagger\"", tagger_line - data); + } /* Get the actual type */ type_len = tag_line - type_line - strlen("type \n"); @@ -87,6 +110,29 @@ static int parse_tag_buffer_internal(struct tag *item, const char *data, const u memcpy(type, type_line + 5, type_len); type[type_len] = '\0'; + if (thorough_verify) { + unsigned long i; + + /* Verify that the object matches */ + if (verify_object(sha1, type)) + return error("char%d: could not verify object %s", 7, sha1_to_hex(sha1)); + + /* Verify the tag-name: we don't allow control characters or spaces in it */ + for (i = 4;;) { + unsigned char c = tag_line[i++]; + if (c == '\n') + break; + if (c > ' ') + continue; + return error("char" PD_FMT ": could not verify tag name", tag_line + i - data); + } + + /* Verify the tagger line */ + /* TODO: check for committer/tagger info */ + + /* The actual stuff afterwards we don't care about.. */ + } + if (item) { tag_len = tagger_line - tag_line - strlen("tag \n"); item->tag = xmalloc(tag_len + 1); @@ -120,7 +166,7 @@ static int parse_tag_buffer_internal(struct tag *item, const char *data, const u int parse_tag_buffer(struct tag *item, void *data, unsigned long size) { - return parse_tag_buffer_internal(item, (const char *) data, size); + return parse_and_verify_tag_buffer(item, (const char *) data, size, 0); } int parse_tag(struct tag *item) -- 1.5.2 - 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