From: Junio C Hamano Date: Thu, 22 Dec 2005 09:39:24 GMT Subject: Re: [PATCH] sanity check in add_packed_git() Message-ID: <7v4q51qxmb.fsf@assigned-by-dhcp.cox.net> In-Reply-To: Daniel Barkalow writes: > I'd like to require it to be a hash, just because that makes it > prohibitively difficult to make something people will accept as > pack-05f611b3b8198b262acdf678584d365f8e879aec.pack other than the one from > the git repository. How about doing something like this, then? I haven't tried this with http-fetch but with this I think we can unconditionally assign p->sha1 in add_packed_git(). -- >8 -- Subject: [PATCH] Require packfiles to follow the naming convention. With this, pack files must be named "pack-[0-9a-f]{40}.pack", with corresponding .idx file, and the hexadecimal part must match the SHA1 checksum git-pack-objects computed when the pack was created originally (i.e. sum over sorted object names of all the contained objects). The core would ignore a valid packfile in $GIT_OBJECT_DIRECTORY/packs that "git-unpack-objects" would expand properly if it does not follow the naming convention. [jc: this breaks existing test t5300.] Signed-off-by: Junio C Hamano --- sha1_file.c | 38 +++++++++++++++++++++++++++++++++++++- 1 files changed, 37 insertions(+), 1 deletions(-) 4ff64a29401b28cfbd925cf86eed8b8e734ed24b diff --git a/sha1_file.c b/sha1_file.c index 6011473..01ac925 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -319,18 +319,33 @@ struct packed_git *packed_git; static int check_packed_git_idx(const char *path, unsigned long *idx_size_, void **idx_map_) { + SHA_CTX ctx; + unsigned char sha1[20]; + unsigned char packname[20]; void *idx_map; unsigned int *index; unsigned long idx_size; int nr, i; - int fd = open(path, O_RDONLY); + int fd; struct stat st; + + fd = open(path, O_RDONLY); if (fd < 0) return -1; if (fstat(fd, &st)) { close(fd); return -1; } + + /* We require "...../pack-XXXX{40}XXXX.idx" now. + * 5-byte "pack-", 40-byte hex and 4-byte .idx. + */ + i = strlen(path); + if (i < 49 || strcmp(path + i - 4, ".idx") || + strncmp(path + i - 49, "pack-", 5) || + get_sha1_hex(path + i - 44, packname)) + return error("non index file %s ignored", path); + idx_size = st.st_size; idx_map = mmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); @@ -362,6 +377,27 @@ static int check_packed_git_idx(const ch if (idx_size != 4*256 + nr * 24 + 20 + 20) return error("wrong index file size"); + /* + * File checksum and index name. + */ + SHA1_Init(&ctx); + SHA1_Update(&ctx, idx_map, idx_size-20); + SHA1_Final(sha1, &ctx); + + if (memcmp(sha1, idx_map + idx_size - 20, 20)) + return error("index checksum mismatch"); + + SHA1_Init(&ctx); + for (i = 0; i < nr; i++) { + unsigned char *ent = (idx_map + 4*256) + i * 24 + 4; + SHA1_Update(&ctx, ent, 20); + } + SHA1_Final(sha1, &ctx); + + if (memcmp(sha1, packname, 20)) + return error("pack index name %s does not match contents %s", + path, sha1_to_hex(sha1)); + return 0; } -- 1.0.GIT