Date: Tue, 31 Dec 2019 00:05:06 +0000 (UTC) From: Martin Matuska <mm@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r356212 - in head: contrib/libarchive contrib/libarchive/libarchive contrib/libarchive/libarchive/test contrib/libarchive/test_utils lib/libarchive/tests usr.bin/bsdcat usr.bin/cpio usr... Message-ID: <201912310005.xBV056p8074062@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mm Date: Tue Dec 31 00:05:06 2019 New Revision: 356212 URL: https://svnweb.freebsd.org/changeset/base/356212 Log: MFV r356163,r356197: Update libarchive to 3.4.1 Relevant vendor changes since last update: Issue #351: Refactor and implement private state logic for write filters PR #1252: RAR5 reader - verify window size for solid files (OSS-Fuzz 15482) PR #1255: zip writer - don't append unused NUL for directories PR #1260: Fix sparse file offset overflow on 32-bit systems PR #1263: UNICODE filename support for reading lha/lzh format Issue #1276: Bugfix and optimize archive_wstring_append_from_mbs() PR #1288: Add the "xattrhdr" option to pax write options PR #1295: 7z reader - fix reading archives with digests in PackInfo PR #1296: RAR5 reader - verify window size for multivolume archives PR #1297: ZIP reader - support LZMA_STREAM_END marker in 'lzma alone' files Issue #1298: Fix a heap-buffer-overflow in archive_string_append_from_wcs() OSS-Fuzz 19360, 19362: LHA reader - plug two memory leaks on error Fix possible off-by-one when dealing with readlink(2) MFC after: 2 weeks Added: head/contrib/libarchive/libarchive/test/test_pax_xattr_header.c - copied unchanged from r356163, vendor/libarchive/dist/libarchive/test/test_pax_xattr_header.c head/contrib/libarchive/libarchive/test/test_pax_xattr_header_all.tar.uu - copied unchanged from r356163, vendor/libarchive/dist/libarchive/test/test_pax_xattr_header_all.tar.uu head/contrib/libarchive/libarchive/test/test_pax_xattr_header_libarchive.tar.uu - copied unchanged from r356163, vendor/libarchive/dist/libarchive/test/test_pax_xattr_header_libarchive.tar.uu head/contrib/libarchive/libarchive/test/test_pax_xattr_header_schily.tar.uu - copied unchanged from r356163, vendor/libarchive/dist/libarchive/test/test_pax_xattr_header_schily.tar.uu head/contrib/libarchive/libarchive/test/test_read_format_7zip_packinfo_digests.7z.uu - copied unchanged from r356163, vendor/libarchive/dist/libarchive/test/test_read_format_7zip_packinfo_digests.7z.uu head/contrib/libarchive/libarchive/test/test_read_format_7zip_packinfo_digests.c - copied unchanged from r356163, vendor/libarchive/dist/libarchive/test/test_read_format_7zip_packinfo_digests.c head/contrib/libarchive/libarchive/test/test_read_format_lha_filename_utf16.c - copied unchanged from r356163, vendor/libarchive/dist/libarchive/test/test_read_format_lha_filename_utf16.c head/contrib/libarchive/libarchive/test/test_read_format_lha_filename_utf16.lzh.uu - copied unchanged from r356163, vendor/libarchive/dist/libarchive/test/test_read_format_lha_filename_utf16.lzh.uu head/contrib/libarchive/libarchive/test/test_read_format_rar5_different_solid_window_size.rar.uu - copied unchanged from r356163, vendor/libarchive/dist/libarchive/test/test_read_format_rar5_different_solid_window_size.rar.uu head/contrib/libarchive/libarchive/test/test_read_format_rar5_different_winsize_on_merge.rar.uu - copied unchanged from r356163, vendor/libarchive/dist/libarchive/test/test_read_format_rar5_different_winsize_on_merge.rar.uu Modified: head/contrib/libarchive/NEWS head/contrib/libarchive/libarchive/archive.h head/contrib/libarchive/libarchive/archive_entry.h head/contrib/libarchive/libarchive/archive_entry_acl.3 head/contrib/libarchive/libarchive/archive_hmac.c head/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c head/contrib/libarchive/libarchive/archive_read_disk_posix.c head/contrib/libarchive/libarchive/archive_read_support_format_7zip.c head/contrib/libarchive/libarchive/archive_read_support_format_lha.c head/contrib/libarchive/libarchive/archive_read_support_format_rar5.c head/contrib/libarchive/libarchive/archive_read_support_format_zip.c head/contrib/libarchive/libarchive/archive_string.c head/contrib/libarchive/libarchive/archive_write.c head/contrib/libarchive/libarchive/archive_write_add_filter_b64encode.c head/contrib/libarchive/libarchive/archive_write_add_filter_bzip2.c head/contrib/libarchive/libarchive/archive_write_add_filter_compress.c head/contrib/libarchive/libarchive/archive_write_add_filter_gzip.c head/contrib/libarchive/libarchive/archive_write_add_filter_lz4.c head/contrib/libarchive/libarchive/archive_write_add_filter_lzop.c head/contrib/libarchive/libarchive/archive_write_add_filter_program.c head/contrib/libarchive/libarchive/archive_write_add_filter_uuencode.c head/contrib/libarchive/libarchive/archive_write_add_filter_xz.c head/contrib/libarchive/libarchive/archive_write_add_filter_zstd.c head/contrib/libarchive/libarchive/archive_write_disk_posix.c head/contrib/libarchive/libarchive/archive_write_private.h head/contrib/libarchive/libarchive/archive_write_set_format_pax.c head/contrib/libarchive/libarchive/archive_write_set_format_zip.c head/contrib/libarchive/libarchive/archive_write_set_options.3 head/contrib/libarchive/libarchive/test/test_open_failure.c head/contrib/libarchive/libarchive/test/test_open_fd.c head/contrib/libarchive/libarchive/test/test_read_disk_directory_traversals.c head/contrib/libarchive/libarchive/test/test_read_format_rar5.c head/contrib/libarchive/libarchive/test/test_sparse_basic.c head/contrib/libarchive/test_utils/test_main.c head/lib/libarchive/tests/Makefile head/usr.bin/bsdcat/Makefile head/usr.bin/cpio/Makefile head/usr.bin/tar/Makefile Directory Properties: head/contrib/libarchive/ (props changed) Modified: head/contrib/libarchive/NEWS ============================================================================== --- head/contrib/libarchive/NEWS Mon Dec 30 23:20:46 2019 (r356211) +++ head/contrib/libarchive/NEWS Tue Dec 31 00:05:06 2019 (r356212) @@ -1,3 +1,9 @@ +Dec 30, 2019: libarchive 3.4.1 released + +Dec 11, 2019: New pax write option "xattrhdr" + +Nov 17, 2019: Unicode filename support for reading lha/lzh archives + Jun 11, 2019: libarchive 3.4.0 released May 18, 2019: Fixes for reading Android APK and JAR archives Modified: head/contrib/libarchive/libarchive/archive.h ============================================================================== --- head/contrib/libarchive/libarchive/archive.h Mon Dec 30 23:20:46 2019 (r356211) +++ head/contrib/libarchive/libarchive/archive.h Tue Dec 31 00:05:06 2019 (r356212) @@ -36,7 +36,7 @@ * assert that ARCHIVE_VERSION_NUMBER >= 2012108. */ /* Note: Compiler will complain if this does not match archive_entry.h! */ -#define ARCHIVE_VERSION_NUMBER 3004000 +#define ARCHIVE_VERSION_NUMBER 3004001 #include <sys/stat.h> #include <stddef.h> /* for wchar_t */ @@ -155,7 +155,7 @@ __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_ONLY_STRING "3.4.0" +#define ARCHIVE_VERSION_ONLY_STRING "3.4.1" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); Modified: head/contrib/libarchive/libarchive/archive_entry.h ============================================================================== --- head/contrib/libarchive/libarchive/archive_entry.h Mon Dec 30 23:20:46 2019 (r356211) +++ head/contrib/libarchive/libarchive/archive_entry.h Tue Dec 31 00:05:06 2019 (r356212) @@ -30,7 +30,7 @@ #define ARCHIVE_ENTRY_H_INCLUDED /* Note: Compiler will complain if this does not match archive.h! */ -#define ARCHIVE_VERSION_NUMBER 3004000 +#define ARCHIVE_VERSION_NUMBER 3004001 /* * Note: archive_entry.h is for use outside of libarchive; the @@ -524,9 +524,6 @@ __LA_DECL int archive_entry_acl_reset(struct archive_ __LA_DECL int archive_entry_acl_next(struct archive_entry *, int /* want_type */, int * /* type */, int * /* permset */, int * /* tag */, int * /* qual */, const char ** /* name */); -__LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type */, - int * /* type */, int * /* permset */, int * /* tag */, - int * /* qual */, const wchar_t ** /* name */); /* * Construct a text-format ACL. The flags argument is a bitmask that Modified: head/contrib/libarchive/libarchive/archive_entry_acl.3 ============================================================================== --- head/contrib/libarchive/libarchive/archive_entry_acl.3 Mon Dec 30 23:20:46 2019 (r356211) +++ head/contrib/libarchive/libarchive/archive_entry_acl.3 Tue Dec 31 00:05:06 2019 (r356212) @@ -34,7 +34,6 @@ .Nm archive_entry_acl_from_text , .Nm archive_entry_acl_from_text_w , .Nm archive_entry_acl_next , -.Nm archive_entry_acl_next_w , .Nm archive_entry_acl_reset , .Nm archive_entry_acl_to_text , .Nm archive_entry_acl_to_text_w , @@ -89,16 +88,6 @@ Streaming Archive Library (libarchive, -larchive) .Fa "const char **ret_name" .Fc .Ft int -.Fo archive_entry_acl_next_w -.Fa "struct archive_entry *a" -.Fa "int type" -.Fa "int *ret_type" -.Fa "int *ret_permset" -.Fa "int *ret_tag" -.Fa "int *ret_qual" -.Fa "const wchar_t **ret_name" -.Fc -.Ft int .Fn archive_entry_acl_reset "struct archive_entry *a" "int type" .Ft char * .Fo archive_entry_acl_to_text @@ -349,8 +338,6 @@ character are skipped. .Pp .Fn archive_entry_acl_next -and -.Fn archive_entry_acl_next_w return the next entry of the ACL list. This functions may only be called after .Fn archive_entry_acl_reset @@ -358,9 +345,7 @@ has indicated the presence of extended ACL entries. .Pp .Fn archive_entry_acl_reset prepare reading the list of ACL entries with -.Fn archive_entry_acl_next -or -.Fn archive_entry_acl_next_w . +.Fn archive_entry_acl_next . The function returns 0 if no non-extended ACLs are found. In this case, the access permissions should be obtained by .Xr archive_entry_mode 3 @@ -447,9 +432,7 @@ if all entries were successfully parsed and if one or more entries were invalid or non-parseable. .Pp .Fn archive_entry_acl_next -and -.Fn archive_entry_acl_next_w -return +returns .Dv ARCHIVE_OK on success, .Dv ARCHIVE_EOF Modified: head/contrib/libarchive/libarchive/archive_hmac.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_hmac.c Mon Dec 30 23:20:46 2019 (r356211) +++ head/contrib/libarchive/libarchive/archive_hmac.c Tue Dec 31 00:05:06 2019 (r356212) @@ -83,7 +83,9 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) static int __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) { +#ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wcast-qual" +#endif BCRYPT_ALG_HANDLE hAlg; BCRYPT_HASH_HANDLE hHash; DWORD hash_len; Modified: head/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c Mon Dec 30 23:20:46 2019 (r356211) +++ head/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c Tue Dec 31 00:05:06 2019 (r356212) @@ -249,11 +249,11 @@ archive_read_disk_entry_from_file(struct archive *_a, #if defined(HAVE_READLINK) || defined(HAVE_READLINKAT) if (S_ISLNK(st->st_mode)) { - size_t linkbuffer_len = st->st_size + 1; + size_t linkbuffer_len = st->st_size; char *linkbuffer; int lnklen; - linkbuffer = malloc(linkbuffer_len); + linkbuffer = malloc(linkbuffer_len + 1); if (linkbuffer == NULL) { archive_set_error(&a->archive, ENOMEM, "Couldn't read link data"); @@ -280,7 +280,7 @@ archive_read_disk_entry_from_file(struct archive *_a, free(linkbuffer); return (ARCHIVE_FAILED); } - linkbuffer[lnklen] = 0; + linkbuffer[lnklen] = '\0'; archive_entry_set_symlink(entry, linkbuffer); free(linkbuffer); } Modified: head/contrib/libarchive/libarchive/archive_read_disk_posix.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_read_disk_posix.c Mon Dec 30 23:20:46 2019 (r356211) +++ head/contrib/libarchive/libarchive/archive_read_disk_posix.c Tue Dec 31 00:05:06 2019 (r356212) @@ -694,6 +694,7 @@ _archive_read_data_block(struct archive *_a, const voi struct tree *t = a->tree; int r; ssize_t bytes; + int64_t sparse_bytes; size_t buffbytes; int empty_sparse_region = 0; @@ -792,9 +793,9 @@ _archive_read_data_block(struct archive *_a, const voi a->archive.state = ARCHIVE_STATE_FATAL; goto abort_read_data; } - bytes = t->current_sparse->offset - t->entry_total; - t->entry_remaining_bytes -= bytes; - t->entry_total += bytes; + sparse_bytes = t->current_sparse->offset - t->entry_total; + t->entry_remaining_bytes -= sparse_bytes; + t->entry_total += sparse_bytes; } /* @@ -2172,7 +2173,7 @@ tree_reopen(struct tree *t, const char *path, int rest #elif defined(O_SEARCH) /* SunOS */ const int o_flag = O_SEARCH; -#elif defined(O_EXEC) +#elif defined(__FreeBSD__) && defined(O_EXEC) /* FreeBSD */ const int o_flag = O_EXEC; #endif @@ -2198,7 +2199,8 @@ tree_reopen(struct tree *t, const char *path, int rest t->stack->flags = needsFirstVisit; t->maxOpenCount = t->openCount = 1; t->initial_dir_fd = open(".", O_RDONLY | O_CLOEXEC); -#if defined(O_PATH) || defined(O_SEARCH) || defined(O_EXEC) +#if defined(O_PATH) || defined(O_SEARCH) || \ + (defined(__FreeBSD__) && defined(O_EXEC)) /* * Most likely reason to fail opening "." is that it's not readable, * so try again for execute. The consequences of not opening this are Modified: head/contrib/libarchive/libarchive/archive_read_support_format_7zip.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_read_support_format_7zip.c Mon Dec 30 23:20:46 2019 (r356211) +++ head/contrib/libarchive/libarchive/archive_read_support_format_7zip.c Tue Dec 31 00:05:06 2019 (r356212) @@ -1787,7 +1787,7 @@ read_PackInfo(struct archive_read *a, struct _7z_pack_ return (0); } - if (*p != kSize) + if (*p != kCRC) return (-1); if (read_Digests(a, &(pi->digest), (size_t)pi->numPackStreams) < 0) Modified: head/contrib/libarchive/libarchive/archive_read_support_format_lha.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_read_support_format_lha.c Mon Dec 30 23:20:46 2019 (r356211) +++ head/contrib/libarchive/libarchive/archive_read_support_format_lha.c Tue Dec 31 00:05:06 2019 (r356212) @@ -175,7 +175,9 @@ struct lha { struct archive_string gname; uint16_t header_crc; uint16_t crc; - struct archive_string_conv *sconv; + /* dirname and filename could be in different codepages */ + struct archive_string_conv *sconv_dir; + struct archive_string_conv *sconv_fname; struct archive_string_conv *opt_sconv; struct archive_string dirname; @@ -232,8 +234,8 @@ static time_t lha_dos_time(const unsigned char *); static time_t lha_win_time(uint64_t, long *); static unsigned char lha_calcsum(unsigned char, const void *, int, size_t); -static int lha_parse_linkname(struct archive_string *, - struct archive_string *); +static int lha_parse_linkname(struct archive_wstring *, + struct archive_wstring *); static int lha_read_data_none(struct archive_read *, const void **, size_t *, int64_t *); static int lha_read_data_lzh(struct archive_read *, const void **, @@ -473,13 +475,15 @@ static int archive_read_format_lha_read_header(struct archive_read *a, struct archive_entry *entry) { - struct archive_string linkname; - struct archive_string pathname; + struct archive_wstring linkname; + struct archive_wstring pathname; struct lha *lha; const unsigned char *p; const char *signature; int err; - + struct archive_mstring conv_buffer; + const wchar_t *conv_buffer_p; + lha_crc16_init(); a->archive.archive_format = ARCHIVE_FORMAT_LHA; @@ -561,10 +565,13 @@ archive_read_format_lha_read_header(struct archive_rea archive_string_empty(&lha->dirname); archive_string_empty(&lha->filename); lha->dos_attr = 0; - if (lha->opt_sconv != NULL) - lha->sconv = lha->opt_sconv; - else - lha->sconv = NULL; + if (lha->opt_sconv != NULL) { + lha->sconv_dir = lha->opt_sconv; + lha->sconv_fname = lha->opt_sconv; + } else { + lha->sconv_dir = NULL; + lha->sconv_fname = NULL; + } switch (p[H_LEVEL_OFFSET]) { case 0: @@ -594,13 +601,55 @@ archive_read_format_lha_read_header(struct archive_rea return (truncated_error(a)); /* - * Make a pathname from a dirname and a filename. - */ - archive_string_concat(&lha->dirname, &lha->filename); + * Make a pathname from a dirname and a filename, after converting to Unicode. + * This is because codepages might differ between dirname and filename. + */ archive_string_init(&pathname); archive_string_init(&linkname); - archive_string_copy(&pathname, &lha->dirname); + archive_string_init(&conv_buffer.aes_mbs); + archive_string_init(&conv_buffer.aes_mbs_in_locale); + archive_string_init(&conv_buffer.aes_utf8); + archive_string_init(&conv_buffer.aes_wcs); + if (0 != archive_mstring_copy_mbs_len_l(&conv_buffer, lha->dirname.s, lha->dirname.length, lha->sconv_dir)) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname cannot be converted " + "from %s to Unicode.", + archive_string_conversion_charset_name(lha->sconv_dir)); + err = ARCHIVE_FATAL; + } else if (0 != archive_mstring_get_wcs(&a->archive, &conv_buffer, &conv_buffer_p)) + err = ARCHIVE_FATAL; + if (err == ARCHIVE_FATAL) { + archive_mstring_clean(&conv_buffer); + archive_wstring_free(&pathname); + archive_wstring_free(&linkname); + return (err); + } + archive_wstring_copy(&pathname, &conv_buffer.aes_wcs); + archive_string_empty(&conv_buffer.aes_mbs); + archive_string_empty(&conv_buffer.aes_mbs_in_locale); + archive_string_empty(&conv_buffer.aes_utf8); + archive_wstring_empty(&conv_buffer.aes_wcs); + if (0 != archive_mstring_copy_mbs_len_l(&conv_buffer, lha->filename.s, lha->filename.length, lha->sconv_fname)) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname cannot be converted " + "from %s to Unicode.", + archive_string_conversion_charset_name(lha->sconv_fname)); + err = ARCHIVE_FATAL; + } + else if (0 != archive_mstring_get_wcs(&a->archive, &conv_buffer, &conv_buffer_p)) + err = ARCHIVE_FATAL; + if (err == ARCHIVE_FATAL) { + archive_mstring_clean(&conv_buffer); + archive_wstring_free(&pathname); + archive_wstring_free(&linkname); + return (err); + } + archive_wstring_concat(&pathname, &conv_buffer.aes_wcs); + archive_mstring_clean(&conv_buffer); + if ((lha->mode & AE_IFMT) == AE_IFLNK) { /* * Extract the symlink-name if it's included in the pathname. @@ -610,8 +659,8 @@ archive_read_format_lha_read_header(struct archive_rea archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Unknown symlink-name"); - archive_string_free(&pathname); - archive_string_free(&linkname); + archive_wstring_free(&pathname); + archive_wstring_free(&linkname); return (ARCHIVE_FAILED); } } else { @@ -629,39 +678,13 @@ archive_read_format_lha_read_header(struct archive_rea /* * Set basic file parameters. */ - if (archive_entry_copy_pathname_l(entry, pathname.s, - pathname.length, lha->sconv) != 0) { - if (errno == ENOMEM) { - archive_set_error(&a->archive, ENOMEM, - "Can't allocate memory for Pathname"); - return (ARCHIVE_FATAL); - } - archive_set_error(&a->archive, - ARCHIVE_ERRNO_FILE_FORMAT, - "Pathname cannot be converted " - "from %s to current locale.", - archive_string_conversion_charset_name(lha->sconv)); - err = ARCHIVE_WARN; - } - archive_string_free(&pathname); + archive_entry_copy_pathname_w(entry, pathname.s); + archive_wstring_free(&pathname); if (archive_strlen(&linkname) > 0) { - if (archive_entry_copy_symlink_l(entry, linkname.s, - linkname.length, lha->sconv) != 0) { - if (errno == ENOMEM) { - archive_set_error(&a->archive, ENOMEM, - "Can't allocate memory for Linkname"); - return (ARCHIVE_FATAL); - } - archive_set_error(&a->archive, - ARCHIVE_ERRNO_FILE_FORMAT, - "Linkname cannot be converted " - "from %s to current locale.", - archive_string_conversion_charset_name(lha->sconv)); - err = ARCHIVE_WARN; - } + archive_entry_copy_symlink_w(entry, linkname.s); } else archive_entry_set_symlink(entry, NULL); - archive_string_free(&linkname); + archive_wstring_free(&linkname); /* * When a header level is 0, there is a possibility that * a pathname and a symlink has '\' character, a directory @@ -1208,6 +1231,26 @@ lha_read_file_extended_header(struct archive_read *a, archive_strncpy(&lha->filename, (const char *)extdheader, datasize); break; + case EXT_UTF16_FILENAME: + if (datasize == 0) { + /* maybe directory header */ + archive_string_empty(&lha->filename); + break; + } else if (datasize & 1) { + /* UTF-16 characters take always 2 or 4 bytes */ + goto invalid; + } + if (extdheader[0] == '\0') + goto invalid; + archive_string_empty(&lha->filename); + archive_array_append(&lha->filename, + (const char *)extdheader, datasize); + /* Setup a string conversion for a filename. */ + lha->sconv_fname = archive_string_conversion_from_charset( + &a->archive, "UTF-16LE", 1); + if (lha->sconv_fname == NULL) + return (ARCHIVE_FATAL); + break; case EXT_DIRECTORY: if (datasize == 0 || extdheader[0] == '\0') /* no directory name data. exit this case. */ @@ -1228,6 +1271,36 @@ lha_read_file_extended_header(struct archive_read *a, /* invalid directory data */ goto invalid; break; + case EXT_UTF16_DIRECTORY: + /* UTF-16 characters take always 2 or 4 bytes */ + if (datasize == 0 || (datasize & 1) || extdheader[0] == '\0') + /* no directory name data. exit this case. */ + goto invalid; + + archive_string_empty(&lha->dirname); + archive_array_append(&lha->dirname, + (const char *)extdheader, datasize); + lha->sconv_dir = archive_string_conversion_from_charset( + &a->archive, "UTF-16LE", 1); + if (lha->sconv_dir == NULL) + return (ARCHIVE_FATAL); + else { + /* + * Convert directory delimiter from 0xFF + * to '/' for local system. + */ + /* UTF-16LE character */ + uint16_t *utf16name = (uint16_t *)lha->dirname.s; + for (i = 0; i < lha->dirname.length / 2; i++) { + if (utf16name[i] == 0xFFFF) + utf16name[i] = L'/'; + } + /* Is last character directory separator? */ + if (utf16name[lha->dirname.length / 2 - 1] != L'/') + /* invalid directory data */ + goto invalid; + } + break; case EXT_DOS_ATTR: if (datasize == 2) lha->dos_attr = (unsigned char) @@ -1276,12 +1349,17 @@ lha_read_file_extended_header(struct archive_read *a, charset = cp.s; break; } - lha->sconv = + lha->sconv_dir = archive_string_conversion_from_charset( &(a->archive), charset, 1); + lha->sconv_fname = + archive_string_conversion_from_charset( + &(a->archive), charset, 1); archive_string_free(&cp); - if (lha->sconv == NULL) + if (lha->sconv_dir == NULL) return (ARCHIVE_FATAL); + if (lha->sconv_fname == NULL) + return (ARCHIVE_FATAL); } break; case EXT_UNIX_MODE: @@ -1336,8 +1414,7 @@ lha_read_file_extended_header(struct archive_read *a, } break; case EXT_TIMEZONE: /* Not supported */ - case EXT_UTF16_FILENAME: /* Not supported */ - case EXT_UTF16_DIRECTORY: /* Not supported */ + break; default: break; } @@ -1600,19 +1677,19 @@ archive_read_format_lha_cleanup(struct archive_read *a * then a archived pathname is 'xxx/bbb|aaa/bb/cc' */ static int -lha_parse_linkname(struct archive_string *linkname, - struct archive_string *pathname) +lha_parse_linkname(struct archive_wstring *linkname, + struct archive_wstring *pathname) { - char * linkptr; + wchar_t * linkptr; size_t symlen; - linkptr = strchr(pathname->s, '|'); + linkptr = wcschr(pathname->s, L'|'); if (linkptr != NULL) { - symlen = strlen(linkptr + 1); - archive_strncpy(linkname, linkptr+1, symlen); + symlen = wcslen(linkptr + 1); + archive_wstrncpy(linkname, linkptr+1, symlen); *linkptr = 0; - pathname->length = strlen(pathname->s); + pathname->length = wcslen(pathname->s); return (1); } Modified: head/contrib/libarchive/libarchive/archive_read_support_format_rar5.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_read_support_format_rar5.c Mon Dec 30 23:20:46 2019 (r356211) +++ head/contrib/libarchive/libarchive/archive_read_support_format_rar5.c Tue Dec 31 00:05:06 2019 (r356212) @@ -63,6 +63,7 @@ #if defined DEBUG #define DEBUG_CODE if(1) +#define LOG(...) do { printf("rar5: " __VA_ARGS__); puts(""); } while(0) #else #define DEBUG_CODE if(0) #endif @@ -115,6 +116,8 @@ struct file_header { /* Optional redir fields */ uint64_t redir_type; uint64_t redir_flags; + + ssize_t solid_window_size; /* Used in file format check. */ }; enum EXTRA { @@ -1177,7 +1180,7 @@ static int process_main_locator_extra_block(struct arc static int parse_file_extra_hash(struct archive_read* a, struct rar5* rar, ssize_t* extra_data_size) { - size_t hash_type; + size_t hash_type = 0; size_t value_len; if(!read_var_sized(a, &hash_type, &value_len)) @@ -1303,7 +1306,7 @@ static int parse_file_extra_htime(struct archive_read* struct archive_entry* e, struct rar5* rar, ssize_t* extra_data_size) { char unix_time = 0; - size_t flags; + size_t flags = 0; size_t value_len; enum HTIME_FLAGS { @@ -1665,7 +1668,18 @@ static int process_head_file(struct archive_read* a, s g_unpack_window_size << ((compression_info >> 10) & 15); rar->cstate.method = c_method; rar->cstate.version = c_version + 50; + rar->file.solid = (compression_info & SOLID) > 0; + /* Archives which declare solid files without initializing the window + * buffer first are invalid. */ + + if(rar->file.solid > 0 && rar->cstate.window_buf == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Declared solid file, but no window buffer " + "initialized yet."); + return ARCHIVE_FATAL; + } + /* Check if window_size is a sane value. Also, if the file is not * declared as a directory, disallow window_size == 0. */ if(window_size > (64 * 1024 * 1024) || @@ -1676,12 +1690,36 @@ static int process_head_file(struct archive_read* a, s return ARCHIVE_FATAL; } - /* Values up to 64M should fit into ssize_t on every - * architecture. */ - rar->cstate.window_size = (ssize_t) window_size; + if(rar->file.solid > 0) { + /* Re-check if current window size is the same as previous + * window size (for solid files only). */ + if(rar->file.solid_window_size > 0 && + rar->file.solid_window_size != (ssize_t) window_size) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Window size for this solid file doesn't match " + "the window size used in previous solid file. "); + return ARCHIVE_FATAL; + } + } + + /* If we're currently switching volumes, ignore the new definition of + * window_size. */ + if(rar->cstate.switch_multivolume == 0) { + /* Values up to 64M should fit into ssize_t on every + * architecture. */ + rar->cstate.window_size = (ssize_t) window_size; + } + + if(rar->file.solid > 0 && rar->file.solid_window_size == 0) { + /* Solid files have to have the same window_size across + whole archive. Remember the window_size parameter + for first solid file found. */ + rar->file.solid_window_size = rar->cstate.window_size; + } + init_window_mask(rar); - rar->file.solid = (compression_info & SOLID) > 0; rar->file.service = 0; if(!read_var_sized(a, &host_os, NULL)) Modified: head/contrib/libarchive/libarchive/archive_read_support_format_zip.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_read_support_format_zip.c Mon Dec 30 23:20:46 2019 (r356211) +++ head/contrib/libarchive/libarchive/archive_read_support_format_zip.c Tue Dec 31 00:05:06 2019 (r356212) @@ -1797,6 +1797,23 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, "lzma data error (error %d)", (int) lz_ret); return (ARCHIVE_FATAL); + /* This case is optional in lzma alone format. It can happen, + * but most of the files don't have it. (GitHub #1257) */ + case LZMA_STREAM_END: + lzma_end(&zip->zipx_lzma_stream); + zip->zipx_lzma_valid = 0; + if((int64_t) zip->zipx_lzma_stream.total_in != + zip->entry_bytes_remaining) + { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "lzma alone premature end of stream"); + return (ARCHIVE_FATAL); + } + + zip->end_of_entry = 1; + break; + case LZMA_OK: break; Modified: head/contrib/libarchive/libarchive/archive_string.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_string.c Mon Dec 30 23:20:46 2019 (r356211) +++ head/contrib/libarchive/libarchive/archive_string.c Tue Dec 31 00:05:06 2019 (r356212) @@ -75,6 +75,9 @@ __FBSDID("$FreeBSD$"); #define wmemmove(a,b,i) (wchar_t *)memmove((a), (b), (i) * sizeof(wchar_t)) #endif +#undef max +#define max(a, b) ((a)>(b)?(a):(b)) + struct archive_string_conv { struct archive_string_conv *next; char *from_charset; @@ -591,7 +594,7 @@ archive_wstring_append_from_mbs(struct archive_wstring * No single byte will be more than one wide character, * so this length estimate will always be big enough. */ - size_t wcs_length = len; + // size_t wcs_length = len; size_t mbs_length = len; const char *mbs = p; wchar_t *wcs; @@ -600,7 +603,11 @@ archive_wstring_append_from_mbs(struct archive_wstring memset(&shift_state, 0, sizeof(shift_state)); #endif - if (NULL == archive_wstring_ensure(dest, dest->length + wcs_length + 1)) + /* + * As we decided to have wcs_length == mbs_length == len + * we can use len here instead of wcs_length + */ + if (NULL == archive_wstring_ensure(dest, dest->length + len + 1)) return (-1); wcs = dest->s + dest->length; /* @@ -609,6 +616,12 @@ archive_wstring_append_from_mbs(struct archive_wstring * multi bytes. */ while (*mbs && mbs_length > 0) { + /* + * The buffer we allocated is always big enough. + * Keep this code path in a comment if we decide to choose + * smaller wcs_length in the future + */ +/* if (wcs_length == 0) { dest->length = wcs - dest->s; dest->s[dest->length] = L'\0'; @@ -618,24 +631,20 @@ archive_wstring_append_from_mbs(struct archive_wstring return (-1); wcs = dest->s + dest->length; } +*/ #if HAVE_MBRTOWC - r = mbrtowc(wcs, mbs, wcs_length, &shift_state); + r = mbrtowc(wcs, mbs, mbs_length, &shift_state); #else - r = mbtowc(wcs, mbs, wcs_length); + r = mbtowc(wcs, mbs, mbs_length); #endif if (r == (size_t)-1 || r == (size_t)-2) { ret_val = -1; - if (errno == EILSEQ) { - ++mbs; - --mbs_length; - continue; - } else - break; + break; } if (r == 0 || r > mbs_length) break; wcs++; - wcs_length--; + // wcs_length--; mbs += r; mbs_length -= r; } @@ -798,7 +807,8 @@ archive_string_append_from_wcs(struct archive_string * as->s[as->length] = '\0'; /* Re-allocate buffer for MBS. */ if (archive_string_ensure(as, - as->length + len * 2 + 1) == NULL) + as->length + max(len * 2, + (size_t)MB_CUR_MAX) + 1) == NULL) return (-1); p = as->s + as->length; end = as->s + as->buffer_length - MB_CUR_MAX -1; @@ -3440,7 +3450,8 @@ strncat_from_utf8_libarchive2(struct archive_string *a as->length = p - as->s; /* Re-allocate buffer for MBS. */ if (archive_string_ensure(as, - as->length + len * 2 + 1) == NULL) + as->length + max(len * 2, + (size_t)MB_CUR_MAX) + 1) == NULL) return (-1); p = as->s + as->length; end = as->s + as->buffer_length - MB_CUR_MAX -1; Modified: head/contrib/libarchive/libarchive/archive_write.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_write.c Mon Dec 30 23:20:46 2019 (r356211) +++ head/contrib/libarchive/libarchive/archive_write.c Tue Dec 31 00:05:06 2019 (r356212) @@ -212,6 +212,7 @@ __archive_write_allocate_filter(struct archive *_a) f = calloc(1, sizeof(*f)); f->archive = _a; + f->state = ARCHIVE_WRITE_FILTER_STATE_NEW; if (a->filter_first == NULL) a->filter_first = f; else @@ -228,6 +229,9 @@ __archive_write_filter(struct archive_write_filter *f, const void *buff, size_t length) { int r; + /* Never write to non-open filters */ + if (f->state != ARCHIVE_WRITE_FILTER_STATE_OPEN) + return(ARCHIVE_FATAL); if (length == 0) return(ARCHIVE_OK); if (f->write == NULL) @@ -240,29 +244,72 @@ __archive_write_filter(struct archive_write_filter *f, } /* - * Open a filter. + * Recursive function for opening the filter chain + * Last filter is opened first */ -int +static int __archive_write_open_filter(struct archive_write_filter *f) { - if (f->open == NULL) + int ret; + + ret = ARCHIVE_OK; + if (f->next_filter != NULL) + ret = __archive_write_open_filter(f->next_filter); + if (ret != ARCHIVE_OK) + return (ret); + if (f->state != ARCHIVE_WRITE_FILTER_STATE_NEW) + return (ARCHIVE_FATAL); + if (f->open == NULL) { + f->state = ARCHIVE_WRITE_FILTER_STATE_OPEN; return (ARCHIVE_OK); - return (f->open)(f); + } + ret = (f->open)(f); + if (ret == ARCHIVE_OK) + f->state = ARCHIVE_WRITE_FILTER_STATE_OPEN; + else + f->state = ARCHIVE_WRITE_FILTER_STATE_FATAL; + return (ret); } /* - * Close a filter. + * Open all filters */ -int -__archive_write_close_filter(struct archive_write_filter *f) +static int +__archive_write_filters_open(struct archive_write *a) { - if (f->close != NULL) - return (f->close)(f); - if (f->next_filter != NULL) - return (__archive_write_close_filter(f->next_filter)); - return (ARCHIVE_OK); + return (__archive_write_open_filter(a->filter_first)); } +/* + * Close all filtes + */ +static int +__archive_write_filters_close(struct archive_write *a) +{ + struct archive_write_filter *f; + int ret, ret1; + ret = ARCHIVE_OK; + for (f = a->filter_first; f != NULL; f = f->next_filter) { + /* Do not close filters that are not open */ + if (f->state == ARCHIVE_WRITE_FILTER_STATE_OPEN) { + if (f->close != NULL) { + ret1 = (f->close)(f); + if (ret1 < ret) + ret = ret1; + if (ret1 == ARCHIVE_OK) { + f->state = + ARCHIVE_WRITE_FILTER_STATE_CLOSED; + } else { + f->state = + ARCHIVE_WRITE_FILTER_STATE_FATAL; + } + } else + f->state = ARCHIVE_WRITE_FILTER_STATE_CLOSED; + } + } + return (ret); +} + int __archive_write_output(struct archive_write *a, const void *buff, size_t length) { @@ -440,7 +487,7 @@ archive_write_client_close(struct archive_write_filter free(state->buffer); free(state); /* Clear the close handler myself not to be called again. */ - f->close = NULL; + f->state = ARCHIVE_WRITE_FILTER_STATE_CLOSED; a->client_data = NULL; /* Clear passphrase. */ if (a->passphrase != NULL) { @@ -477,9 +524,10 @@ archive_write_open(struct archive *_a, void *client_da client_filter->write = archive_write_client_write; client_filter->close = archive_write_client_close; - ret = __archive_write_open_filter(a->filter_first); + ret = __archive_write_filters_open(a); if (ret < ARCHIVE_WARN) { - r1 = __archive_write_close_filter(a->filter_first); + r1 = __archive_write_filters_close(a); + __archive_write_filters_free(_a); return (r1 < ret ? r1 : ret); } @@ -521,7 +569,7 @@ _archive_write_close(struct archive *_a) } /* Finish the compression and close the stream. */ - r1 = __archive_write_close_filter(a->filter_first); + r1 = __archive_write_filters_close(a); if (r1 < r) r = r1; Modified: head/contrib/libarchive/libarchive/archive_write_add_filter_b64encode.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_write_add_filter_b64encode.c Mon Dec 30 23:20:46 2019 (r356211) +++ head/contrib/libarchive/libarchive/archive_write_add_filter_b64encode.c Tue Dec 31 00:05:06 2019 (r356212) @@ -149,12 +149,7 @@ archive_filter_b64encode_open(struct archive_write_fil { struct private_b64encode *state = (struct private_b64encode *)f->data; size_t bs = 65536, bpb; - int ret; - ret = __archive_write_open_filter(f->next_filter); - if (ret != ARCHIVE_OK) - return (ret); - if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { /* Buffer size should be a multiple number of the of bytes * per block for performance. */ @@ -266,7 +261,6 @@ static int archive_filter_b64encode_close(struct archive_write_filter *f) { struct private_b64encode *state = (struct private_b64encode *)f->data; - int ret, ret2; /* Flush remaining bytes. */ if (state->hold_len != 0) @@ -274,12 +268,8 @@ archive_filter_b64encode_close(struct archive_write_fi archive_string_sprintf(&state->encoded_buff, "====\n"); /* Write the last block */ archive_write_set_bytes_in_last_block(f->archive, 1); - ret = __archive_write_filter(f->next_filter, + return __archive_write_filter(f->next_filter, state->encoded_buff.s, archive_strlen(&state->encoded_buff)); - ret2 = __archive_write_close_filter(f->next_filter); - if (ret > ret2) - ret = ret2; - return (ret); } static int Modified: head/contrib/libarchive/libarchive/archive_write_add_filter_bzip2.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_write_add_filter_bzip2.c Mon Dec 30 23:20:46 2019 (r356211) +++ head/contrib/libarchive/libarchive/archive_write_add_filter_bzip2.c Tue Dec 31 00:05:06 2019 (r356212) @@ -167,10 +167,6 @@ archive_compressor_bzip2_open(struct archive_write_fil struct private_data *data = (struct private_data *)f->data; int ret; - ret = __archive_write_open_filter(f->next_filter); - if (ret != 0) - return (ret); - if (data->compressed == NULL) { size_t bs = 65536, bpb; if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { @@ -262,7 +258,7 @@ static int archive_compressor_bzip2_close(struct archive_write_filter *f) { struct private_data *data = (struct private_data *)f->data; - int ret, r1; + int ret; /* Finish compression cycle. */ ret = drive_compressor(f, data, 1); @@ -281,9 +277,7 @@ archive_compressor_bzip2_close(struct archive_write_fi "Failed to clean up compressor"); ret = ARCHIVE_FATAL; } - - r1 = __archive_write_close_filter(f->next_filter); - return (r1 < ret ? r1 : ret); + return ret; } static int Modified: head/contrib/libarchive/libarchive/archive_write_add_filter_compress.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_write_add_filter_compress.c Mon Dec 30 23:20:46 2019 (r356211) +++ head/contrib/libarchive/libarchive/archive_write_add_filter_compress.c Tue Dec 31 00:05:06 2019 (r356212) @@ -146,17 +146,12 @@ archive_write_add_filter_compress(struct archive *_a) static int archive_compressor_compress_open(struct archive_write_filter *f) { - int ret; struct private_data *state; size_t bs = 65536, bpb; f->code = ARCHIVE_FILTER_COMPRESS; f->name = "compress"; - ret = __archive_write_open_filter(f->next_filter); - if (ret != ARCHIVE_OK) - return (ret); - state = (struct private_data *)calloc(1, sizeof(*state)); if (state == NULL) { archive_set_error(f->archive, ENOMEM, @@ -426,30 +421,27 @@ static int archive_compressor_compress_close(struct archive_write_filter *f) { struct private_data *state = (struct private_data *)f->data; - int ret, ret2; + int ret; ret = output_code(f, state->cur_code); if (ret != ARCHIVE_OK) - goto cleanup; + return ret; ret = output_flush(f); if (ret != ARCHIVE_OK) - goto cleanup; + return ret; /* Write the last block */ ret = __archive_write_filter(f->next_filter, state->compressed, state->compressed_offset); -cleanup: - ret2 = __archive_write_close_filter(f->next_filter); - if (ret > ret2) - ret = ret2; - free(state->compressed); - free(state); return (ret); } static int archive_compressor_compress_free(struct archive_write_filter *f) { - (void)f; /* UNUSED */ + struct private_data *state = (struct private_data *)f->data; + + free(state->compressed); + free(state); return (ARCHIVE_OK); } Modified: head/contrib/libarchive/libarchive/archive_write_add_filter_gzip.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_write_add_filter_gzip.c Mon Dec 30 23:20:46 2019 (r356211) +++ head/contrib/libarchive/libarchive/archive_write_add_filter_gzip.c Tue Dec 31 00:05:06 2019 (r356212) @@ -184,10 +184,6 @@ archive_compressor_gzip_open(struct archive_write_filt struct private_data *data = (struct private_data *)f->data; int ret; - ret = __archive_write_open_filter(f->next_filter); - if (ret != ARCHIVE_OK) - return (ret); - if (data->compressed == NULL) { size_t bs = 65536, bpb; if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { @@ -307,7 +303,7 @@ archive_compressor_gzip_close(struct archive_write_fil { unsigned char trailer[8]; struct private_data *data = (struct private_data *)f->data; - int ret, r1; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201912310005.xBV056p8074062>