From: Junio C Hamano Date: Wed, 2 Nov 2005 23:19:13 +0000 (-0800) Subject: Be careful when dereferencing tags. X-Git-Tag: v0.99.9c^2~7 X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=9534f40bc42dd826cc26c8c8c84f6a8a5fc569f6;p=git.git Be careful when dereferencing tags. One caller of deref_tag() was not careful enough to make sure what deref_tag() returned was not NULL (i.e. we found a tag object that points at an object we do not have). Fix it, and warn about refs that point at such an incomplete tag where needed. Signed-off-by: Junio C Hamano --- diff --git a/commit.c b/commit.c index 8f403180e..a8c9bfc8b 100644 --- a/commit.c +++ b/commit.c @@ -55,7 +55,7 @@ static struct commit *check_commit(struct object *obj, struct commit *lookup_commit_reference_gently(const unsigned char *sha1, int quiet) { - struct object *obj = deref_tag(parse_object(sha1)); + struct object *obj = deref_tag(parse_object(sha1), NULL, 0); if (!obj) return NULL; diff --git a/fetch-pack.c b/fetch-pack.c index 3df991100..cb2171523 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -38,9 +38,9 @@ static void rev_list_push(struct commit *commit, int mark) static int rev_list_insert_ref(const char *path, const unsigned char *sha1) { - struct object *o = deref_tag(parse_object(sha1)); + struct object *o = deref_tag(parse_object(sha1), path, 0); - if (o->type == commit_type) + if (o && o->type == commit_type) rev_list_push((struct commit *)o, SEEN); return 0; @@ -317,7 +317,8 @@ static int everything_local(struct ref **refs, int nr_match, char **match) * Don't mark them common yet; the server has to be told so first. */ for (ref = *refs; ref; ref = ref->next) { - struct object *o = deref_tag(lookup_object(ref->old_sha1)); + struct object *o = deref_tag(lookup_object(ref->old_sha1), + NULL, 0); if (!o || o->type != commit_type || !(o->flags & COMPLETE)) continue; diff --git a/name-rev.c b/name-rev.c index 21fecdf54..59194f134 100644 --- a/name-rev.c +++ b/name-rev.c @@ -164,7 +164,7 @@ int main(int argc, char **argv) continue; } - o = deref_tag(parse_object(sha1)); + o = deref_tag(parse_object(sha1), *argv, 0); if (!o || o->type != commit_type) { fprintf(stderr, "Could not get commit for %s. Skipping.\n", *argv); diff --git a/send-pack.c b/send-pack.c index 9f9a6e70b..3eeb18f7c 100644 --- a/send-pack.c +++ b/send-pack.c @@ -126,12 +126,12 @@ static int ref_newer(const unsigned char *new_sha1, /* Both new and old must be commit-ish and new is descendant of * old. Otherwise we require --force. */ - o = deref_tag(parse_object(old_sha1)); + o = deref_tag(parse_object(old_sha1), NULL, 0); if (!o || o->type != commit_type) return 0; old = (struct commit *) o; - o = deref_tag(parse_object(new_sha1)); + o = deref_tag(parse_object(new_sha1), NULL, 0); if (!o || o->type != commit_type) return 0; new = (struct commit *) o; diff --git a/server-info.c b/server-info.c index ba5359108..0cba8e19f 100644 --- a/server-info.c +++ b/server-info.c @@ -13,9 +13,10 @@ static int add_info_ref(const char *path, const unsigned char *sha1) fprintf(info_ref_fp, "%s %s\n", sha1_to_hex(sha1), path); if (o->type == tag_type) { - o = deref_tag(o); - fprintf(info_ref_fp, "%s %s^{}\n", - sha1_to_hex(o->sha1), path); + o = deref_tag(o, path, 0); + if (o) + fprintf(info_ref_fp, "%s %s^{}\n", + sha1_to_hex(o->sha1), path); } return 0; } diff --git a/sha1_name.c b/sha1_name.c index fe409fbce..be1755a70 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -349,7 +349,7 @@ static int peel_onion(const char *name, int len, unsigned char *sha1) if (!o) return -1; if (!type_string) { - o = deref_tag(o); + o = deref_tag(o, name, sp - name - 2); if (!o || (!o->parsed && !parse_object(o->sha1))) return -1; memcpy(sha1, o->sha1, 20); diff --git a/tag.c b/tag.c index b1ab75ff0..e574c4b7a 100644 --- a/tag.c +++ b/tag.c @@ -3,10 +3,15 @@ const char *tag_type = "tag"; -struct object *deref_tag(struct object *o) +struct object *deref_tag(struct object *o, const char *warn, int warnlen) { while (o && o->type == tag_type) o = parse_object(((struct tag *)o)->tagged->sha1); + if (!o && warn) { + if (!warnlen) + warnlen = strlen(warn); + error("missing object referenced by '%.*s'", warnlen, warn); + } return o; } diff --git a/tag.h b/tag.h index 36e532401..7a0cb0070 100644 --- a/tag.h +++ b/tag.h @@ -15,6 +15,6 @@ struct tag { extern struct tag *lookup_tag(const unsigned char *sha1); extern int parse_tag_buffer(struct tag *item, void *data, unsigned long size); extern int parse_tag(struct tag *item); -extern struct object *deref_tag(struct object *); +extern struct object *deref_tag(struct object *, const char *, int); #endif /* TAG_H */ diff --git a/upload-pack.c b/upload-pack.c index c5eff2136..be6313280 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -226,7 +226,7 @@ static int send_ref(const char *refname, const unsigned char *sha1) nr_our_refs++; } if (o->type == tag_type) { - o = deref_tag(o); + o = deref_tag(o, refname, 0); packet_write(1, "%s %s^{}\n", sha1_to_hex(o->sha1), refname); } return 0;