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
This commit is contained in:
Martin Matuska 2018-11-24 01:25:45 +00:00
commit 276f481d65
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=340866
11 changed files with 104 additions and 39 deletions

View File

@ -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);
/*

View File

@ -753,8 +753,10 @@ archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags,
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 *text_len, int flags,
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 ||

View File

@ -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, void** value) {
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** value) {
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_read* a) {
// 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 rar5* rar,
}
}
/* 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* pvalue,
* 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_t* pvalue,
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* a,
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, struct rar5* rar,
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, struct rar5* rar,
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, const uint8_t* p,
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 block_size,
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,8 +3293,13 @@ static int rar5_read_data(struct archive_read *a, const void **buff,
}
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) {
@ -3301,6 +3316,7 @@ static int rar5_read_data(struct archive_read *a, const void **buff,
* value in the last `archive_read_data` call to signal an error
* to the user. */
rar->file.eof = 1;
return verify_global_checksums(a);
}

View File

@ -4899,10 +4899,10 @@ isofile_gen_utility_names(struct archive_write *a, struct isofile *file)
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/'

View File

@ -1810,10 +1810,10 @@ mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file,
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/'

View File

@ -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);
}

View File

@ -2120,10 +2120,10 @@ file_gen_utility_names(struct archive_write *a, struct file *file)
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);

View File

@ -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}
};

View File

@ -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();
}

View File

@ -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) {

View File

@ -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);
}