As a recovery tool, unpack-objects should go on unpacking as many
objects as it can.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 builtin/unpack-objects.c | 42 +++++++++++++++++++++++++++++++++++++++++-
 t/t1050-large.sh         |  7 +++++++
 2 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 99cde45..8b5c67e 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -88,10 +88,50 @@ static void use(int bytes)
        consumed_bytes += bytes;
 }
 
+static void inflate_and_throw_away(unsigned long size)
+{
+       git_zstream stream;
+       char buf[8192];
+
+       memset(&stream, 0, sizeof(stream));
+       stream.next_out = (unsigned char *)buf;
+       stream.avail_out = sizeof(buf);
+       stream.next_in = fill(1);
+       stream.avail_in = len;
+       git_inflate_init(&stream);
+
+       for (;;) {
+               int ret = git_inflate(&stream, 0);
+               use(len - stream.avail_in);
+               if (stream.total_out == size && ret == Z_STREAM_END)
+                       break;
+               if (ret != Z_OK) {
+                       error("inflate returned %d", ret);
+                       if (!recover)
+                               exit(1);
+                       has_errors = 1;
+                       break;
+               }
+               stream.next_out = (unsigned char *)buf;
+               stream.avail_out = sizeof(buf);
+               stream.next_in = fill(1);
+               stream.avail_in = len;
+       }
+       git_inflate_end(&stream);
+}
+
 static void *get_data(unsigned long size)
 {
        git_zstream stream;
-       void *buf = xmalloc(size);
+       void *buf = xmalloc_gentle(size);
+
+       if (!buf) {
+               if (!recover)
+                       exit(1);
+               has_errors = 1;
+               inflate_and_throw_away(size);
+               return NULL;
+       }
 
        memset(&stream, 0, sizeof(stream));
 
diff --git a/t/t1050-large.sh b/t/t1050-large.sh
index 5642f84..eec2cca 100755
--- a/t/t1050-large.sh
+++ b/t/t1050-large.sh
@@ -169,4 +169,11 @@ test_expect_success 'fsck' '
        test "$n" -gt 1
 '
 
+test_expect_success 'unpack-objects' '
+       P=`ls .git/objects/pack/*.pack` &&
+       git unpack-objects -n -r <$P 2>err
+       test $? = 1 &&
+       grep "error: attempting to allocate .* over limit" err
+'
+
 test_done
-- 
2.1.0.rc0.78.gc0d8480

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to