From owner-svn-src-vendor@freebsd.org Sat Nov 24 01:15:12 2018 Return-Path: Delivered-To: svn-src-vendor@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 563A6113676B; Sat, 24 Nov 2018 01:15:12 +0000 (UTC) (envelope-from mm@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 0A01C7C6B3; Sat, 24 Nov 2018 01:15:12 +0000 (UTC) (envelope-from mm@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id C79FF268A1; Sat, 24 Nov 2018 01:15:11 +0000 (UTC) (envelope-from mm@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id wAO1FBGX098919; Sat, 24 Nov 2018 01:15:11 GMT (envelope-from mm@FreeBSD.org) Received: (from mm@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id wAO1F9K5098905; Sat, 24 Nov 2018 01:15:09 GMT (envelope-from mm@FreeBSD.org) Message-Id: <201811240115.wAO1F9K5098905@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mm set sender to mm@FreeBSD.org using -f From: Martin Matuska Date: Sat, 24 Nov 2018 01:15:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org Subject: svn commit: r340865 - in vendor/libarchive/dist: build/cmake cpio libarchive libarchive/test tar X-SVN-Group: vendor X-SVN-Commit-Author: mm X-SVN-Commit-Paths: in vendor/libarchive/dist: build/cmake cpio libarchive libarchive/test tar X-SVN-Commit-Revision: 340865 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 0A01C7C6B3 X-Spamd-Result: default: False [1.41 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_SPAM_LONG(0.46)[0.458,0]; NEURAL_SPAM_MEDIUM(0.76)[0.762,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US]; NEURAL_SPAM_SHORT(0.19)[0.194,0] X-Rspamd-Server: mx1.freebsd.org X-BeenThere: svn-src-vendor@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for the vendor work area tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 24 Nov 2018 01:15:12 -0000 Author: mm Date: Sat Nov 24 01:15:08 2018 New Revision: 340865 URL: https://svnweb.freebsd.org/changeset/base/340865 Log: Update vendor/libarchive/dist to git 0e416f2fe757ad6841dbb3386a17d88b5c9f5533 Relevant vendor changes: PR #1080: Spelling fixes PR #1084: RAR5 reader bugfixes PR #1091: fix use-after-free in delayed newc link processing PR #1092: Fix a few obvious resource leaks and strcpy() misuses Modified: vendor/libarchive/dist/build/cmake/config.h.in vendor/libarchive/dist/cpio/cpio.c vendor/libarchive/dist/libarchive/archive_acl.c vendor/libarchive/dist/libarchive/archive_read_support_format_rar5.c vendor/libarchive/dist/libarchive/archive_windows.c vendor/libarchive/dist/libarchive/archive_write_set_format_iso9660.c vendor/libarchive/dist/libarchive/archive_write_set_format_mtree.c vendor/libarchive/dist/libarchive/archive_write_set_format_pax.c vendor/libarchive/dist/libarchive/archive_write_set_format_xar.c vendor/libarchive/dist/libarchive/test/test_fuzz.c vendor/libarchive/dist/libarchive/test/test_read_format_rar5.c vendor/libarchive/dist/libarchive/test/test_write_disk_perms.c vendor/libarchive/dist/tar/write.c Modified: vendor/libarchive/dist/build/cmake/config.h.in ============================================================================== --- vendor/libarchive/dist/build/cmake/config.h.in Fri Nov 23 23:33:55 2018 (r340864) +++ vendor/libarchive/dist/build/cmake/config.h.in Sat Nov 24 01:15:08 2018 (r340865) @@ -680,6 +680,12 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the `bz2' library (-lbz2). */ #cmakedefine HAVE_LIBBZ2 1 +/* Define to 1 if you have the `b2' library (-lb2). */ +#cmakedefine HAVE_LIBB2 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_BLAKE2_H 1 + /* Define to 1 if you have the `charset' library (-lcharset). */ #cmakedefine HAVE_LIBCHARSET 1 Modified: vendor/libarchive/dist/cpio/cpio.c ============================================================================== --- vendor/libarchive/dist/cpio/cpio.c Fri Nov 23 23:33:55 2018 (r340864) +++ vendor/libarchive/dist/cpio/cpio.c Sat Nov 24 01:15:08 2018 (r340865) @@ -755,8 +755,10 @@ file_to_archive(struct cpio *cpio, const char *srcpath } if (cpio->option_rename) destpath = cpio_rename(destpath); - if (destpath == NULL) + if (destpath == NULL) { + archive_entry_free(entry); return (0); + } archive_entry_copy_pathname(entry, destpath); /* Modified: vendor/libarchive/dist/libarchive/archive_acl.c ============================================================================== --- vendor/libarchive/dist/libarchive/archive_acl.c Fri Nov 23 23:33:55 2018 (r340864) +++ vendor/libarchive/dist/libarchive/archive_acl.c Sat Nov 24 01:15:08 2018 (r340865) @@ -753,8 +753,10 @@ archive_acl_to_text_w(struct archive_acl *acl, ssize_t append_entry_w(&wp, prefix, ap->type, ap->tag, flags, wname, ap->permset, id); count++; - } else if (r < 0 && errno == ENOMEM) + } else if (r < 0 && errno == ENOMEM) { + free(ws); return (NULL); + } } /* Add terminating character */ @@ -975,8 +977,10 @@ archive_acl_to_text_l(struct archive_acl *acl, ssize_t prefix = NULL; r = archive_mstring_get_mbs_l( &ap->name, &name, &len, sc); - if (r != 0) + if (r != 0) { + free(s); return (NULL); + } if (count > 0) *p++ = separator; if (name == NULL || Modified: vendor/libarchive/dist/libarchive/archive_read_support_format_rar5.c ============================================================================== --- vendor/libarchive/dist/libarchive/archive_read_support_format_rar5.c Fri Nov 23 23:33:55 2018 (r340864) +++ vendor/libarchive/dist/libarchive/archive_read_support_format_rar5.c Sat Nov 24 01:15:08 2018 (r340865) @@ -88,6 +88,7 @@ struct file_header { uint8_t solid : 1; /* Is this a solid stream? */ uint8_t service : 1; /* Is this file a service data? */ + uint8_t eof : 1; /* Did we finish unpacking the file? */ /* Optional time fields. */ uint64_t e_mtime; @@ -176,7 +177,7 @@ struct comp_state { decompression. */ uint8_t* filtered_buf; /* Buffer used when applying filters. */ const uint8_t* block_buf; /* Buffer used when merging blocks. */ - size_t window_mask; /* Convinience field; window_size - 1. */ + size_t window_mask; /* Convenience field; window_size - 1. */ int64_t write_ptr; /* This amount of data has been unpacked in the window buffer. */ int64_t last_write_ptr; /* This amount of data has been stored in @@ -279,7 +280,7 @@ struct rar5 { int skip_mode; /* An offset to QuickOpen list. This is not supported by this unpacker, - * becuase we're focusing on streaming interface. QuickOpen is designed + * because we're focusing on streaming interface. QuickOpen is designed * to make things quicker for non-stream interfaces, so it's not our * use case. */ uint64_t qlist_offset; @@ -387,7 +388,7 @@ static void cdeque_pop_front_fast(struct cdeque* d, vo d->size--; } -/* Pops a front element of this cicrular deque object and returns its value. +/* Pops a front element of this circular deque object and returns its value. * This function performs bounds checking. */ static int cdeque_pop_front(struct cdeque* d, void** value) { if(!d || !value) @@ -400,17 +401,17 @@ static int cdeque_pop_front(struct cdeque* d, void** v return CDE_OK; } -/* Convinience function to cast filter_info** to void **. */ +/* Convenience function to cast filter_info** to void **. */ static void** cdeque_filter_p(struct filter_info** f) { return (void**) (size_t) f; } -/* Convinience function to cast filter_info* to void *. */ +/* Convenience function to cast filter_info* to void *. */ static void* cdeque_filter(struct filter_info* f) { return (void**) (size_t) f; } -/* Destroys this circular deque object. Dellocates the memory of the collection +/* Destroys this circular deque object. Deallocates the memory of the collection * buffer, but doesn't deallocate the memory of any pointer passed to this * deque as a value. */ static void cdeque_free(struct cdeque* d) { @@ -434,7 +435,7 @@ static inline struct rar5* get_context(struct archive_ // TODO: make sure these functions return a little endian number -/* Convinience functions used by filter implementations. */ +/* Convenience functions used by filter implementations. */ static uint32_t read_filter_data(struct rar5* rar, uint32_t offset) { uint32_t* dptr = (uint32_t*) &rar->cstate.window_buf[offset]; @@ -672,7 +673,7 @@ static void push_data(struct archive_read* a, struct r } } -/* Convinience function that submits the data to the user. It uses the +/* Convenience function that submits the data to the user. It uses the * unpack window buffer as a source location. */ static void push_window_data(struct archive_read* a, struct rar5* rar, int64_t idx_begin, int64_t idx_end) @@ -753,7 +754,7 @@ static void free_filters(struct rar5* rar) { /* Free any remaining filters. All filters should be naturally consumed by * the unpacking function, so remaining filters after unpacking normally - * mean that unpacking wasn't successfull. But still of course we shouldn't + * mean that unpacking wasn't successful. But still of course we shouldn't * leak memory in such case. */ /* cdeque_size() is a fast operation, so we can use it as a loop @@ -885,7 +886,7 @@ static int read_var(struct archive_read* a, uint64_t* * it will not have the possibility to advance the file * pointer, because it will not know how many bytes it needs * to consume. This is why we handle such situation here - * autmatically. */ + * automatically. */ if(ARCHIVE_OK != consume(a, 1 + i)) { return 0; } @@ -918,7 +919,7 @@ static int read_var_sized(struct archive_read* a, size size_t* pvalue_len) { uint64_t v; - uint64_t v_size; + uint64_t v_size = 0; const int ret = pvalue_len ? read_var(a, &v, &v_size) @@ -1218,7 +1219,7 @@ static int process_head_file_extra(struct archive_read ssize_t extra_data_size) { size_t extra_field_size; - size_t extra_field_id; + size_t extra_field_id = 0; int ret = ARCHIVE_FATAL; size_t var_size; @@ -1288,7 +1289,7 @@ static int process_head_file(struct archive_read* a, s size_t host_os = 0; size_t name_size = 0; uint64_t unpacked_size; - uint32_t mtime = 0, crc; + uint32_t mtime = 0, crc = 0; int c_method = 0, c_version = 0, is_dir; char name_utf8_buf[2048 * 4]; const uint8_t* p; @@ -1522,7 +1523,7 @@ static int process_head_main(struct archive_read* a, s enum MAIN_FLAGS { VOLUME = 0x0001, /* multi-volume archive */ - VOLUME_NUMBER = 0x0002, /* volume number, first vol doesnt have it */ + VOLUME_NUMBER = 0x0002, /* volume number, first vol doesn't have it */ SOLID = 0x0004, /* solid archive */ PROTECT = 0x0008, /* contains Recovery info */ LOCK = 0x0010, /* readonly flag, not used */ @@ -1647,7 +1648,7 @@ static int process_base_block(struct archive_read* a, { struct rar5* rar = get_context(a); uint32_t hdr_crc, computed_crc; - size_t raw_hdr_size, hdr_size_len, hdr_size; + size_t raw_hdr_size = 0, hdr_size_len, hdr_size; size_t header_id = 0; size_t header_flags = 0; const uint8_t* p; @@ -2211,7 +2212,7 @@ static int parse_block_header(struct archive_read* a, return ARCHIVE_OK; } -/* Convinience function used during filter processing. */ +/* Convenience function used during filter processing. */ static int parse_filter_data(struct rar5* rar, const uint8_t* p, uint32_t* filter_data) { @@ -2685,6 +2686,12 @@ static int merge_block(struct archive_read* a, ssize_t cur_block_size = rar5_min(rar->file.bytes_remaining, block_size - partial_offset); + if(cur_block_size == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Encountered block size == 0 during block merge"); + return ARCHIVE_FATAL; + } + if(!read_ahead(a, cur_block_size, &lp)) return ARCHIVE_EOF; @@ -3116,6 +3123,9 @@ static int do_unstore_file(struct archive_read* a, } size_t to_read = rar5_min(rar->file.bytes_remaining, 64 * 1024); + if(to_read == 0) { + return ARCHIVE_EOF; + } if(!read_ahead(a, to_read, &p)) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "I/O error " @@ -3186,7 +3196,7 @@ static int verify_checksums(struct archive_read* a) { * data and discarding the result). */ if(!rar->skip_mode) { - /* Always check checkums if we're not in skip mode */ + /* Always check checksums if we're not in skip mode */ verify_crc = 1; } else { /* We can override the logic above with a compile-time option @@ -3283,9 +3293,14 @@ static int rar5_read_data(struct archive_read *a, cons } ret = use_data(rar, buff, size, offset); - if(ret == ARCHIVE_OK) + if(ret == ARCHIVE_OK) { return ret; + } + if(rar->file.eof == 1) { + return ARCHIVE_EOF; + } + ret = do_unpack(a, rar, buff, size, offset); if(ret != ARCHIVE_OK) { return ret; @@ -3301,6 +3316,7 @@ static int rar5_read_data(struct archive_read *a, cons * value in the last `archive_read_data` call to signal an error * to the user. */ + rar->file.eof = 1; return verify_global_checksums(a); } Modified: vendor/libarchive/dist/libarchive/archive_windows.c ============================================================================== --- vendor/libarchive/dist/libarchive/archive_windows.c Fri Nov 23 23:33:55 2018 (r340864) +++ vendor/libarchive/dist/libarchive/archive_windows.c Sat Nov 24 01:15:08 2018 (r340865) @@ -445,7 +445,8 @@ fileTimeToUTC(const FILETIME *filetime, time_t *t, lon * Windows' stat() does not accept the path added "\\?\" especially "?" * character. * It means we cannot access the long name path longer than MAX_PATH. - * So I've implemented simular Windows' stat() to access the long name path. + * So I've implemented a function similar to Windows' stat() to access the + * long name path. * And I've added some feature. * 1. set st_ino by nFileIndexHigh and nFileIndexLow of * BY_HANDLE_FILE_INFORMATION. Modified: vendor/libarchive/dist/libarchive/archive_write_set_format_iso9660.c ============================================================================== --- vendor/libarchive/dist/libarchive/archive_write_set_format_iso9660.c Fri Nov 23 23:33:55 2018 (r340864) +++ vendor/libarchive/dist/libarchive/archive_write_set_format_iso9660.c Sat Nov 24 01:15:08 2018 (r340865) @@ -4899,10 +4899,10 @@ isofile_gen_utility_names(struct archive_write *a, str if (p[0] == '/') { if (p[1] == '/') /* Convert '//' --> '/' */ - strcpy(p, p+1); + memmove(p, p+1, strlen(p+1) + 1); else if (p[1] == '.' && p[2] == '/') /* Convert '/./' --> '/' */ - strcpy(p, p+2); + memmove(p, p+2, strlen(p+2) + 1); else if (p[1] == '.' && p[2] == '.' && p[3] == '/') { /* Convert 'dir/dir1/../dir2/' * --> 'dir/dir2/' Modified: vendor/libarchive/dist/libarchive/archive_write_set_format_mtree.c ============================================================================== --- vendor/libarchive/dist/libarchive/archive_write_set_format_mtree.c Fri Nov 23 23:33:55 2018 (r340864) +++ vendor/libarchive/dist/libarchive/archive_write_set_format_mtree.c Sat Nov 24 01:15:08 2018 (r340865) @@ -1810,10 +1810,10 @@ mtree_entry_setup_filenames(struct archive_write *a, s if (p[0] == '/') { if (p[1] == '/') /* Convert '//' --> '/' */ - strcpy(p, p+1); + memmove(p, p+1, strlen(p+1) + 1); else if (p[1] == '.' && p[2] == '/') /* Convert '/./' --> '/' */ - strcpy(p, p+2); + memmove(p, p+2, strlen(p+2) + 1); else if (p[1] == '.' && p[2] == '.' && p[3] == '/') { /* Convert 'dir/dir1/../dir2/' * --> 'dir/dir2/' Modified: vendor/libarchive/dist/libarchive/archive_write_set_format_pax.c ============================================================================== --- vendor/libarchive/dist/libarchive/archive_write_set_format_pax.c Fri Nov 23 23:33:55 2018 (r340864) +++ vendor/libarchive/dist/libarchive/archive_write_set_format_pax.c Sat Nov 24 01:15:08 2018 (r340865) @@ -522,11 +522,13 @@ add_pax_acl(struct archive_write *a, ARCHIVE_ERRNO_FILE_FORMAT, "%s %s %s", "Can't translate ", attr, " to UTF-8"); return(ARCHIVE_WARN); - } else if (*p != '\0') { + } + + if (*p != '\0') { add_pax_attr(&(pax->pax_header), attr, p); - free(p); } + free(p); return(ARCHIVE_OK); } Modified: vendor/libarchive/dist/libarchive/archive_write_set_format_xar.c ============================================================================== --- vendor/libarchive/dist/libarchive/archive_write_set_format_xar.c Fri Nov 23 23:33:55 2018 (r340864) +++ vendor/libarchive/dist/libarchive/archive_write_set_format_xar.c Sat Nov 24 01:15:08 2018 (r340865) @@ -2120,10 +2120,10 @@ file_gen_utility_names(struct archive_write *a, struct if (p[0] == '/') { if (p[1] == '/') /* Convert '//' --> '/' */ - strcpy(p, p+1); + memmove(p, p+1, strlen(p+1) + 1); else if (p[1] == '.' && p[2] == '/') /* Convert '/./' --> '/' */ - strcpy(p, p+2); + memmove(p, p+2, strlen(p+2) + 1); else if (p[1] == '.' && p[2] == '.' && p[3] == '/') { /* Convert 'dir/dir1/../dir2/' * --> 'dir/dir2/' @@ -3169,8 +3169,10 @@ save_xattrs(struct archive_write *a, struct file *file checksum_update(&(xar->a_sumwrk), xar->wbuff, size); if (write_to_temp(a, xar->wbuff, size) - != ARCHIVE_OK) + != ARCHIVE_OK) { + free(heap); return (ARCHIVE_FATAL); + } if (r == ARCHIVE_OK) { xar->stream.next_out = xar->wbuff; xar->stream.avail_out = sizeof(xar->wbuff); Modified: vendor/libarchive/dist/libarchive/test/test_fuzz.c ============================================================================== --- vendor/libarchive/dist/libarchive/test/test_fuzz.c Fri Nov 23 23:33:55 2018 (r340864) +++ vendor/libarchive/dist/libarchive/test/test_fuzz.c Sat Nov 24 01:15:08 2018 (r340865) @@ -433,7 +433,7 @@ DEFINE_TEST(test_fuzz_tar) {0, fileset9}, /* Exercise lzo decompressor. */ #endif #if HAVE_ZSTD_H && HAVE_LIBZSTD - {0, fileset10}, /* Excercise zstd decompressor. */ + {0, fileset10}, /* Exercise zstd decompressor. */ #endif {1, NULL} }; Modified: vendor/libarchive/dist/libarchive/test/test_read_format_rar5.c ============================================================================== --- vendor/libarchive/dist/libarchive/test/test_read_format_rar5.c Fri Nov 23 23:33:55 2018 (r340864) +++ vendor/libarchive/dist/libarchive/test/test_read_format_rar5.c Sat Nov 24 01:15:08 2018 (r340865) @@ -726,3 +726,44 @@ DEFINE_TEST(test_read_format_rar5_extract_win32) assertA(0 == extract_one(a, ae, 0x36A448FF)); EPILOGUE(); } + +DEFINE_TEST(test_read_format_rar5_block_by_block) +{ + /* This test uses strange buffer sizes intentionally. */ + + struct archive_entry *ae; + struct archive *a; + uint8_t buf[173]; + int bytes_read; + uint32_t computed_crc = 0; + + extract_reference_file("test_read_format_rar5_compressed.rar"); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filename(a, "test_read_format_rar5_compressed.rar", 130)); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.bin", archive_entry_pathname(ae)); + assertEqualInt(1200, archive_entry_size(ae)); + + /* File size is 1200 bytes, we're reading it using a buffer of 173 bytes. + * Libarchive is configured to use a buffer of 130 bytes. */ + + while(1) { + /* archive_read_data should return one of: + * a) 0, if there is no more data to be read, + * b) negative value, if there was an error, + * c) positive value, meaning how many bytes were read. + */ + + bytes_read = archive_read_data(a, buf, sizeof(buf)); + assertA(bytes_read >= 0); + if(bytes_read <= 0) + break; + + computed_crc = crc32(computed_crc, buf, bytes_read); + } + + assertEqualInt(computed_crc, 0x7CCA70CD); + EPILOGUE(); +} Modified: vendor/libarchive/dist/libarchive/test/test_write_disk_perms.c ============================================================================== --- vendor/libarchive/dist/libarchive/test/test_write_disk_perms.c Fri Nov 23 23:33:55 2018 (r340864) +++ vendor/libarchive/dist/libarchive/test/test_write_disk_perms.c Sat Nov 24 01:15:08 2018 (r340865) @@ -203,7 +203,7 @@ DEFINE_TEST(test_write_disk_perms) failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode); assertEqualInt(st.st_mode & 0777, 0744); - /* For dir, the owner should get left when not overwritting. */ + /* For dir, the owner should get left when not overwriting. */ assertMakeDir("dir_owner", 0744); if (getuid() == 0) { Modified: vendor/libarchive/dist/tar/write.c ============================================================================== --- vendor/libarchive/dist/tar/write.c Fri Nov 23 23:33:55 2018 (r340864) +++ vendor/libarchive/dist/tar/write.c Sat Nov 24 01:15:08 2018 (r340865) @@ -540,8 +540,7 @@ write_archive(struct archive *a, struct bsdtar *bsdtar lafe_warnc(archive_errno(disk), "%s", archive_error_string(disk)); bsdtar->return_value = 1; - archive_entry_free(entry); - continue; + goto next_entry; } /* @@ -557,15 +556,14 @@ write_archive(struct archive *a, struct bsdtar *bsdtar "%s", archive_error_string(disk)); if (r == ARCHIVE_FATAL) bsdtar->return_value = 1; - else - archive_read_close(disk); - archive_entry_free(entry); - continue; + archive_read_close(disk); + goto next_entry; } write_file(bsdtar, a, entry); - archive_entry_free(entry); archive_read_close(disk); +next_entry: + archive_entry_free(entry); entry = NULL; archive_entry_linkify(bsdtar->resolver, &entry, &sparse_entry); }