summaryrefslogtreecommitdiff
path: root/sha1_file.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2010-03-02 20:44:09 (GMT)
committerJunio C Hamano <gitster@pobox.com>2010-03-02 20:44:09 (GMT)
commit34c014d13e6b82fc3ae63d3657fcc6a6f367d760 (patch)
treea9c4c2746e5fe23b1a8ab92188a3021b5d034167 /sha1_file.c
parent7237f971819e4a65a77e4a551466937d7bfdc9e8 (diff)
parent748af44c63ea6fec12690f1693f3dddd963e88d5 (diff)
downloadgit-34c014d13e6b82fc3ae63d3657fcc6a6f367d760.zip
git-34c014d13e6b82fc3ae63d3657fcc6a6f367d760.tar.gz
git-34c014d13e6b82fc3ae63d3657fcc6a6f367d760.tar.bz2
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.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/sha1_file.c b/sha1_file.c
index 0375159..006321e 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;