From: Junio C Hamano Date: Tue, 14 Apr 2015 18:49:09 +0000 (-0700) Subject: Merge branch 'sb/plug-streaming-leak' X-Git-Tag: v2.4.0-rc2~5 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/d2ae751b1cae0674e0a1f7fe4da0a341365cefbb?hp=-c Merge branch 'sb/plug-streaming-leak' * sb/plug-streaming-leak: streaming.c: fix a memleak --- d2ae751b1cae0674e0a1f7fe4da0a341365cefbb diff --combined streaming.c index 2ff036a0fa,c4d421d599..811fcc24d2 --- a/streaming.c +++ b/streaming.c @@@ -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); @@@ -149,13 -149,11 +149,13 @@@ 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 (;;) { @@@ -516,8 -517,6 +519,8 @@@ 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) { @@@ -540,7 -539,7 +543,7 @@@ 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;