From a5c9af6912f46fe613ad98e51d40a1d59e5464e8 Mon Sep 17 00:00:00 2001 From: Julian Ospald Date: Fri, 23 Jan 2026 14:26:18 +0800 Subject: [PATCH] Update libarchive-clib to 3.8.5 --- libarchive-clib/c/archive.h | 4 +- libarchive-clib/c/archive_cryptor.c | 6 +- libarchive-clib/c/archive_cryptor_private.h | 4 +- libarchive-clib/c/archive_disk_acl_darwin.c | 3 +- libarchive-clib/c/archive_entry.h | 2 +- .../c/archive_read_disk_entry_from_file.c | 15 ++-- libarchive-clib/c/archive_read_disk_posix.c | 35 ++++---- libarchive-clib/c/archive_read_disk_windows.c | 10 ++- .../c/archive_read_support_filter_lz4.c | 82 ++++++++++++++++--- .../c/archive_read_support_filter_uu.c | 8 +- .../c/archive_read_support_filter_zstd.c | 67 ++++++++++++--- .../c/archive_read_support_format_7zip.c | 8 +- .../c/archive_read_support_format_cab.c | 2 +- .../c/archive_read_support_format_cpio.c | 6 +- .../c/archive_read_support_format_lha.c | 4 +- .../c/archive_read_support_format_mtree.c | 14 ++-- .../c/archive_read_support_format_tar.c | 1 + .../c/archive_read_support_format_zip.c | 28 ++++--- libarchive-clib/c/archive_string.c | 24 +++++- libarchive-clib/c/archive_string.h | 4 + libarchive-clib/c/archive_util.c | 2 +- libarchive-clib/c/archive_version_details.c | 2 +- libarchive-clib/c/archive_windows.c | 5 +- libarchive-clib/c/archive_write.c | 2 +- libarchive-clib/c/archive_write_disk_posix.c | 26 +++--- libarchive-clib/c/archive_write_open_fd.c | 6 +- libarchive-clib/c/archive_write_open_file.c | 6 +- .../c/archive_write_open_filename.c | 2 + libarchive-clib/c/archive_write_open_memory.c | 6 +- .../c/archive_write_set_format_shar.c | 5 +- .../c/archive_write_set_format_ustar.c | 2 +- .../c/archive_write_set_format_xar.c | 12 +-- libarchive-clib/libarchive-clib.cabal | 2 +- 33 files changed, 272 insertions(+), 133 deletions(-) diff --git a/libarchive-clib/c/archive.h b/libarchive-clib/c/archive.h index 98d7674..a9d34be 100644 --- a/libarchive-clib/c/archive.h +++ b/libarchive-clib/c/archive.h @@ -34,7 +34,7 @@ * assert that ARCHIVE_VERSION_NUMBER >= 2012108. */ /* Note: Compiler will complain if this does not match archive_entry.h! */ -#define ARCHIVE_VERSION_NUMBER 3008002 +#define ARCHIVE_VERSION_NUMBER 3008005 #include #include /* for wchar_t */ @@ -177,7 +177,7 @@ __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_ONLY_STRING "3.8.2" +#define ARCHIVE_VERSION_ONLY_STRING "3.8.5" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); diff --git a/libarchive-clib/c/archive_cryptor.c b/libarchive-clib/c/archive_cryptor.c index 9f03f9c..b6a02fd 100644 --- a/libarchive-clib/c/archive_cryptor.c +++ b/libarchive-clib/c/archive_cryptor.c @@ -490,9 +490,9 @@ aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in, size_t in_len, uint8_t * const out, size_t *out_len) { uint8_t *const ebuf = ctx->encr_buf; - unsigned pos = ctx->encr_pos; - unsigned max = (unsigned)((in_len < *out_len)? in_len: *out_len); - unsigned i; + size_t pos = ctx->encr_pos; + size_t max = (in_len < *out_len)? in_len: *out_len; + size_t i; for (i = 0; i < max; ) { if (pos == AES_BLOCK_SIZE) { diff --git a/libarchive-clib/c/archive_cryptor_private.h b/libarchive-clib/c/archive_cryptor_private.h index 1dbc5c1..272f2f8 100644 --- a/libarchive-clib/c/archive_cryptor_private.h +++ b/libarchive-clib/c/archive_cryptor_private.h @@ -56,10 +56,10 @@ int __libarchive_cryptor_build_hack(void); typedef struct { CCCryptorRef ctx; uint8_t key[AES_MAX_KEY_SIZE]; - unsigned key_len; + size_t key_len; uint8_t nonce[AES_BLOCK_SIZE]; uint8_t encr_buf[AES_BLOCK_SIZE]; - unsigned encr_pos; + size_t encr_pos; } archive_crypto_ctx; #elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA diff --git a/libarchive-clib/c/archive_disk_acl_darwin.c b/libarchive-clib/c/archive_disk_acl_darwin.c index 12c3587..b4842d1 100644 --- a/libarchive-clib/c/archive_disk_acl_darwin.c +++ b/libarchive-clib/c/archive_disk_acl_darwin.c @@ -124,7 +124,6 @@ static void add_trivial_nfs4_acl(struct archive_entry *entry) { mode_t mode; - int i; const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA; const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA | ARCHIVE_ENTRY_ACL_APPEND_DATA; @@ -195,7 +194,7 @@ add_trivial_nfs4_acl(struct archive_entry *entry) } else if ((mode & 0010) || (mode & 0001)) tacl_entry[1].permset |= eperm; - for (i = 0; i < sizeof(tacl_entry) / sizeof(tacl_entry[0]); i++) { + for (size_t i = 0; i < sizeof(tacl_entry) / sizeof(tacl_entry[0]); i++) { if (tacl_entry[i].permset != 0) { archive_entry_acl_add_entry(entry, tacl_entry[i].type, tacl_entry[i].permset, diff --git a/libarchive-clib/c/archive_entry.h b/libarchive-clib/c/archive_entry.h index 344f33b..b434356 100644 --- a/libarchive-clib/c/archive_entry.h +++ b/libarchive-clib/c/archive_entry.h @@ -28,7 +28,7 @@ #define ARCHIVE_ENTRY_H_INCLUDED /* Note: Compiler will complain if this does not match archive.h! */ -#define ARCHIVE_VERSION_NUMBER 3008002 +#define ARCHIVE_VERSION_NUMBER 3008005 /* * Note: archive_entry.h is for use outside of libarchive; the diff --git a/libarchive-clib/c/archive_read_disk_entry_from_file.c b/libarchive-clib/c/archive_read_disk_entry_from_file.c index 42af403..6e6bae6 100644 --- a/libarchive-clib/c/archive_read_disk_entry_from_file.c +++ b/libarchive-clib/c/archive_read_disk_entry_from_file.c @@ -254,7 +254,7 @@ archive_read_disk_entry_from_file(struct archive *_a, if (S_ISLNK(st->st_mode)) { size_t linkbuffer_len = st->st_size; char *linkbuffer; - int lnklen; + ssize_t lnklen; linkbuffer = malloc(linkbuffer_len + 1); if (linkbuffer == NULL) { @@ -358,12 +358,10 @@ setup_mac_metadata(struct archive_read_disk *a, return (ARCHIVE_OK); archive_string_init(&tempfile); - if (__archive_get_tempdir(&tempfile) != ARCHIVE_OK) { - ret = ARCHIVE_WARN; - goto cleanup; - } - archive_strcat(&tempfile, "tar.md.XXXXXX"); - tempfd = mkstemp(tempfile.s); + archive_strcpy(&tempfile, name); + archive_string_dirname(&tempfile); + archive_strcat(&tempfile, "/tar.XXXXXXXX"); + tempfd = __archive_mkstemp(tempfile.s); if (tempfd < 0) { archive_set_error(&a->archive, errno, "Could not open extended attribute file"); @@ -894,7 +892,7 @@ setup_sparse_fiemap(struct archive_read_disk *a, for (iters = 0; ; ++iters) { int i, r; - r = ioctl(*fd, FS_IOC_FIEMAP, fm); + r = ioctl(*fd, FS_IOC_FIEMAP, fm); if (r < 0) { /* When something error happens, it is better we * should return ARCHIVE_OK because an earlier @@ -1081,4 +1079,3 @@ setup_sparse(struct archive_read_disk *a, #endif #endif /* !defined(_WIN32) || defined(__CYGWIN__) */ - diff --git a/libarchive-clib/c/archive_read_disk_posix.c b/libarchive-clib/c/archive_read_disk_posix.c index 54a8e66..94fa8fe 100644 --- a/libarchive-clib/c/archive_read_disk_posix.c +++ b/libarchive-clib/c/archive_read_disk_posix.c @@ -107,6 +107,8 @@ #define O_CLOEXEC 0 #endif +#define MAX_FILESYSTEM_ID 1000000 + #if defined(__hpux) && !defined(HAVE_DIRFD) #define dirfd(x) ((x)->__dd_fd) #define HAVE_DIRFD @@ -1412,8 +1414,12 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) * This is the new filesystem which we have to generate a new ID for. */ fid = t->max_filesystem_id++; + if (fid > MAX_FILESYSTEM_ID) { + archive_set_error(&a->archive, ENOMEM, "Too many filesystems"); + return (ARCHIVE_FATAL); + } if (t->max_filesystem_id > t->allocated_filesystem) { - size_t s; + int s; void *p; s = t->max_filesystem_id * 2; @@ -1693,8 +1699,6 @@ setup_current_filesystem(struct archive_read_disk *a) #endif t->current_filesystem->noatime = 0; - /* Set maximum filename length. */ - t->current_filesystem->name_max = svfs.f_namemax; return (ARCHIVE_OK); } @@ -2014,11 +2018,8 @@ tree_dup(int fd) } #endif /* F_DUPFD_CLOEXEC */ new_fd = dup(fd); - if (new_fd != -1) { - __archive_ensure_cloexec_flag(new_fd); - return (new_fd); - } - return (-1); + __archive_ensure_cloexec_flag(new_fd); + return (new_fd); } /* @@ -2140,16 +2141,11 @@ tree_reopen(struct tree *t, const char *path, int restore_time) * so try again for execute. The consequences of not opening this are * unhelpful and unnecessary errors later. */ - if (t->initial_dir_fd < 0) { + if (t->initial_dir_fd < 0) t->initial_dir_fd = open(".", o_flag | O_CLOEXEC); - if (t->initial_dir_fd < 0) - return NULL; - } #endif __archive_ensure_cloexec_flag(t->initial_dir_fd); t->working_dir_fd = tree_dup(t->initial_dir_fd); - if (t->working_dir_fd < 0) - return NULL; return (t); } @@ -2355,15 +2351,20 @@ static int tree_dir_next_posix(struct tree *t) { int r; +#if defined(HAVE_FDOPENDIR) + int fd; +#endif const char *name; size_t namelen; if (t->d == NULL) { #if defined(HAVE_FDOPENDIR) - int fd = tree_dup(t->working_dir_fd); - if (fd != -1) - t->d = fdopendir(fd); + if (t->working_dir_fd >= 0) { + fd = tree_dup(t->working_dir_fd); + if (fd != -1) + t->d = fdopendir(fd); + } #else /* HAVE_FDOPENDIR */ if (tree_enter_working_dir(t) == 0) { t->d = opendir("."); diff --git a/libarchive-clib/c/archive_read_disk_windows.c b/libarchive-clib/c/archive_read_disk_windows.c index 689a459..117ca50 100644 --- a/libarchive-clib/c/archive_read_disk_windows.c +++ b/libarchive-clib/c/archive_read_disk_windows.c @@ -53,6 +53,8 @@ /* To deal with absolute symlink issues */ #define START_ABSOLUTE_SYMLINK_REPARSE L"\\??\\" +#define MAX_FILESYSTEM_ID 1000000 + /*- * This is a new directory-walking system that addresses a number * of problems I've had with fts(3). In particular, it has no @@ -1449,8 +1451,12 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) * There is a new filesystem, we generate a new ID for. */ fid = t->max_filesystem_id++; + if (fid > MAX_FILESYSTEM_ID) { + archive_set_error(&a->archive, ENOMEM, "Too many filesystems"); + return (ARCHIVE_FATAL); + } if (t->max_filesystem_id > t->allocated_filesystem) { - size_t s; + int s; void *p; s = t->max_filesystem_id * 2; @@ -1462,7 +1468,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) return (ARCHIVE_FATAL); } t->filesystem_table = (struct filesystem *)p; - t->allocated_filesystem = (int)s; + t->allocated_filesystem = s; } t->current_filesystem_id = fid; t->current_filesystem = &(t->filesystem_table[fid]); diff --git a/libarchive-clib/c/archive_read_support_filter_lz4.c b/libarchive-clib/c/archive_read_support_filter_lz4.c index 760e6d9..144572e 100644 --- a/libarchive-clib/c/archive_read_support_filter_lz4.c +++ b/libarchive-clib/c/archive_read_support_filter_lz4.c @@ -49,9 +49,12 @@ #include "archive_xxhash.h" #define LZ4_MAGICNUMBER 0x184d2204 -#define LZ4_SKIPPABLED 0x184d2a50 #define LZ4_LEGACY 0x184c2102 +// Note: LZ4 and zstd share the same skippable frame format with the same magic numbers. +#define LZ4_SKIPPABLE_START 0x184D2A50 +#define LZ4_SKIPPABLE_MASK 0xFFFFFFF0 + #if defined(HAVE_LIBLZ4) struct private_data { enum { SELECT_STREAM, @@ -141,19 +144,67 @@ lz4_reader_bid(struct archive_read_filter_bidder *self, { const unsigned char *buffer; ssize_t avail; - int bits_checked; - uint32_t number; + int bits_checked = 0; + ssize_t min_lz4_archive_size = 11; + + // LZ4 skippable frames contain a 4 byte magic number followed by + // a 4 byte frame data size, then that number of bytes of data. Regular + // frames contain a 4 byte magic number followed by a 2-14 byte frame + // header, some data, and a 3 byte end marker. + ssize_t min_lz4_frame_size = 8; + + ssize_t offset_in_buffer = 0; + ssize_t max_lookahead = 64 * 1024; - (void)self; /* UNUSED */ + (void)self; // UNUSED - /* Minimal lz4 archive is 11 bytes. */ - buffer = __archive_read_filter_ahead(filter, 11, &avail); + // Zstd and LZ4 skippable frame magic numbers are identical. To + // differentiate these two, we need to look for a non-skippable + // frame. + + // Minimal lz4 archive is 11 bytes. + buffer = __archive_read_filter_ahead(filter, min_lz4_archive_size, &avail); if (buffer == NULL) return (0); - /* First four bytes must be LZ4 magic numbers. */ - bits_checked = 0; - if ((number = archive_le32dec(buffer)) == LZ4_MAGICNUMBER) { + uint32_t magic_number = archive_le32dec(buffer); + + while ((magic_number & LZ4_SKIPPABLE_MASK) == LZ4_SKIPPABLE_START) { + + offset_in_buffer += 4; // Skip over the magic number + + // Ensure that we can read another 4 bytes. + if (offset_in_buffer + 4 > avail) { + buffer = __archive_read_filter_ahead(filter, offset_in_buffer + 4, &avail); + if (buffer == NULL) + return (0); + } + + uint32_t frame_data_size = archive_le32dec(buffer + offset_in_buffer); + + // Skip over the 4 frame data size bytes, plus the value stored there. + offset_in_buffer += 4 + frame_data_size; + + // There should be at least one more frame if this is LZ4 data. + if (offset_in_buffer + min_lz4_frame_size > avail) { // TODO: should this be >= ? + if (offset_in_buffer + min_lz4_frame_size > max_lookahead) + return (0); + + buffer = __archive_read_filter_ahead(filter, offset_in_buffer + min_lz4_frame_size, &avail); + if (buffer == NULL) + return (0); + } + + magic_number = archive_le32dec(buffer + offset_in_buffer); + } + + // We have skipped over any skippable frames. Either a regular LZ4 frame + // follows, or this isn't LZ4 data. + + bits_checked = offset_in_buffer; + buffer = buffer + offset_in_buffer; + + if (magic_number == LZ4_MAGICNUMBER) { unsigned char flag, BD; bits_checked += 32; @@ -175,11 +226,16 @@ lz4_reader_bid(struct archive_read_filter_bidder *self, if (BD & ~0x70) return (0); bits_checked += 8; - } else if (number == LZ4_LEGACY) { + + return (bits_checked); + } + + if (magic_number == LZ4_LEGACY) { bits_checked += 32; + return (bits_checked); } - - return (bits_checked); + + return (0); } #if !defined(HAVE_LIBLZ4) @@ -342,7 +398,7 @@ lz4_filter_read(struct archive_read_filter *self, const void **p) return lz4_filter_read_default_stream(self, p); else if (number == LZ4_LEGACY) return lz4_filter_read_legacy_stream(self, p); - else if ((number & ~0xF) == LZ4_SKIPPABLED) { + else if ((number & LZ4_SKIPPABLE_MASK) == LZ4_SKIPPABLE_START) { read_buf = __archive_read_filter_ahead( self->upstream, 4, NULL); if (read_buf == NULL) { diff --git a/libarchive-clib/c/archive_read_support_filter_uu.c b/libarchive-clib/c/archive_read_support_filter_uu.c index d722fe3..acb8feb 100644 --- a/libarchive-clib/c/archive_read_support_filter_uu.c +++ b/libarchive-clib/c/archive_read_support_filter_uu.c @@ -232,8 +232,8 @@ bid_get_line(struct archive_read_filter *filter, size_t nbytes_req = (*ravail+1023) & ~1023U; ssize_t tested; - /* Increase reading bytes if it is not enough to at least - * new two lines. */ + /* Increase reading bytes if it is not enough for at least + * two new lines. */ if (nbytes_req < (size_t)*ravail + 160) nbytes_req <<= 1; @@ -411,7 +411,7 @@ ensure_in_buff_size(struct archive_read_filter *self, /* * Calculate a new buffer size for in_buff. - * Increase its value until it has enough size we need. + * Increase its value until it is enough for our needs. */ newsize = uudecode->in_allocated; do { @@ -494,7 +494,7 @@ uudecode_filter_read(struct archive_read_filter *self, const void **buff) } /* * If there is remaining data which is saved by - * previous calling, use it first. + * a previous call, use it first. */ if (ensure_in_buff_size(self, uudecode, avail_in + uudecode->in_cnt) != ARCHIVE_OK) diff --git a/libarchive-clib/c/archive_read_support_filter_zstd.c b/libarchive-clib/c/archive_read_support_filter_zstd.c index 9a1dd71..da7c540 100644 --- a/libarchive-clib/c/archive_read_support_filter_zstd.c +++ b/libarchive-clib/c/archive_read_support_filter_zstd.c @@ -110,24 +110,67 @@ zstd_bidder_bid(struct archive_read_filter_bidder *self, { const unsigned char *buffer; ssize_t avail; - unsigned prefix; - /* Zstd frame magic values */ - unsigned zstd_magic = 0xFD2FB528U; - unsigned zstd_magic_skippable_start = 0x184D2A50U; - unsigned zstd_magic_skippable_mask = 0xFFFFFFF0; + // Zstandard skippable frames contain a 4 byte magic number followed by + // a 4 byte frame data size, then that number of bytes of data. Regular + // frames contain a 4 byte magic number followed by a 2-14 byte frame + // header, some data, and a 3 byte end marker. + ssize_t min_zstd_frame_size = 8; - (void) self; /* UNUSED */ + ssize_t offset_in_buffer = 0; + ssize_t max_lookahead = 64 * 1024; - buffer = __archive_read_filter_ahead(filter, 4, &avail); + // Zstd regular frame magic number. + uint32_t zstd_magic = 0xFD2FB528U; + + // Note: Zstd and LZ4 skippable frame magic numbers are identical. + // To differentiate these two, we need to look for a non-skippable + // frame. + uint32_t zstd_magic_skippable_start = 0x184D2A50; + uint32_t zstd_magic_skippable_mask = 0xFFFFFFF0; + + (void) self; // UNUSED + + buffer = __archive_read_filter_ahead(filter, min_zstd_frame_size, &avail); if (buffer == NULL) return (0); - prefix = archive_le32dec(buffer); - if (prefix == zstd_magic) - return (32); - if ((prefix & zstd_magic_skippable_mask) == zstd_magic_skippable_start) - return (32); + uint32_t magic_number = archive_le32dec(buffer); + + while ((magic_number & zstd_magic_skippable_mask) == zstd_magic_skippable_start) { + + offset_in_buffer += 4; // Skip over the magic number + + // Ensure that we can read another 4 bytes. + if (offset_in_buffer + 4 > avail) { + buffer = __archive_read_filter_ahead(filter, offset_in_buffer + 4, &avail); + if (buffer == NULL) + return (0); + } + + uint32_t frame_data_size = archive_le32dec(buffer + offset_in_buffer); + + // Skip over the 4 frame data size bytes, plus the value stored there. + offset_in_buffer += 4 + frame_data_size; + + // There should be at least one more frame if this is zstd data. + if (offset_in_buffer + min_zstd_frame_size > avail) { + if (offset_in_buffer + min_zstd_frame_size > max_lookahead) + return (0); + + buffer = __archive_read_filter_ahead(filter, offset_in_buffer + min_zstd_frame_size, &avail); + if (buffer == NULL) + return (0); + } + + magic_number = archive_le32dec(buffer + offset_in_buffer); + } + + // We have skipped over any skippable frames. Either a regular zstd frame + // follows, or this isn't zstd data. + + if (magic_number == zstd_magic) + return (offset_in_buffer + 4); return (0); } diff --git a/libarchive-clib/c/archive_read_support_format_7zip.c b/libarchive-clib/c/archive_read_support_format_7zip.c index 5954627..330d551 100644 --- a/libarchive-clib/c/archive_read_support_format_7zip.c +++ b/libarchive-clib/c/archive_read_support_format_7zip.c @@ -744,6 +744,7 @@ find_elf_data_sec(struct archive_read *a) const char *h; char big_endian, format_64; ssize_t bytes, min_addr = SFX_MIN_ADDR; + ssize_t request; uint64_t e_shoff, strtab_offset, strtab_size; uint16_t e_shentsize, e_shnum, e_shstrndx; uint16_t (*dec16)(const void *); @@ -796,7 +797,12 @@ find_elf_data_sec(struct archive_read *a) if (__archive_read_seek(a, e_shoff, SEEK_SET) < 0) { break; } - h = __archive_read_ahead(a, (size_t)e_shnum * (size_t)e_shentsize, NULL); + if (format_64) { + request = (size_t)e_shnum * (size_t)e_shentsize + 0x28; + } else { + request = (size_t)e_shnum * (size_t)e_shentsize + 0x18; + } + h = __archive_read_ahead(a, request, &bytes); if (h == NULL) { break; } diff --git a/libarchive-clib/c/archive_read_support_format_cab.c b/libarchive-clib/c/archive_read_support_format_cab.c index a96f7d3..63755ef 100644 --- a/libarchive-clib/c/archive_read_support_format_cab.c +++ b/libarchive-clib/c/archive_read_support_format_cab.c @@ -2813,7 +2813,7 @@ lzx_decode_blocks(struct lzx_stream *strm, int last) lzx_br_bits(&bre, mt_max_bits)); lzx_br_consume(&bre, mt_bitlen[c]); } - if (c > UCHAR_MAX) + if ((unsigned int)c > UCHAR_MAX) break; /* * 'c' is exactly literal code. diff --git a/libarchive-clib/c/archive_read_support_format_cpio.c b/libarchive-clib/c/archive_read_support_format_cpio.c index 74f3549..526096b 100644 --- a/libarchive-clib/c/archive_read_support_format_cpio.c +++ b/libarchive-clib/c/archive_read_support_format_cpio.c @@ -825,9 +825,9 @@ header_odc(struct archive_read *a, struct cpio *cpio, } /* - * NOTE: if a filename suffix is ".z", it is the file gziped by afio. - * it would be nice that we can show uncompressed file size and we can - * uncompressed file contents automatically, unfortunately we have nothing + * NOTE: if a filename suffix is ".z", it is a file gzipped by afio. + * it would be nice if we could show uncompressed file size and + * uncompress file contents automatically, unfortunately we have nothing * to get a uncompressed file size while reading each header. It means * we also cannot uncompress file contents under our framework. */ diff --git a/libarchive-clib/c/archive_read_support_format_lha.c b/libarchive-clib/c/archive_read_support_format_lha.c index 2a84ad9..cf6a147 100644 --- a/libarchive-clib/c/archive_read_support_format_lha.c +++ b/libarchive-clib/c/archive_read_support_format_lha.c @@ -689,7 +689,7 @@ archive_read_format_lha_read_header(struct archive_read *a, * a pathname and a symlink has '\' character, a directory * separator in DOS/Windows. So we should convert it to '/'. */ - if (p[H_LEVEL_OFFSET] == 0) + if (lha->level == 0) lha_replace_path_separator(lha, entry); archive_entry_set_mode(entry, lha->mode); @@ -2374,7 +2374,7 @@ lzh_decode_blocks(struct lzh_stream *strm, int last) lzh_br_consume(&bre, lt_bitlen[c]); } blocks_avail--; - if (c > UCHAR_MAX) + if ((unsigned int)c > UCHAR_MAX) /* Current block is a match data. */ break; /* diff --git a/libarchive-clib/c/archive_read_support_format_mtree.c b/libarchive-clib/c/archive_read_support_format_mtree.c index ded13be..10c07b0 100644 --- a/libarchive-clib/c/archive_read_support_format_mtree.c +++ b/libarchive-clib/c/archive_read_support_format_mtree.c @@ -392,8 +392,8 @@ next_line(struct archive_read *a, if (len >= MAX_LINE_LEN) return (-1); - /* Increase reading bytes if it is not enough to at least - * new two lines. */ + /* Increase reading bytes if it is not enough for at least + * two new lines. */ if (nbytes_req < (size_t)*ravail + 160) nbytes_req <<= 1; @@ -568,8 +568,8 @@ bid_keyword_list(const char *p, ssize_t len, int unset, int last_is_path) --len; value = 1; } - /* A keyword should have a its value unless - * "/unset" operation. */ + /* A keyword should have a value unless this is + * an "/unset" operation. */ if (!unset && value == 0) return (-1); } @@ -752,7 +752,7 @@ detect_form(struct archive_read *a, int *is_form_d) } else if (form_D == 1) { if (!last_is_path && keywords > 0) /* This this is not `form D' - * and We cannot accept mixed + * and we cannot accept mixed * format. */ break; } @@ -805,7 +805,7 @@ detect_form(struct archive_read *a, int *is_form_d) * to read the entire mtree file into memory up front. * * The parsing is done in two steps. First, it is decided if a line - * changes the global defaults and if it is, processed accordingly. + * changes the global defaults and if it does, it is processed accordingly. * Otherwise, the options of the line are merged with the current * global options. */ @@ -1254,7 +1254,7 @@ parse_file(struct archive_read *a, struct archive_entry *entry, archive_entry_filetype(entry) == AE_IFDIR) { mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC); __archive_ensure_cloexec_flag(mtree->fd); - if (mtree->fd < 0 && ( + if (mtree->fd == -1 && ( #if defined(_WIN32) && !defined(__CYGWIN__) /* * On Windows, attempting to open a file with an diff --git a/libarchive-clib/c/archive_read_support_format_tar.c b/libarchive-clib/c/archive_read_support_format_tar.c index eeb2c72..98f7d69 100644 --- a/libarchive-clib/c/archive_read_support_format_tar.c +++ b/libarchive-clib/c/archive_read_support_format_tar.c @@ -2311,6 +2311,7 @@ pax_attribute_read_number(struct archive_read *a, size_t value_length, int64_t * archive_string_init(&as); r = read_bytes_to_string(a, &as, value_length, &unconsumed); if (tar_flush_unconsumed(a, &unconsumed) != ARCHIVE_OK) { + *result = 0; return (ARCHIVE_FATAL); } if (r < ARCHIVE_OK) { diff --git a/libarchive-clib/c/archive_read_support_format_zip.c b/libarchive-clib/c/archive_read_support_format_zip.c index 9abd557..0c86ce9 100644 --- a/libarchive-clib/c/archive_read_support_format_zip.c +++ b/libarchive-clib/c/archive_read_support_format_zip.c @@ -78,6 +78,12 @@ #include "archive_crc32.h" #endif +/* length of local file header, not including filename and extra */ +#define ZIP_LOCHDR_LEN 30U + +/* maximum length of Mac metadata in MiB */ +#define ZIP_MAX_METADATA 10U + struct zip_entry { struct archive_rb_node node; struct zip_entry *next; @@ -933,7 +939,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, zip->init_default_conversion = 1; } - if ((p = __archive_read_ahead(a, 30, NULL)) == NULL) { + if ((p = __archive_read_ahead(a, ZIP_LOCHDR_LEN, NULL)) == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP file header"); return (ARCHIVE_FATAL); @@ -969,7 +975,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, filename_length = archive_le16dec(p + 26); extra_length = archive_le16dec(p + 28); - __archive_read_consume(a, 30); + __archive_read_consume(a, ZIP_LOCHDR_LEN); /* Read the filename. */ if ((h = __archive_read_ahead(a, filename_length, NULL)) == NULL) { @@ -3637,7 +3643,7 @@ read_eocd(struct zip *zip, const char *p, int64_t current_offset) { uint16_t disk_num; uint32_t cd_size, cd_offset; - + disk_num = archive_le16dec(p + 4); cd_size = archive_le32dec(p + 12); cd_offset = archive_le32dec(p + 16); @@ -4097,7 +4103,7 @@ zip_get_local_file_header_size(struct archive_read *a, size_t extra) const char *p; ssize_t filename_length, extra_length; - if ((p = __archive_read_ahead(a, extra + 30, NULL)) == NULL) { + if ((p = __archive_read_ahead(a, extra + ZIP_LOCHDR_LEN, NULL)) == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP file header"); return (ARCHIVE_WARN); @@ -4111,7 +4117,7 @@ zip_get_local_file_header_size(struct archive_read *a, size_t extra) filename_length = archive_le16dec(p + 26); extra_length = archive_le16dec(p + 28); - return (30 + filename_length + extra_length); + return (ZIP_LOCHDR_LEN + filename_length + extra_length); } static int @@ -4148,16 +4154,16 @@ zip_read_mac_metadata(struct archive_read *a, struct archive_entry *entry, return (ARCHIVE_WARN); } - if (rsrc->uncompressed_size > (4 * 1024 * 1024)) { + if (rsrc->uncompressed_size > ZIP_MAX_METADATA * 1048576U) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Mac metadata is too large: %jd > 4M bytes", - (intmax_t)rsrc->uncompressed_size); + "Mac metadata is too large: %jd > %u MiB", + (intmax_t)rsrc->uncompressed_size, ZIP_MAX_METADATA); return (ARCHIVE_WARN); } - if (rsrc->compressed_size > (4 * 1024 * 1024)) { + if (rsrc->compressed_size > ZIP_MAX_METADATA * 1048576U) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Mac metadata is too large: %jd > 4M bytes", - (intmax_t)rsrc->compressed_size); + "Mac metadata is too large: %jd > %u MiB", + (intmax_t)rsrc->compressed_size, ZIP_MAX_METADATA); return (ARCHIVE_WARN); } diff --git a/libarchive-clib/c/archive_string.c b/libarchive-clib/c/archive_string.c index 3bb9783..a776dc8 100644 --- a/libarchive-clib/c/archive_string.c +++ b/libarchive-clib/c/archive_string.c @@ -2054,6 +2054,26 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n, return (r); } +struct archive_string * +archive_string_dirname(struct archive_string *as) +{ + /* strip trailing separators */ + while (as->length > 1 && as->s[as->length - 1] == '/') + as->length--; + /* strip final component */ + while (as->length > 0 && as->s[as->length - 1] != '/') + as->length--; + /* empty path -> cwd */ + if (as->length == 0) + return (archive_strcat(as, ".")); + /* strip separator(s) */ + while (as->length > 1 && as->s[as->length - 1] == '/') + as->length--; + /* terminate */ + as->s[as->length] = '\0'; + return (as); +} + #if HAVE_ICONV /* @@ -3553,7 +3573,7 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes, if (sc->to_cp == CP_C_LOCALE) { /* - * "C" locale special process. + * "C" locale special processing. */ u16 = _p; ll = 0; @@ -3670,7 +3690,7 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p, avail = as16->buffer_length - 2; if (sc->from_cp == CP_C_LOCALE) { /* - * "C" locale special process. + * "C" locale special processing. */ count = 0; while (count < length && *s) { diff --git a/libarchive-clib/c/archive_string.h b/libarchive-clib/c/archive_string.h index e898786..d5f5c03 100644 --- a/libarchive-clib/c/archive_string.h +++ b/libarchive-clib/c/archive_string.h @@ -192,6 +192,10 @@ void archive_string_vsprintf(struct archive_string *, const char *, void archive_string_sprintf(struct archive_string *, const char *, ...) __LA_PRINTF(2, 3); +/* Equivalent to dirname(3) */ +struct archive_string * +archive_string_dirname(struct archive_string *); + /* Translates from MBS to Unicode. */ /* Returns non-zero if conversion failed in any way. */ int archive_wstring_append_from_mbs(struct archive_wstring *dest, diff --git a/libarchive-clib/c/archive_util.c b/libarchive-clib/c/archive_util.c index d048bbc..0d1de1e 100644 --- a/libarchive-clib/c/archive_util.c +++ b/libarchive-clib/c/archive_util.c @@ -456,7 +456,7 @@ __archive_issetugid(void) return (-1); if (ruid != euid || ruid != suid) return (1); - if (getresgid(&ruid, &egid, &sgid) != 0) + if (getresgid(&rgid, &egid, &sgid) != 0) return (-1); if (rgid != egid || rgid != sgid) return (1); diff --git a/libarchive-clib/c/archive_version_details.c b/libarchive-clib/c/archive_version_details.c index 0cf92db..9063faa 100644 --- a/libarchive-clib/c/archive_version_details.c +++ b/libarchive-clib/c/archive_version_details.c @@ -333,7 +333,7 @@ archive_libbsdxml_version(void) const char * archive_libxml2_version(void) { -#if HAVE_LIBXML_XMLREADER_H && HAVE_LIBXML2 +#if HAVE_LIBXML_XMLVERSION_H && HAVE_LIBXML2 return LIBXML_DOTTED_VERSION; #else return NULL; diff --git a/libarchive-clib/c/archive_windows.c b/libarchive-clib/c/archive_windows.c index e55f995..3fbea6c 100644 --- a/libarchive-clib/c/archive_windows.c +++ b/libarchive-clib/c/archive_windows.c @@ -253,7 +253,7 @@ la_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode, createExParams.dwSize = sizeof(createExParams); createExParams.dwFileAttributes = dwFlagsAndAttributes & 0xFFFF; createExParams.dwFileFlags = dwFlagsAndAttributes & 0xFFF00000; - createExParams.dwSecurityQosFlags = dwFlagsAndAttributes & 0x000F00000; + createExParams.dwSecurityQosFlags = dwFlagsAndAttributes & 0x000F0000; createExParams.lpSecurityAttributes = lpSecurityAttributes; createExParams.hTemplateFile = hTemplateFile; handle = CreateFile2(wpath, dwDesiredAccess, dwShareMode, @@ -747,7 +747,8 @@ __la_seek_fstat(int fd, la_seek_stat_t *st) int ret; ret = __hstat((HANDLE)_get_osfhandle(fd), &u); - copy_seek_stat(st, &u); + if (ret >= 0) + copy_seek_stat(st, &u); return (ret); } diff --git a/libarchive-clib/c/archive_write.c b/libarchive-clib/c/archive_write.c index 9b9cb19..e1ce5d5 100644 --- a/libarchive-clib/c/archive_write.c +++ b/libarchive-clib/c/archive_write.c @@ -821,7 +821,7 @@ _archive_write_data(struct archive *_a, const void *buff, size_t s) { struct archive_write *a = (struct archive_write *)_a; const size_t max_write = INT_MAX; - int ret; + ssize_t ret; archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_DATA, "archive_write_data"); diff --git a/libarchive-clib/c/archive_write_disk_posix.c b/libarchive-clib/c/archive_write_disk_posix.c index 6fcf392..d1f043d 100644 --- a/libarchive-clib/c/archive_write_disk_posix.c +++ b/libarchive-clib/c/archive_write_disk_posix.c @@ -412,12 +412,14 @@ static ssize_t _archive_write_disk_data_block(struct archive *, const void *, static int la_mktemp(struct archive_write_disk *a) { + struct archive_string *tmp = &a->_tmpname_data; int oerrno, fd; mode_t mode; - archive_string_empty(&a->_tmpname_data); - archive_string_sprintf(&a->_tmpname_data, "%s.XXXXXX", a->name); - a->tmpname = a->_tmpname_data.s; + archive_strcpy(tmp, a->name); + archive_string_dirname(tmp); + archive_strcat(tmp, "/tar.XXXXXXXX"); + a->tmpname = tmp->s; fd = __archive_mkstemp(a->tmpname); if (fd == -1) @@ -2559,9 +2561,9 @@ _archive_write_disk_close(struct archive *_a) * for directories. For other file types * we need to verify via fstat() or lstat() */ - if (fd < 0 || p->filetype != AE_IFDIR) { + if (fd == -1 || p->filetype != AE_IFDIR) { #if HAVE_FSTAT - if (fd >= 0 && ( + if (fd > 0 && ( fstat(fd, &st) != 0 || la_verify_filetype(st.st_mode, p->filetype) == 0)) { @@ -4287,8 +4289,10 @@ create_tempdatafork(struct archive_write_disk *a, const char *pathname) int tmpfd; archive_string_init(&tmpdatafork); - archive_strcpy(&tmpdatafork, "tar.md.XXXXXX"); - tmpfd = mkstemp(tmpdatafork.s); + archive_strcpy(&tmpdatafork, pathname); + archive_string_dirname(&tmpdatafork); + archive_strcat(&tmpdatafork, "/tar.XXXXXXXX"); + tmpfd = __archive_mkstemp(tmpdatafork.s); if (tmpfd < 0) { archive_set_error(&a->archive, errno, "Failed to mkstemp"); @@ -4367,8 +4371,10 @@ set_mac_metadata(struct archive_write_disk *a, const char *pathname, * silly dance of writing the data to disk just so that * copyfile() can read it back in again. */ archive_string_init(&tmp); - archive_strcpy(&tmp, "tar.mmd.XXXXXX"); - fd = mkstemp(tmp.s); + archive_strcpy(&tmp, pathname); + archive_string_dirname(&tmp); + archive_strcat(&tmp, "/tar.XXXXXXXX"); + fd = __archive_mkstemp(tmp.s); if (fd < 0) { archive_set_error(&a->archive, errno, @@ -4441,7 +4447,7 @@ fixup_appledouble(struct archive_write_disk *a, const char *pathname) */ fd = open(pathname, O_RDONLY | O_BINARY | O_CLOEXEC); __archive_ensure_cloexec_flag(fd); - if (fd < 0) { + if (fd == -1) { archive_set_error(&a->archive, errno, "Failed to open a restoring file"); ret = ARCHIVE_WARN; diff --git a/libarchive-clib/c/archive_write_open_fd.c b/libarchive-clib/c/archive_write_open_fd.c index ba034ed..a795552 100644 --- a/libarchive-clib/c/archive_write_open_fd.c +++ b/libarchive-clib/c/archive_write_open_fd.c @@ -135,11 +135,7 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length static int file_free(struct archive *a, void *client_data) { - struct write_fd_data *mine = (struct write_fd_data *)client_data; - (void)a; /* UNUSED */ - if (mine == NULL) - return (ARCHIVE_OK); - free(mine); + free(client_data); return (ARCHIVE_OK); } diff --git a/libarchive-clib/c/archive_write_open_file.c b/libarchive-clib/c/archive_write_open_file.c index 0b310f3..6271b36 100644 --- a/libarchive-clib/c/archive_write_open_file.c +++ b/libarchive-clib/c/archive_write_open_file.c @@ -96,11 +96,7 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length static int file_free(struct archive *a, void *client_data) { - struct write_FILE_data *mine = client_data; - (void)a; /* UNUSED */ - if (mine == NULL) - return (ARCHIVE_OK); - free(mine); + free(client_data); return (ARCHIVE_OK); } diff --git a/libarchive-clib/c/archive_write_open_filename.c b/libarchive-clib/c/archive_write_open_filename.c index 7d0f9bd..430de21 100644 --- a/libarchive-clib/c/archive_write_open_filename.c +++ b/libarchive-clib/c/archive_write_open_filename.c @@ -191,6 +191,8 @@ file_open(struct archive *a, void *client_data) archive_set_error(a, errno, "Couldn't stat '%s'", mbs); else archive_set_error(a, errno, "Couldn't stat '%ls'", wcs); + close(mine->fd); + mine->fd = -1; return (ARCHIVE_FATAL); } diff --git a/libarchive-clib/c/archive_write_open_memory.c b/libarchive-clib/c/archive_write_open_memory.c index e316504..3b929ac 100644 --- a/libarchive-clib/c/archive_write_open_memory.c +++ b/libarchive-clib/c/archive_write_open_memory.c @@ -104,11 +104,7 @@ memory_write(struct archive *a, void *client_data, const void *buff, size_t leng static int memory_write_free(struct archive *a, void *client_data) { - struct write_memory_data *mine; (void)a; /* UNUSED */ - mine = client_data; - if (mine == NULL) - return (ARCHIVE_OK); - free(mine); + free(client_data); return (ARCHIVE_OK); } diff --git a/libarchive-clib/c/archive_write_set_format_shar.c b/libarchive-clib/c/archive_write_set_format_shar.c index be9f78c..f6f28de 100644 --- a/libarchive-clib/c/archive_write_set_format_shar.c +++ b/libarchive-clib/c/archive_write_set_format_shar.c @@ -144,7 +144,9 @@ archive_write_set_format_shar_dump(struct archive *_a) struct archive_write *a = (struct archive_write *)_a; struct shar *shar; - archive_write_set_format_shar(&a->archive); + int ret = archive_write_set_format_shar(&a->archive); + if (ret != ARCHIVE_OK) + return ret; shar = (struct shar *)a->format_data; shar->dump = 1; a->format_write_data = archive_write_shar_data_uuencode; @@ -240,6 +242,7 @@ archive_write_shar_header(struct archive_write *a, struct archive_entry *entry) shar_quote(&shar->work, p, 1); archive_strcat(&shar->work, " > /dev/null 2>&1\n"); + free(shar->last_dir); shar->last_dir = p; } } else { diff --git a/libarchive-clib/c/archive_write_set_format_ustar.c b/libarchive-clib/c/archive_write_set_format_ustar.c index 09b71fe..4084eb4 100644 --- a/libarchive-clib/c/archive_write_set_format_ustar.c +++ b/libarchive-clib/c/archive_write_set_format_ustar.c @@ -539,7 +539,7 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512], ret = ARCHIVE_WARN; } if (copy_length > 0) { - if (strlen(p) > USTAR_gname_size) { + if (copy_length > USTAR_gname_size) { if (tartype != 'x') { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Group name too long"); diff --git a/libarchive-clib/c/archive_write_set_format_xar.c b/libarchive-clib/c/archive_write_set_format_xar.c index 9921f10..ec32190 100644 --- a/libarchive-clib/c/archive_write_set_format_xar.c +++ b/libarchive-clib/c/archive_write_set_format_xar.c @@ -1000,13 +1000,13 @@ xmlwrite_heap(struct archive_write *a, struct xml_writer *writer, const char *encname; int r; - r = xmlwrite_fstring(a, writer, "length", "%ju", heap->length); + r = xmlwrite_fstring(a, writer, "length", "%ju", (uintmax_t)heap->length); if (r < 0) return (ARCHIVE_FATAL); - r = xmlwrite_fstring(a, writer, "offset", "%ju", heap->temp_offset); + r = xmlwrite_fstring(a, writer, "offset", "%ju", (uintmax_t)heap->temp_offset); if (r < 0) return (ARCHIVE_FATAL); - r = xmlwrite_fstring(a, writer, "size", "%ju", heap->size); + r = xmlwrite_fstring(a, writer, "size", "%ju", (uintmax_t)heap->size); if (r < 0) return (ARCHIVE_FATAL); switch (heap->compression) { @@ -1356,7 +1356,7 @@ make_file_entry(struct archive_write *a, struct xml_writer *writer, * Make a inode entry, "". */ r = xmlwrite_fstring(a, writer, "inode", - "%jd", archive_entry_ino64(file->entry)); + "%jd", (intmax_t)archive_entry_ino64(file->entry)); if (r < 0) return (ARCHIVE_FATAL); if (archive_entry_dev(file->entry) != 0) { @@ -1378,7 +1378,7 @@ make_file_entry(struct archive_write *a, struct xml_writer *writer, * Make a user entry, "" and ". */ r = xmlwrite_fstring(a, writer, "uid", - "%d", archive_entry_uid(file->entry)); + "%jd", (intmax_t)archive_entry_uid(file->entry)); if (r < 0) return (ARCHIVE_FATAL); r = archive_entry_uname_l(file->entry, &p, &len, xar->sconv); @@ -1404,7 +1404,7 @@ make_file_entry(struct archive_write *a, struct xml_writer *writer, * Make a group entry, "" and ". */ r = xmlwrite_fstring(a, writer, "gid", - "%d", archive_entry_gid(file->entry)); + "%jd", (intmax_t)archive_entry_gid(file->entry)); if (r < 0) return (ARCHIVE_FATAL); r = archive_entry_gname_l(file->entry, &p, &len, xar->sconv); diff --git a/libarchive-clib/libarchive-clib.cabal b/libarchive-clib/libarchive-clib.cabal index 22ed941..ba00f44 100644 --- a/libarchive-clib/libarchive-clib.cabal +++ b/libarchive-clib/libarchive-clib.cabal @@ -1,6 +1,6 @@ cabal-version: 2.0 name: libarchive-clib -version: 3.8.2 +version: 3.8.5 license: OtherLicense license-file: LICENSE copyright: Copyright: (c) 2018-2020 Vanessa McHale