Merge branch 'sb/plug-streaming-leak'
authorJunio C Hamano <gitster@pobox.com>
Tue, 14 Apr 2015 18:49:09 +0000 (11:49 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 14 Apr 2015 18:49:09 +0000 (11:49 -0700)
* sb/plug-streaming-leak:
streaming.c: fix a memleak

1  2 
streaming.c
diff --combined streaming.c
index 2ff036a0fa6c8e7b013d061d16baf33045305950,c4d421d5990b03c9b510d4f8ae4e4a25c414a275..811fcc24d2a8ba56c233ae4e37b7acac29a4a0d8
@@@ -99,7 -99,7 +99,7 @@@ int close_istream(struct git_istream *s
        return r;
  }
  
 -ssize_t read_istream(struct git_istream *st, char *buf, size_t sz)
 +ssize_t read_istream(struct git_istream *st, void *buf, size_t sz)
  {
        return st->vtbl->read(st, buf, sz);
  }
@@@ -111,17 -111,17 +111,17 @@@ static enum input_source istream_source
        unsigned long size;
        int status;
  
 +      oi->typep = type;
        oi->sizep = &size;
 -      status = sha1_object_info_extended(sha1, oi);
 +      status = sha1_object_info_extended(sha1, oi, 0);
        if (status < 0)
                return stream_error;
 -      *type = status;
  
        switch (oi->whence) {
        case OI_LOOSE:
                return loose;
        case OI_PACKED:
 -              if (!oi->u.packed.is_delta && big_file_threshold <= size)
 +              if (!oi->u.packed.is_delta && big_file_threshold < size)
                        return pack_non_delta;
                /* fallthru */
        default:
@@@ -135,7 -135,7 +135,7 @@@ struct git_istream *open_istream(const 
                                 struct stream_filter *filter)
  {
        struct git_istream *st;
 -      struct object_info oi;
 +      struct object_info oi = {NULL};
        const unsigned char *real = lookup_replace_object(sha1);
        enum input_source src = istream_source(real, type, &oi);
  
                        return NULL;
                }
        }
 -      if (st && filter) {
 +      if (filter) {
                /* Add "&& !is_null_stream_filter(filter)" for performance */
                struct git_istream *nst = attach_stream_filter(st, filter);
 -              if (!nst)
 +              if (!nst) {
                        close_istream(st);
 +                      return NULL;
 +              }
                st = nst;
        }
  
@@@ -239,7 -237,7 +239,7 @@@ static read_method_decl(filtered
                if (!fs->input_finished) {
                        fs->i_end = read_istream(fs->upstream, fs->ibuf, FILTER_BUFFER);
                        if (fs->i_end < 0)
 -                              break;
 +                              return -1;
                        if (fs->i_end)
                                continue;
                }
@@@ -311,7 -309,7 +311,7 @@@ static read_method_decl(loose
                        st->z_state = z_done;
                        break;
                }
 -              if (status != Z_OK && status != Z_BUF_ERROR) {
 +              if (status != Z_OK && (status != Z_BUF_ERROR || total_read < sz)) {
                        git_inflate_end(&st->z);
                        st->z_state = z_error;
                        return -1;
@@@ -507,8 -505,11 +507,11 @@@ int stream_blob_to_fd(int fd, unsigned 
        int result = -1;
  
        st = open_istream(sha1, &type, &sz, filter);
-       if (!st)
+       if (!st) {
+               if (filter)
+                       free_stream_filter(filter);
                return result;
+       }
        if (type != OBJ_BLOB)
                goto close_and_exit;
        for (;;) {
                ssize_t wrote, holeto;
                ssize_t readlen = read_istream(st, buf, sizeof(buf));
  
 +              if (readlen < 0)
 +                      goto close_and_exit;
                if (!readlen)
                        break;
                if (can_seek && sizeof(buf) == readlen) {
                        goto close_and_exit;
        }
        if (kept && (lseek(fd, kept - 1, SEEK_CUR) == (off_t) -1 ||
 -                   write(fd, "", 1) != 1))
 +                   xwrite(fd, "", 1) != 1))
                goto close_and_exit;
        result = 0;