]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
RAR5 reader: Removed a memory leak in process_head_file 1125/head
authorGrzegorz Antoniak <ga@anadoxin.org>
Fri, 18 Jan 2019 06:24:17 +0000 (07:24 +0100)
committerGrzegorz Antoniak <ga@anadoxin.org>
Fri, 18 Jan 2019 06:30:53 +0000 (07:30 +0100)
The process_head_file function was using memset() to clear the
archive_entry structure. The problem was that this structure could
contain pointers to allocated blocks of memory, and removing those
pointers with memset() resulted in a memory leak.

Switching it in favor of archive_entry_clear() effectively clears the
structure, but also releases any allocated memory blocks. This removes
the memory leak.

The commit also changes the way a temporary archive_entry instance is
being created when skipping a base block after block merge; instead of
directly creating a new instance on the stack, a constructor function
archive_entry_new() is used to ensure the new archive_entry instance is
not in an inconsistent state. This is needed because the fix described
in the first half of this commit message depends on the archive_entry
instance being in a consistent state due to the call of the
archive_entry_clear() function.

libarchive/archive_read_support_format_rar5.c

index 6d824673e399e0012098954a994ff5cb414a53c2..b5f94e0c0a8379b3a71231d05a01f8deb28b63fb 100644 (file)
@@ -1301,7 +1301,7 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
     char name_utf8_buf[2048 * 4];
     const uint8_t* p;
 
-    memset(entry, 0, sizeof(struct archive_entry));
+    archive_entry_clear(entry);
 
     /* Do not reset file context if we're switching archives. */
     if(!rar->cstate.switch_multivolume) {
@@ -1795,8 +1795,14 @@ static int skip_base_block(struct archive_read* a) {
     int ret;
     struct rar5* rar = get_context(a);
 
-    struct archive_entry entry;
-    ret = process_base_block(a, &entry);
+    /* Create a new local archive_entry structure that will be operated on
+     * by header reader; operations on this archive_entry will be discarded.
+     */
+    struct archive_entry* entry = archive_entry_new();
+    ret = process_base_block(a, entry);
+
+    /* Discard operations on this archive_entry structure. */
+    archive_entry_free(entry);
 
     if(rar->generic.last_header_id == 2 && rar->generic.split_before > 0)
         return ARCHIVE_OK;