Skip to content

Commit 8a2e163

Browse files
pcloudsgitster
authored andcommitted
index-pack: factor out unpack core from get_data_from_pack
This allows caller to consume large inflated object with a fixed amount of memory. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 9ec2dde commit 8a2e163

File tree

1 file changed

+24
-3
lines changed

1 file changed

+24
-3
lines changed

builtin/index-pack.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -504,23 +504,26 @@ static void *unpack_raw_entry(struct object_entry *obj,
504504
return data;
505505
}
506506

507-
static void *get_data_from_pack(struct object_entry *obj)
507+
static void *unpack_data(struct object_entry *obj,
508+
int (*consume)(const unsigned char *, unsigned long, void *),
509+
void *cb_data)
508510
{
509511
off_t from = obj[0].idx.offset + obj[0].hdr_size;
510512
unsigned long len = obj[1].idx.offset - from;
511513
unsigned char *data, *inbuf;
512514
git_zstream stream;
513515
int status;
514516

515-
data = xmalloc(obj->size);
517+
data = xmalloc(consume ? 64*1024 : obj->size);
516518
inbuf = xmalloc((len < 64*1024) ? len : 64*1024);
517519

518520
memset(&stream, 0, sizeof(stream));
519521
git_inflate_init(&stream);
520522
stream.next_out = data;
521-
stream.avail_out = obj->size;
523+
stream.avail_out = consume ? 64*1024 : obj->size;
522524

523525
do {
526+
unsigned char *last_out = stream.next_out;
524527
ssize_t n = (len < 64*1024) ? len : 64*1024;
525528
n = pread(pack_fd, inbuf, n, from);
526529
if (n < 0)
@@ -535,6 +538,15 @@ static void *get_data_from_pack(struct object_entry *obj)
535538
stream.next_in = inbuf;
536539
stream.avail_in = n;
537540
status = git_inflate(&stream, 0);
541+
if (consume) {
542+
if (consume(last_out, stream.next_out - last_out, cb_data)) {
543+
free(inbuf);
544+
free(data);
545+
return NULL;
546+
}
547+
stream.next_out = data;
548+
stream.avail_out = 64*1024;
549+
}
538550
} while (len && status == Z_OK && !stream.avail_in);
539551

540552
/* This has been inflated OK when first encountered, so... */
@@ -543,9 +555,18 @@ static void *get_data_from_pack(struct object_entry *obj)
543555

544556
git_inflate_end(&stream);
545557
free(inbuf);
558+
if (consume) {
559+
free(data);
560+
data = NULL;
561+
}
546562
return data;
547563
}
548564

565+
static void *get_data_from_pack(struct object_entry *obj)
566+
{
567+
return unpack_data(obj, NULL, NULL);
568+
}
569+
549570
static int compare_delta_bases(const union delta_base *base1,
550571
const union delta_base *base2,
551572
enum object_type type1,

0 commit comments

Comments
 (0)