diff options
author | Junio C Hamano <gitster@pobox.com> | 2010-03-02 12:44:09 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2010-03-02 12:44:09 -0800 |
commit | 34c014d13e6b82fc3ae63d3657fcc6a6f367d760 (patch) | |
tree | a9c4c2746e5fe23b1a8ab92188a3021b5d034167 /sha1_file.c | |
parent | 7237f971819e4a65a77e4a551466937d7bfdc9e8 (diff) | |
parent | 748af44c63ea6fec12690f1693f3dddd963e88d5 (diff) | |
download | git-34c014d13e6b82fc3ae63d3657fcc6a6f367d760.tar.gz git-34c014d13e6b82fc3ae63d3657fcc6a6f367d760.tar.xz |
Merge branch 'np/compress-loose-object-memsave'
* 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 037515960..006321e00 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; |