diff options
author | Junio C Hamano <gitster@pobox.com> | 2010-03-04 22:26:05 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2010-03-04 22:26:05 -0800 |
commit | 035aa7678b75bd6ec67f0b496603660fc685734f (patch) | |
tree | b88aecb4a9df15aabac07b6e270592a26b5b33b9 /sha1_file.c | |
parent | 6c4ee2244aea924b6d04b4753ca8c7709e8e5f90 (diff) | |
parent | 748af44c63ea6fec12690f1693f3dddd963e88d5 (diff) | |
download | git-035aa7678b75bd6ec67f0b496603660fc685734f.tar.gz |
Merge branch 'np/compress-loose-object-memsave' into maint
* np/compress-loose-object-memsave:
sha1_file: be paranoid when creating loose objects
sha1_file: don't malloc the whole compressed result when writing out objects
Diffstat (limited to 'sha1_file.c')
-rw-r--r-- | sha1_file.c | 33 |
1 files changed, 19 insertions, 14 deletions
diff --git a/sha1_file.c b/sha1_file.c index 657825e14e..c0214d7946 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -2281,9 +2281,10 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen, void *buf, unsigned long len, time_t mtime) { int fd, ret; - size_t size; - unsigned char *compressed; + unsigned char compressed[4096]; z_stream stream; + git_SHA_CTX c; + unsigned char parano_sha1[20]; char *filename; static char tmpfile[PATH_MAX]; @@ -2301,36 +2302,40 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen, /* Set it up */ memset(&stream, 0, sizeof(stream)); deflateInit(&stream, zlib_compression_level); - size = 8 + deflateBound(&stream, len+hdrlen); - compressed = xmalloc(size); - - /* Compress it */ stream.next_out = compressed; - stream.avail_out = size; + stream.avail_out = sizeof(compressed); + git_SHA1_Init(&c); /* First header.. */ stream.next_in = (unsigned char *)hdr; stream.avail_in = hdrlen; while (deflate(&stream, 0) == Z_OK) /* nothing */; + git_SHA1_Update(&c, hdr, hdrlen); /* Then the data itself.. */ stream.next_in = buf; stream.avail_in = len; - ret = deflate(&stream, Z_FINISH); + do { + unsigned char *in0 = stream.next_in; + ret = deflate(&stream, Z_FINISH); + git_SHA1_Update(&c, in0, stream.next_in - in0); + if (write_buffer(fd, compressed, stream.next_out - compressed) < 0) + die("unable to write sha1 file"); + stream.next_out = compressed; + stream.avail_out = sizeof(compressed); + } while (ret == Z_OK); + if (ret != Z_STREAM_END) die("unable to deflate new object %s (%d)", sha1_to_hex(sha1), ret); - ret = deflateEnd(&stream); if (ret != Z_OK) die("deflateEnd on object %s failed (%d)", sha1_to_hex(sha1), ret); + git_SHA1_Final(parano_sha1, &c); + if (hashcmp(sha1, parano_sha1) != 0) + die("confused by unstable object source data for %s", sha1_to_hex(sha1)); - size = stream.total_out; - - if (write_buffer(fd, compressed, size) < 0) - die("unable to write sha1 file"); close_sha1_file(fd); - free(compressed); if (mtime) { struct utimbuf utb; |