Commit 5d844a1e3768d8c536169a754802b4bf8ebdd64c

Stefan Sperling 2019-08-13T15:41:46

don't attempt to parse Git's "leightweight" tags as real tag objects

diff --git a/got/got.c b/got/got.c
index 2a63d8f..263bc2c 100644
--- a/got/got.c
+++ b/got/got.c
@@ -1402,8 +1402,13 @@ print_commit(struct got_commit_object *commit, struct got_object_id *id,
 			name += 8;
 		if (strncmp(name, "tags/", 5) == 0) {
 			err = got_object_open_as_tag(&tag, repo, re->id);
-			if (err)
-				return err;
+			if (err) {
+				if (err->code != GOT_ERR_OBJ_TYPE)
+					return err;
+				/* Ref points at something other than a tag. */
+				err = NULL;
+				tag = NULL;
+			}
 		}
 		cmp = got_object_id_cmp(tag ?
 		    got_object_tag_get_object_id(tag) : re->id, id);
diff --git a/lib/object.c b/lib/object.c
index 63fbc85..79ee0f0 100644
--- a/lib/object.c
+++ b/lib/object.c
@@ -1307,6 +1307,8 @@ open_tag(struct got_tag_object **tag, struct got_repository *repo,
 	struct got_packidx *packidx = NULL;
 	int idx;
 	char *path_packfile = NULL;
+	struct got_object *obj = NULL;
+	int obj_type = GOT_OBJ_TYPE_ANY;
 
 	if (check_cache) {
 		*tag = got_repo_get_cached_tag(repo, id);
@@ -1332,14 +1334,36 @@ open_tag(struct got_tag_object **tag, struct got_repository *repo,
 			if (err)
 				goto done;
 		}
-		err = read_packed_tag_privsep(tag, pack,
-		    packidx, idx, id);
+
+		/* Beware of "leightweight" tags: Check object type first. */
+		err = read_packed_object_privsep(&obj, repo, pack, packidx,
+		    idx, id);
+		if (err)
+			goto done;
+		obj_type = obj->type;
+		got_object_close(obj);
+		if (obj_type != GOT_OBJ_TYPE_TAG) {
+			err = got_error(GOT_ERR_OBJ_TYPE);
+			goto done;
+		}
+		err = read_packed_tag_privsep(tag, pack, packidx, idx, id);
 	} else if (err->code == GOT_ERR_NO_OBJ) {
 		int fd;
 
 		err = open_loose_object(&fd, id, repo);
 		if (err)
 			return err;
+		err = read_object_header_privsep(&obj, repo, fd);
+		if (err)
+			return err;
+		obj_type = obj->type;
+		got_object_close(obj);
+		if (obj_type != GOT_OBJ_TYPE_TAG)
+			return got_error(GOT_ERR_OBJ_TYPE);
+
+		err = open_loose_object(&fd, id, repo);
+		if (err)
+			return err;
 		err = read_tag_privsep(tag, fd, repo);
 	}
 
diff --git a/tog/tog.c b/tog/tog.c
index 68b3beb..330cb72 100644
--- a/tog/tog.c
+++ b/tog/tog.c
@@ -998,8 +998,13 @@ build_refs_str(char **refs_str, struct got_reflist_head *refs,
 			name += 8;
 		if (strncmp(name, "tags/", 5) == 0) {
 			err = got_object_open_as_tag(&tag, repo, re->id);
-			if (err)
-				break;
+			if (err) {
+				if (err->code != GOT_ERR_OBJ_TYPE)
+					break;
+				/* Ref points at something other than a tag. */
+				err = NULL;
+				tag = NULL;
+			}
 		}
 		cmp = got_object_id_cmp(tag ?
 		    got_object_tag_get_object_id(tag) : re->id, id);