svn commit: r340866 - in head/contrib/libarchive: cpio libarchive libarchive/test tar

Martin Matuska mm at FreeBSD.org
Sat Nov 24 01:25:48 UTC 2018


Author: mm
Date: Sat Nov 24 01:25:45 2018
New Revision: 340866
URL: https://svnweb.freebsd.org/changeset/base/340866

Log:
  MFV r340865:
  Sync libarchive with vendor.
  
  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
  
  MFC after:	1 week

Modified:
  head/contrib/libarchive/cpio/cpio.c
  head/contrib/libarchive/libarchive/archive_acl.c
  head/contrib/libarchive/libarchive/archive_read_support_format_rar5.c
  head/contrib/libarchive/libarchive/archive_write_set_format_iso9660.c
  head/contrib/libarchive/libarchive/archive_write_set_format_mtree.c
  head/contrib/libarchive/libarchive/archive_write_set_format_pax.c
  head/contrib/libarchive/libarchive/archive_write_set_format_xar.c
  head/contrib/libarchive/libarchive/test/test_fuzz.c
  head/contrib/libarchive/libarchive/test/test_read_format_rar5.c
  head/contrib/libarchive/libarchive/test/test_write_disk_perms.c
  head/contrib/libarchive/tar/write.c
Directory Properties:
  head/contrib/libarchive/   (props changed)

Modified: head/contrib/libarchive/cpio/cpio.c
==============================================================================
--- head/contrib/libarchive/cpio/cpio.c	Sat Nov 24 01:15:08 2018	(r340865)
+++ head/contrib/libarchive/cpio/cpio.c	Sat Nov 24 01:25:45 2018	(r340866)
@@ -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: head/contrib/libarchive/libarchive/archive_acl.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_acl.c	Sat Nov 24 01:15:08 2018	(r340865)
+++ head/contrib/libarchive/libarchive/archive_acl.c	Sat Nov 24 01:25:45 2018	(r340866)
@@ -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: head/contrib/libarchive/libarchive/archive_read_support_format_rar5.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_read_support_format_rar5.c	Sat Nov 24 01:15:08 2018	(r340865)
+++ head/contrib/libarchive/libarchive/archive_read_support_format_rar5.c	Sat Nov 24 01:25:45 2018	(r340866)
@@ -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: head/contrib/libarchive/libarchive/archive_write_set_format_iso9660.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_write_set_format_iso9660.c	Sat Nov 24 01:15:08 2018	(r340865)
+++ head/contrib/libarchive/libarchive/archive_write_set_format_iso9660.c	Sat Nov 24 01:25:45 2018	(r340866)
@@ -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: head/contrib/libarchive/libarchive/archive_write_set_format_mtree.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_write_set_format_mtree.c	Sat Nov 24 01:15:08 2018	(r340865)
+++ head/contrib/libarchive/libarchive/archive_write_set_format_mtree.c	Sat Nov 24 01:25:45 2018	(r340866)
@@ -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: head/contrib/libarchive/libarchive/archive_write_set_format_pax.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_write_set_format_pax.c	Sat Nov 24 01:15:08 2018	(r340865)
+++ head/contrib/libarchive/libarchive/archive_write_set_format_pax.c	Sat Nov 24 01:25:45 2018	(r340866)
@@ -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: head/contrib/libarchive/libarchive/archive_write_set_format_xar.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_write_set_format_xar.c	Sat Nov 24 01:15:08 2018	(r340865)
+++ head/contrib/libarchive/libarchive/archive_write_set_format_xar.c	Sat Nov 24 01:25:45 2018	(r340866)
@@ -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: head/contrib/libarchive/libarchive/test/test_fuzz.c
==============================================================================
--- head/contrib/libarchive/libarchive/test/test_fuzz.c	Sat Nov 24 01:15:08 2018	(r340865)
+++ head/contrib/libarchive/libarchive/test/test_fuzz.c	Sat Nov 24 01:25:45 2018	(r340866)
@@ -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: head/contrib/libarchive/libarchive/test/test_read_format_rar5.c
==============================================================================
--- head/contrib/libarchive/libarchive/test/test_read_format_rar5.c	Sat Nov 24 01:15:08 2018	(r340865)
+++ head/contrib/libarchive/libarchive/test/test_read_format_rar5.c	Sat Nov 24 01:25:45 2018	(r340866)
@@ -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: head/contrib/libarchive/libarchive/test/test_write_disk_perms.c
==============================================================================
--- head/contrib/libarchive/libarchive/test/test_write_disk_perms.c	Sat Nov 24 01:15:08 2018	(r340865)
+++ head/contrib/libarchive/libarchive/test/test_write_disk_perms.c	Sat Nov 24 01:25:45 2018	(r340866)
@@ -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: head/contrib/libarchive/tar/write.c
==============================================================================
--- head/contrib/libarchive/tar/write.c	Sat Nov 24 01:15:08 2018	(r340865)
+++ head/contrib/libarchive/tar/write.c	Sat Nov 24 01:25:45 2018	(r340866)
@@ -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);
 	}


More information about the svn-src-head mailing list