diff options
Diffstat (limited to 'fsck.c')
-rw-r--r-- | fsck.c | 76 |
1 files changed, 53 insertions, 23 deletions
@@ -148,20 +148,17 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func) struct tree_desc desc; unsigned o_mode; const char *o_name; - const unsigned char *o_sha1; init_tree_desc(&desc, item->buffer, item->size); o_mode = 0; o_name = NULL; - o_sha1 = NULL; while (desc.size) { unsigned mode; const char *name; - const unsigned char *sha1; - sha1 = tree_entry_extract(&desc, &name, &mode); + tree_entry_extract(&desc, &name, &mode); if (strchr(name, '/')) has_full_path = 1; @@ -207,7 +204,6 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func) o_mode = mode; o_name = name; - o_sha1 = sha1; } retval = 0; @@ -226,14 +222,51 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func) return retval; } +static int fsck_ident(char **ident, struct object *obj, fsck_error error_func) +{ + if (**ident == '<') + return error_func(obj, FSCK_ERROR, "invalid author/committer line - missing space before email"); + *ident += strcspn(*ident, "<>\n"); + if (**ident == '>') + return error_func(obj, FSCK_ERROR, "invalid author/committer line - bad name"); + if (**ident != '<') + return error_func(obj, FSCK_ERROR, "invalid author/committer line - missing email"); + if ((*ident)[-1] != ' ') + return error_func(obj, FSCK_ERROR, "invalid author/committer line - missing space before email"); + (*ident)++; + *ident += strcspn(*ident, "<>\n"); + if (**ident != '>') + return error_func(obj, FSCK_ERROR, "invalid author/committer line - bad email"); + (*ident)++; + if (**ident != ' ') + return error_func(obj, FSCK_ERROR, "invalid author/committer line - missing space before date"); + (*ident)++; + if (**ident == '0' && (*ident)[1] != ' ') + return error_func(obj, FSCK_ERROR, "invalid author/committer line - zero-padded date"); + *ident += strspn(*ident, "0123456789"); + if (**ident != ' ') + return error_func(obj, FSCK_ERROR, "invalid author/committer line - bad date"); + (*ident)++; + if ((**ident != '+' && **ident != '-') || + !isdigit((*ident)[1]) || + !isdigit((*ident)[2]) || + !isdigit((*ident)[3]) || + !isdigit((*ident)[4]) || + ((*ident)[5] != '\n')) + return error_func(obj, FSCK_ERROR, "invalid author/committer line - bad time zone"); + (*ident) += 6; + return 0; +} + static int fsck_commit(struct commit *commit, fsck_error error_func) { char *buffer = commit->buffer; unsigned char tree_sha1[20], sha1[20]; struct commit_graft *graft; int parents = 0; + int err; - if (!commit->date) + if (commit->date == ULONG_MAX) return error_func(&commit->object, FSCK_ERROR, "invalid author/committer line"); if (memcmp(buffer, "tree ", 5)) @@ -270,6 +303,16 @@ static int fsck_commit(struct commit *commit, fsck_error error_func) } if (memcmp(buffer, "author ", 7)) return error_func(&commit->object, FSCK_ERROR, "invalid format - expected 'author' line"); + buffer += 7; + err = fsck_ident(&buffer, &commit->object, error_func); + if (err) + return err; + if (memcmp(buffer, "committer ", strlen("committer "))) + return error_func(&commit->object, FSCK_ERROR, "invalid format - expected 'committer' line"); + buffer += strlen("committer "); + err = fsck_ident(&buffer, &commit->object, error_func); + if (err) + return err; if (!commit->tree) return error_func(&commit->object, FSCK_ERROR, "could not load commit's tree %s", sha1_to_hex(tree_sha1)); @@ -306,28 +349,15 @@ int fsck_object(struct object *obj, int strict, fsck_error error_func) int fsck_error_function(struct object *obj, int type, const char *fmt, ...) { va_list ap; - int len; - struct strbuf sb; + struct strbuf sb = STRBUF_INIT; - strbuf_init(&sb, 0); - strbuf_addf(&sb, "object %s:", obj->sha1?sha1_to_hex(obj->sha1):"(null)"); + strbuf_addf(&sb, "object %s:", sha1_to_hex(obj->sha1)); va_start(ap, fmt); - len = vsnprintf(sb.buf + sb.len, strbuf_avail(&sb), fmt, ap); + strbuf_vaddf(&sb, fmt, ap); va_end(ap); - if (len < 0) - len = 0; - if (len >= strbuf_avail(&sb)) { - strbuf_grow(&sb, len + 2); - va_start(ap, fmt); - len = vsnprintf(sb.buf + sb.len, strbuf_avail(&sb), fmt, ap); - va_end(ap); - if (len >= strbuf_avail(&sb)) - die("this should not happen, your snprintf is broken"); - } - - error(sb.buf); + error("%s", sb.buf); strbuf_release(&sb); return 1; } |