summaryrefslogtreecommitdiff
path: root/builtin-pack-objects.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin-pack-objects.c')
-rw-r--r--builtin-pack-objects.c81
1 files changed, 52 insertions, 29 deletions
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 5e42387..149fa28 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -243,41 +243,61 @@ static int encode_header(enum object_type type, unsigned long size, unsigned cha
return n;
}
-static int revalidate_one(struct object_entry *entry,
- void *data, char *type, unsigned long size)
+static int check_inflate(unsigned char *data, unsigned long len, unsigned long expect)
{
- int err;
- if ((!data) ||
- ((entry->type != OBJ_DELTA) &&
- ( (size != entry->size) ||
- strcmp(type_names[entry->type], type))))
- err = -1;
- else
- err = check_sha1_signature(entry->sha1, data, size, type);
- free(data);
- return err;
+ z_stream stream;
+ unsigned char fakebuf[4096];
+ int st;
+
+ memset(&stream, 0, sizeof(stream));
+ stream.next_in = data;
+ stream.avail_in = len;
+ stream.next_out = fakebuf;
+ stream.avail_out = sizeof(fakebuf);
+ inflateInit(&stream);
+
+ while (1) {
+ st = inflate(&stream, Z_FINISH);
+ if (st == Z_STREAM_END || st == Z_OK) {
+ st = (stream.total_out == expect &&
+ stream.total_in == len) ? 0 : -1;
+ break;
+ }
+ if (st != Z_BUF_ERROR) {
+ st = -1;
+ break;
+ }
+ stream.next_out = fakebuf;
+ stream.avail_out = sizeof(fakebuf);
+ }
+ inflateEnd(&stream);
+ return st;
}
/*
* we are going to reuse the existing pack entry data. make
* sure it is not corrupt.
*/
-static int revalidate_pack_entry(struct object_entry *entry)
+static int revalidate_pack_entry(struct object_entry *entry, unsigned char *data, unsigned long len)
{
- void *data;
- char type[20];
- unsigned long size;
- struct pack_entry e;
+ enum object_type type;
+ unsigned long size, used;
if (pack_to_stdout)
return 0;
- e.p = entry->in_pack;
- e.offset = entry->in_pack_offset;
-
- /* the caller has already called use_packed_git() for us */
- data = unpack_entry_gently(&e, type, &size);
- return revalidate_one(entry, data, type, size);
+ /* the caller has already called use_packed_git() for us,
+ * so it is safe to access the pack data from mmapped location.
+ * make sure the entry inflates correctly.
+ */
+ used = unpack_object_header_gently(data, len, &type, &size);
+ if (!used)
+ return -1;
+ if (type == OBJ_DELTA)
+ used += 20; /* skip base object name */
+ data += used;
+ len -= used;
+ return check_inflate(data, len, entry->size);
}
static int revalidate_loose_object(struct object_entry *entry,
@@ -285,15 +305,18 @@ static int revalidate_loose_object(struct object_entry *entry,
unsigned long mapsize)
{
/* we already know this is a loose object with new type header. */
- void *data;
- char type[20];
- unsigned long size;
+ enum object_type type;
+ unsigned long size, used;
if (pack_to_stdout)
return 0;
- data = unpack_sha1_file(map, mapsize, type, &size);
- return revalidate_one(entry, data, type, size);
+ used = unpack_object_header_gently(map, mapsize, &type, &size);
+ if (!used)
+ return -1;
+ map += used;
+ mapsize -= used;
+ return check_inflate(map, mapsize, size);
}
static unsigned long write_object(struct sha1file *f,
@@ -377,7 +400,7 @@ static unsigned long write_object(struct sha1file *f,
datalen = find_packed_object_size(p, entry->in_pack_offset);
buf = (char *) p->pack_base + entry->in_pack_offset;
- if (revalidate_pack_entry(entry))
+ if (revalidate_pack_entry(entry, buf, datalen))
die("corrupt delta in pack %s", sha1_to_hex(entry->sha1));
sha1write(f, buf, datalen);
unuse_packed_git(p);