[PATCH] pack-check.c::verify_packfile(): don't run SHA-1 update on huge data
- From
Junio C Hamano <junkio@cox.net>
- Date
- Jan 4, 2007, 07:26 UTC
- Message-ID
- <7vr6ubmewg.fsf_-_@assigned-by-dhcp.cox.net>
- In-Reply-To
- <7v1wmbnw9x.fsf@assigned-by-dhcp.cox.net>
Running the SHA1_Update() on the whole packfile in a single call revealed an overflow problem we had in the SHA-1 implementation on POWER architecture some time ago, which was fixed with commit b47f509b (June 19, 2006). Other SHA-1 implementations may have a similar problem.
The sliding mmap() series already makes chunked calls to SHA1_Update(), so this patch itself will become moot when it graduates to "master", but in the meantime, run the hash function in smaller chunks to prevent possible future problems.
Signed-off-by: Junio C Hamano <junkio@cox.net> ---
* Chris, if you have a chance could you try this on the huge pack you had trouble with?
Also whose SHA-1 implementation are you using, if this indeed is the problem, I wonder?
pack-check.c | 20 +++++++++++++++----- 1 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/pack-check.c b/pack-check.c index c0caaee..8e123b7 100644 --- a/pack-check.c +++ b/pack-check.c @@ -1,16 +1,18 @@ #include "cache.h" #include "pack.h" +#define BATCH (1u<<20) + static int verify_packfile(struct packed_git *p) { unsigned long index_size = p->index_size; void *index_base = p->index_base; SHA_CTX ctx; unsigned char sha1[20]; - unsigned long pack_size = p->pack_size; - void *pack_base; struct pack_header *hdr; int nr_objects, err, i; + unsigned char *packdata; + unsigned long datasize; /* Header consistency check */ hdr = p->pack_base; @@ -25,11 +27,19 @@ static int verify_packfile(struct packed_git *p) "while idx size expects %d", nr_objects, num_packed_objects(p)); + /* Check integrity of pack data with its SHA-1 checksum */ SHA1_Init(&ctx); - pack_base = p->pack_base; - SHA1_Update(&ctx, pack_base, pack_size - 20); + packdata = p->pack_base; + datasize = p->pack_size - 20; + while (datasize) { + unsigned long batch = (datasize < BATCH) ? datasize : BATCH; + SHA1_Update(&ctx, packdata, batch); + datasize -= batch; + packdata += batch; + } SHA1_Final(sha1, &ctx); - if (hashcmp(sha1, (unsigned char *)pack_base + pack_size - 20)) + + if (hashcmp(sha1, (unsigned char *)(p->pack_base) + p->pack_size - 20)) return error("Packfile %s SHA1 mismatch with itself", p->pack_name); if (hashcmp(sha1, (unsigned char *)index_base + index_size - 40))