diff options
author | kientzle <kientzle@FreeBSD.org> | 2010-01-23 07:52:13 +0000 |
---|---|---|
committer | kientzle <kientzle@FreeBSD.org> | 2010-01-23 07:52:13 +0000 |
commit | 643a6f51c1d7cff9b6d3e3c3411c9344a8eab43e (patch) | |
tree | 0e002528c25b691cc569a8803787f4384c8b34a7 | |
parent | c88be204c754239a8a19025fa8bee6f2c54eb282 (diff) | |
download | FreeBSD-src-643a6f51c1d7cff9b6d3e3c3411c9344a8eab43e.zip FreeBSD-src-643a6f51c1d7cff9b6d3e3c3411c9344a8eab43e.tar.gz |
Fix a memory leak when a filter fails to initialize.
-rw-r--r-- | lib/libarchive/archive_read.c | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/lib/libarchive/archive_read.c b/lib/libarchive/archive_read.c index fd56dc6..91c5aa5 100644 --- a/lib/libarchive/archive_read.c +++ b/lib/libarchive/archive_read.c @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); static int build_stream(struct archive_read *); static int choose_format(struct archive_read *); +static int cleanup_filters(struct archive_read *); static struct archive_vtable *archive_read_vtable(void); static int _archive_read_close(struct archive *); static int _archive_read_finish(struct archive *); @@ -393,14 +394,13 @@ build_stream(struct archive_read *a) free(filter); return (r); } + a->filter = filter; /* Verify the filter by asking it for some data. */ __archive_read_filter_ahead(filter, 1, &avail); if (avail < 0) { - /* If the read failed, bail out now. */ - free(filter); - return (avail); + cleanup_filters(a); + return (ARCHIVE_FATAL); } - a->filter = filter; } } @@ -738,18 +738,10 @@ _archive_read_close(struct archive *_a) /* TODO: Clean up the formatters. */ - /* Clean up the filter pipeline. */ - while (a->filter != NULL) { - struct archive_read_filter *t = a->filter->upstream; - if (a->filter->close != NULL) { - r1 = (a->filter->close)(a->filter); - if (r1 < r) - r = r1; - } - free(a->filter->buffer); - free(a->filter); - a->filter = t; - } + /* Release the filter objects. */ + r1 = cleanup_filters(a); + if (r1 < r) + r = r1; /* Release the bidder objects. */ n = sizeof(a->bidders)/sizeof(a->bidders[0]); @@ -764,6 +756,25 @@ _archive_read_close(struct archive *_a) return (r); } +static int +cleanup_filters(struct archive_read *a) +{ + int r = ARCHIVE_OK; + /* Clean up the filter pipeline. */ + while (a->filter != NULL) { + struct archive_read_filter *t = a->filter->upstream; + if (a->filter->close != NULL) { + int r1 = (a->filter->close)(a->filter); + if (r1 < r) + r = r1; + } + free(a->filter->buffer); + free(a->filter); + a->filter = t; + } + return r; +} + /* * Release memory and other resources. */ |