git: 3a77c21a25e1 - stable/13 - libarchive: merge from vendor branch
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 04 May 2024 12:37:43 UTC
The branch stable/13 has been updated by mm: URL: https://cgit.FreeBSD.org/src/commit/?id=3a77c21a25e12fd60cc6093c74d4ad1a7f247319 commit 3a77c21a25e12fd60cc6093c74d4ad1a7f247319 Author: Martin Matuska <mm@FreeBSD.org> AuthorDate: 2024-04-29 08:15:04 +0000 Commit: Martin Matuska <mm@FreeBSD.org> CommitDate: 2024-05-04 11:54:42 +0000 libarchive: merge from vendor branch Libarchive 3.7.4 + three fixes from master Security fixes: #2135 rar: Fix OOB in rar e8 filter (CVE-2024-26256) #2145 zip: Fix out of boundary access #2148 rar: Fix OOB in rar delta filter #2149 rar: Fix OOB in rar audio filter Important bugfixes: #2131 7zip: Limit amount of properties #2110 bsdtar: Fix error handling around strtol() usages #2116 passphrase: Never allow empty passwords #2124 rar: Fix "File CRC Error" when extracting specific rar4 archives #2123 xar: Avoid infinite link loop #2150 xar: Fix another infinite loop and expat error handling #2108 zip: Update AppleDouble support for directories #2071 zstd: Implement core detectiongit PR: 278662 (exp-run) (cherry picked from commit 13d826ff947d9026f98e317e7385b22abfc0eace) --- contrib/libarchive/NEWS | 2 + contrib/libarchive/README.md | 2 +- contrib/libarchive/cat/cmdline.c | 16 +++-- contrib/libarchive/cpio/cmdline.c | 16 +++-- contrib/libarchive/libarchive/archive.h | 6 +- contrib/libarchive/libarchive/archive_entry.h | 2 +- contrib/libarchive/libarchive/archive_entry_acl.3 | 2 +- contrib/libarchive/libarchive/archive_read_disk.3 | 4 +- .../libarchive/archive_read_support_format_7zip.c | 2 + .../libarchive/archive_read_support_format_all.c | 2 +- .../libarchive/archive_read_support_format_ar.c | 4 +- .../libarchive/archive_read_support_format_lha.c | 4 +- .../libarchive/archive_read_support_format_mtree.c | 8 +-- .../libarchive/archive_read_support_format_rar.c | 30 +++++++- .../libarchive/archive_read_support_format_warc.c | 10 ++- .../libarchive/archive_read_support_format_xar.c | 9 +++ .../libarchive/archive_read_support_format_zip.c | 15 +++- contrib/libarchive/libarchive/archive_util.c | 3 +- .../libarchive/archive_write_add_filter_zstd.c | 23 +++++- .../libarchive/archive_write_disk_posix.c | 3 +- .../libarchive/libarchive/archive_write_private.h | 2 +- .../libarchive/archive_write_set_format_gnutar.c | 2 +- .../libarchive/archive_write_set_passphrase.c | 35 ++++----- .../libarchive/libarchive/libarchive_internals.3 | 2 +- .../test/test_read_format_xar_doublelink.c | 55 ++++++++++++++ .../test/test_read_format_xar_doublelink.xar.uu | 12 ++++ .../libarchive/test/test_write_disk_appledouble.c | 84 ++++++++++++++++++++++ .../test/test_write_disk_appledouble_zip.zip.uu | 27 +++++++ contrib/libarchive/libarchive_fe/passphrase.c | 4 +- contrib/libarchive/tar/bsdtar.1 | 15 ++-- contrib/libarchive/tar/bsdtar.c | 63 ++++++++-------- contrib/libarchive/tar/cmdline.c | 16 +++-- contrib/libarchive/unzip/cmdline.c | 18 +++-- contrib/libarchive/unzip/test/test_I.c | 13 ++++ lib/libarchive/tests/Makefile | 3 + 35 files changed, 404 insertions(+), 110 deletions(-) diff --git a/contrib/libarchive/NEWS b/contrib/libarchive/NEWS index f4395fd1c979..ebdbb2a978ec 100644 --- a/contrib/libarchive/NEWS +++ b/contrib/libarchive/NEWS @@ -1,3 +1,5 @@ +Apr 26, 2024: libarchive 3.7.4 released + Apr 08, 2024: libarchive 3.7.3 released Sep 12, 2023: libarchive 3.7.2 released diff --git a/contrib/libarchive/README.md b/contrib/libarchive/README.md index 727ed49856b6..933de6986425 100644 --- a/contrib/libarchive/README.md +++ b/contrib/libarchive/README.md @@ -201,7 +201,7 @@ questions we are asked about libarchive: In case other thread calls the same function in parallel, it might get interrupted by it and cause the executable to use umask=0 for the remaining execution. - This will then lead to implicitely created directories to have 777 + This will then lead to implicitly created directories to have 777 permissions without sticky bit. * In particular, libarchive's modules to read or write a directory diff --git a/contrib/libarchive/cat/cmdline.c b/contrib/libarchive/cat/cmdline.c index ea1e0eed6d0a..851b63de06e5 100644 --- a/contrib/libarchive/cat/cmdline.c +++ b/contrib/libarchive/cat/cmdline.c @@ -114,12 +114,18 @@ bsdcat_getopt(struct bsdcat *bsdcat) enum { state_start = 0, state_old_tar, state_next_word, state_short, state_long }; - const struct bsdcat_option *popt, *match = NULL, *match2 = NULL; - const char *p, *long_prefix = "--"; + const struct bsdcat_option *popt, *match, *match2; + const char *p, *long_prefix; size_t optlength; - int opt = '?'; - int required = 0; + int opt; + int required; +again: + match = NULL; + match2 = NULL; + long_prefix = "--"; + opt = '?'; + required = 0; bsdcat->argument = NULL; /* First time through, initialize everything. */ @@ -172,7 +178,7 @@ bsdcat_getopt(struct bsdcat *bsdcat) if (opt == '\0') { /* End of this group; recurse to get next option. */ bsdcat->getopt_state = state_next_word; - return bsdcat_getopt(bsdcat); + goto again; } /* Does this option take an argument? */ diff --git a/contrib/libarchive/cpio/cmdline.c b/contrib/libarchive/cpio/cmdline.c index 312d762c8f46..ab25492ede48 100644 --- a/contrib/libarchive/cpio/cmdline.c +++ b/contrib/libarchive/cpio/cmdline.c @@ -114,12 +114,18 @@ cpio_getopt(struct cpio *cpio) static int state = state_start; static char *opt_word; - const struct option *popt, *match = NULL, *match2 = NULL; - const char *p, *long_prefix = "--"; + const struct option *popt, *match, *match2; + const char *p, *long_prefix; size_t optlength; - int opt = '?'; - int required = 0; + int opt; + int required; +again: + match = NULL; + match2 = NULL; + long_prefix = "--"; + opt = '?'; + required = 0; cpio->argument = NULL; /* First time through, initialize everything. */ @@ -169,7 +175,7 @@ cpio_getopt(struct cpio *cpio) if (opt == '\0') { /* End of this group; recurse to get next option. */ state = state_next_word; - return cpio_getopt(cpio); + goto again; } /* Does this option take an argument? */ diff --git a/contrib/libarchive/libarchive/archive.h b/contrib/libarchive/libarchive/archive.h index 2e3a9f31cd33..fd4dd20fad13 100644 --- a/contrib/libarchive/libarchive/archive.h +++ b/contrib/libarchive/libarchive/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 3007003 +#define ARCHIVE_VERSION_NUMBER 3007004 #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.7.3" +#define ARCHIVE_VERSION_ONLY_STRING "3.7.4" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); @@ -895,7 +895,7 @@ __LA_DECL int archive_write_set_options(struct archive *_a, const char *opts); /* - * Set a encryption passphrase. + * Set an encryption passphrase. */ __LA_DECL int archive_write_set_passphrase(struct archive *_a, const char *p); __LA_DECL int archive_write_set_passphrase_callback(struct archive *, diff --git a/contrib/libarchive/libarchive/archive_entry.h b/contrib/libarchive/libarchive/archive_entry.h index df9cb765f7e8..1c59ded7c911 100644 --- a/contrib/libarchive/libarchive/archive_entry.h +++ b/contrib/libarchive/libarchive/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 3007003 +#define ARCHIVE_VERSION_NUMBER 3007004 /* * Note: archive_entry.h is for use outside of libarchive; the diff --git a/contrib/libarchive/libarchive/archive_entry_acl.3 b/contrib/libarchive/libarchive/archive_entry_acl.3 index 50dd642c20c6..4d0d8b50ed07 100644 --- a/contrib/libarchive/libarchive/archive_entry_acl.3 +++ b/contrib/libarchive/libarchive/archive_entry_acl.3 @@ -383,7 +383,7 @@ Prefix each default ACL entry with the word The mask and other ACLs don not contain a double colon. .El .Pp -The following flags are effecive only on NFSv4 ACL: +The following flags are effective only on NFSv4 ACL: .Bl -tag -offset indent -compact -width ARCHIV .It Dv ARCHIVE_ENTRY_ACL_STYLE_COMPACT Do not output minus characters for unset permissions and flags in NFSv4 ACL diff --git a/contrib/libarchive/libarchive/archive_read_disk.3 b/contrib/libarchive/libarchive/archive_read_disk.3 index 7cde3c232713..990c1514c4d5 100644 --- a/contrib/libarchive/libarchive/archive_read_disk.3 +++ b/contrib/libarchive/libarchive/archive_read_disk.3 @@ -288,11 +288,11 @@ calls. If matched based on calls to .Tn archive_match_time_excluded , or .Tn archive_match_owner_excluded , -then the callback function specified by the _excluded_func parameter will execute. This function will recieve data provided to the fourth parameter, void *_client_data. +then the callback function specified by the _excluded_func parameter will execute. This function will receive data provided to the fourth parameter, void *_client_data. .It Fn archive_read_disk_set_metadata_filter_callback Allows the caller to set a callback function during calls to .Xr archive_read_header 3 -to filter out metadata for each entry. The callback function recieves the +to filter out metadata for each entry. The callback function receives the .Tn struct archive object, void* custom filter data, and the .Tn struct archive_entry . diff --git a/contrib/libarchive/libarchive/archive_read_support_format_7zip.c b/contrib/libarchive/libarchive/archive_read_support_format_7zip.c index 92495e628f9a..7e465935c902 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_7zip.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_7zip.c @@ -2037,6 +2037,8 @@ read_Folder(struct archive_read *a, struct _7z_folder *f) if (parse_7zip_uint64( a, &(f->coders[i].propertiesSize)) < 0) return (-1); + if (UMAX_ENTRY < f->coders[i].propertiesSize) + return (-1); if ((p = header_bytes( a, (size_t)f->coders[i].propertiesSize)) == NULL) return (-1); diff --git a/contrib/libarchive/libarchive/archive_read_support_format_all.c b/contrib/libarchive/libarchive/archive_read_support_format_all.c index 5a4e1ab675a5..3b53c9ad5f57 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_all.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_all.c @@ -67,7 +67,7 @@ archive_read_support_format_all(struct archive *a) * increase the chance that a high bid from someone else will * make it unnecessary for these to do anything at all. */ - /* These three have potentially large look-ahead. */ + /* These have potentially large look-ahead. */ archive_read_support_format_7zip(a); archive_read_support_format_cab(a); archive_read_support_format_rar(a); diff --git a/contrib/libarchive/libarchive/archive_read_support_format_ar.c b/contrib/libarchive/libarchive/archive_read_support_format_ar.c index ca8effb0b0ee..6f1be8591fef 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_ar.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_ar.c @@ -270,7 +270,7 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry, } if (ar->strtab != NULL) { archive_set_error(&a->archive, EINVAL, - "More than one string tables exist"); + "More than one string table exists"); return (ARCHIVE_FATAL); } @@ -515,7 +515,7 @@ archive_read_format_ar_read_data(struct archive_read *a, if (ar->entry_padding) { if (skipped >= 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Truncated ar archive- failed consuming padding"); + "Truncated ar archive - failed consuming padding"); } return (ARCHIVE_FATAL); } diff --git a/contrib/libarchive/libarchive/archive_read_support_format_lha.c b/contrib/libarchive/libarchive/archive_read_support_format_lha.c index 1c64b2900b8e..4d6290ac33bb 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_lha.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_lha.c @@ -1693,7 +1693,7 @@ archive_read_format_lha_cleanup(struct archive_read *a) * example. * 1. a symbolic-name is 'aaa/bb/cc' * 2. a filename is 'xxx/bbb' - * then a archived pathname is 'xxx/bbb|aaa/bb/cc' + * then an archived pathname is 'xxx/bbb|aaa/bb/cc' */ static int lha_parse_linkname(struct archive_wstring *linkname, @@ -2385,7 +2385,7 @@ lzh_decode_blocks(struct lzh_stream *strm, int last) return (100); } - /* lzh_br_read_ahead() always try to fill the + /* lzh_br_read_ahead() always tries to fill the * cache buffer up. In specific situation we * are close to the end of the data, the cache * buffer will not be full and thus we have to diff --git a/contrib/libarchive/libarchive/archive_read_support_format_mtree.c b/contrib/libarchive/libarchive/archive_read_support_format_mtree.c index 630cff6e3999..6971228eefad 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_mtree.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_mtree.c @@ -416,8 +416,8 @@ next_line(struct archive_read *a, } /* - * Compare characters with a mtree keyword. - * Returns the length of a mtree keyword if matched. + * Compare characters with an mtree keyword. + * Returns the length of an mtree keyword if matched. * Returns 0 if not matched. */ static int @@ -515,7 +515,7 @@ bid_keyword(const char *p, ssize_t len) /* * Test whether there is a set of mtree keywords. - * Returns the number of keyword. + * Returns the number of keywords. * Returns -1 if we got incorrect sequence. * This function expects a set of "<space characters>keyword=value". * When "unset" is specified, expects a set of "<space characters>keyword". @@ -760,7 +760,7 @@ detect_form(struct archive_read *a, int *is_form_d) multiline = 1; else { /* We've got plenty of correct lines - * to assume that this file is a mtree + * to assume that this file is an mtree * format. */ if (++entry_cnt >= MAX_BID_ENTRY) break; diff --git a/contrib/libarchive/libarchive/archive_read_support_format_rar.c b/contrib/libarchive/libarchive/archive_read_support_format_rar.c index 99a11d170074..4fc6626cacfd 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_rar.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_rar.c @@ -2176,6 +2176,19 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, { start = rar->offset; end = start + rar->dictionary_size; + + /* We don't want to overflow the window and overwrite data that we write + * at 'start'. Therefore, reduce the end length by the maximum match size, + * which is 260 bytes. You can compute this maximum by looking at the + * definition of 'expand', in particular when 'symbol >= 271'. */ + /* NOTE: It's possible for 'dictionary_size' to be less than this 260 + * value, however that will only be the case when 'unp_size' is small, + * which should only happen when the entry size is small and there's no + * risk of overflowing the buffer */ + if (rar->dictionary_size > 260) { + end -= 260; + } + if (rar->filters.filterstart < end) { end = rar->filters.filterstart; } @@ -3599,7 +3612,15 @@ execute_filter_delta(struct rar_filter *filter, struct rar_virtual_machine *vm) { uint8_t lastbyte = 0; for (idx = i; idx < length; idx += numchannels) + { + /* + * The src block should not overlap with the dst block. + * If so it would be better to consider this archive is broken. + */ + if (src >= dst) + return 0; lastbyte = dst[idx] = lastbyte - *src++; + } } filter->filteredblockaddress = length; @@ -3615,7 +3636,7 @@ execute_filter_e8(struct rar_filter *filter, struct rar_virtual_machine *vm, siz uint32_t filesize = 0x1000000; uint32_t i; - if (length > PROGRAM_WORK_SIZE || length < 4) + if (length > PROGRAM_WORK_SIZE || length <= 4) return 0; for (i = 0; i <= length - 5; i++) @@ -3701,6 +3722,13 @@ execute_filter_audio(struct rar_filter *filter, struct rar_virtual_machine *vm) memset(&state, 0, sizeof(state)); for (j = i; j < length; j += numchannels) { + /* + * The src block should not overlap with the dst block. + * If so it would be better to consider this archive is broken. + */ + if (src >= dst) + return 0; + int8_t delta = (int8_t)*src++; uint8_t predbyte, byte; int prederror; diff --git a/contrib/libarchive/libarchive/archive_read_support_format_warc.c b/contrib/libarchive/libarchive/archive_read_support_format_warc.c index c49d44eba5e5..fcec5bc4cbb9 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_warc.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_warc.c @@ -215,6 +215,7 @@ _warc_rdhdr(struct archive_read *a, struct archive_entry *entry) const char *buf; ssize_t nrd; const char *eoh; + char *tmp; /* for the file name, saves some strndup()'ing */ warc_string_t fnam; /* warc record type, not that we really use it a lot */ @@ -321,7 +322,14 @@ start_over: * malloc()+free() roundtrip */ if (fnam.len + 1U > w->pool.len) { w->pool.len = ((fnam.len + 64U) / 64U) * 64U; - w->pool.str = realloc(w->pool.str, w->pool.len); + tmp = realloc(w->pool.str, w->pool.len); + if (tmp == NULL) { + archive_set_error( + &a->archive, ENOMEM, + "Out of memory"); + return (ARCHIVE_FATAL); + } + w->pool.str = tmp; } memcpy(w->pool.str, fnam.str, fnam.len); w->pool.str[fnam.len] = '\0'; diff --git a/contrib/libarchive/libarchive/archive_read_support_format_xar.c b/contrib/libarchive/libarchive/archive_read_support_format_xar.c index fd63594373cb..cefb36410e77 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_xar.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_xar.c @@ -2055,6 +2055,12 @@ xml_start(struct archive_read *a, const char *name, struct xmlattr_list *list) attr = attr->next) { if (strcmp(attr->name, "link") != 0) continue; + if (xar->file->hdnext != NULL || xar->file->link != 0 || + xar->file == xar->hdlink_orgs) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "File with multiple link attributes"); + return (ARCHIVE_FATAL); + } if (strcmp(attr->value, "original") == 0) { xar->file->hdnext = xar->hdlink_orgs; xar->hdlink_orgs = xar->file; @@ -3251,6 +3257,9 @@ expat_start_cb(void *userData, const XML_Char *name, const XML_Char **atts) struct xmlattr_list list; int r; + if (ud->state != ARCHIVE_OK) + return; + r = expat_xmlattr_setup(a, &list, atts); if (r == ARCHIVE_OK) r = xml_start(a, (const char *)name, &list); diff --git a/contrib/libarchive/libarchive/archive_read_support_format_zip.c b/contrib/libarchive/libarchive/archive_read_support_format_zip.c index 212bfff9fa7b..c9759eaf9a89 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_zip.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_zip.c @@ -1393,7 +1393,7 @@ check_authentication_code(struct archive_read *a, const void *_p) * [CRC32] [compressed low] [compressed high] [uncompressed low] [uncompressed high] [other PK marker] * ``` * Since the 32-bit and 64-bit compressed sizes both match, the - * actualy size must fit in 32 bits, which implies the high-order + * actual size must fit in 32 bits, which implies the high-order * word of the compressed size is zero. So we know the uncompressed * low word is zero, which again implies that if we accept the shorter * format, there will not be a valid PK marker following it. @@ -4083,6 +4083,17 @@ slurp_central_directory(struct archive_read *a, struct archive_entry* entry, } else { /* Generate resource fork name to find its * resource file at zip->tree_rsrc. */ + + /* If this is an entry ending with slash, + * make the resource for name slash-less + * as the actual resource fork doesn't end with '/'. + */ + size_t tmp_length = filename_length; + if (tmp_length > 0 && name[tmp_length - 1] == '/') { + tmp_length--; + r = rsrc_basename(name, tmp_length); + } + archive_strcpy(&(zip_entry->rsrcname), "__MACOSX/"); archive_strncat(&(zip_entry->rsrcname), @@ -4090,7 +4101,7 @@ slurp_central_directory(struct archive_read *a, struct archive_entry* entry, archive_strcat(&(zip_entry->rsrcname), "._"); archive_strncat(&(zip_entry->rsrcname), name + (r - name), - filename_length - (r - name)); + tmp_length - (r - name)); /* Register an entry to RB tree to sort it by * file offset. */ __archive_rb_tree_insert_node(&zip->tree, diff --git a/contrib/libarchive/libarchive/archive_util.c b/contrib/libarchive/libarchive/archive_util.c index 32d4bd40988c..7b918fef04b8 100644 --- a/contrib/libarchive/libarchive/archive_util.c +++ b/contrib/libarchive/libarchive/archive_util.c @@ -255,10 +255,9 @@ __archive_mktempx(const char *tmpdir, wchar_t *template) #endif fd = -1; ws = NULL; + archive_string_init(&temp_name); if (template == NULL) { - archive_string_init(&temp_name); - /* Get a temporary directory. */ if (tmpdir == NULL) { size_t l; diff --git a/contrib/libarchive/libarchive/archive_write_add_filter_zstd.c b/contrib/libarchive/libarchive/archive_write_add_filter_zstd.c index 94249accd08b..7ea3d18c9b76 100644 --- a/contrib/libarchive/libarchive/archive_write_add_filter_zstd.c +++ b/contrib/libarchive/libarchive/archive_write_add_filter_zstd.c @@ -29,6 +29,9 @@ #ifdef HAVE_ERRNO_H #include <errno.h> #endif +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif #ifdef HAVE_STDINT_H #include <stdint.h> #endif @@ -38,6 +41,9 @@ #ifdef HAVE_STRING_H #include <string.h> #endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif #ifdef HAVE_ZSTD_H #include <zstd.h> #endif @@ -190,6 +196,7 @@ string_to_number(const char *string, intmax_t *numberp) return (ARCHIVE_OK); } +#if HAVE_ZSTD_H && HAVE_ZSTD_compressStream static int string_to_size(const char *string, size_t *numberp) { @@ -224,6 +231,7 @@ string_to_size(const char *string, size_t *numberp) *numberp = (size_t)(number << shift); return (ARCHIVE_OK); } +#endif /* * Set write options. @@ -264,7 +272,20 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key, if (string_to_number(value, &threads) != ARCHIVE_OK) { return (ARCHIVE_WARN); } - if (threads < 0) { + +#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) + if (threads == 0) { + threads = sysconf(_SC_NPROCESSORS_ONLN); + } +#elif !defined(__CYGWIN__) && defined(_WIN32_WINNT) && \ + _WIN32_WINNT >= 0x0601 /* _WIN32_WINNT_WIN7 */ + if (threads == 0) { + DWORD winCores = GetActiveProcessorCount( + ALL_PROCESSOR_GROUPS); + threads = (intmax_t)winCores; + } +#endif + if (threads < 0 || threads > INT_MAX) { return (ARCHIVE_WARN); } data->threads = (int)threads; diff --git a/contrib/libarchive/libarchive/archive_write_disk_posix.c b/contrib/libarchive/libarchive/archive_write_disk_posix.c index f671bc6db747..d69c77ea0517 100644 --- a/contrib/libarchive/libarchive/archive_write_disk_posix.c +++ b/contrib/libarchive/libarchive/archive_write_disk_posix.c @@ -4427,7 +4427,8 @@ fixup_appledouble(struct archive_write_disk *a, const char *pathname) #else la_stat(datafork.s, &st) == -1 || #endif - (st.st_mode & AE_IFMT) != AE_IFREG) + (((st.st_mode & AE_IFMT) != AE_IFREG) && + ((st.st_mode & AE_IFMT) != AE_IFDIR))) goto skip_appledouble; /* diff --git a/contrib/libarchive/libarchive/archive_write_private.h b/contrib/libarchive/libarchive/archive_write_private.h index abd5a8ddcd85..f259ccb16546 100644 --- a/contrib/libarchive/libarchive/archive_write_private.h +++ b/contrib/libarchive/libarchive/archive_write_private.h @@ -158,7 +158,7 @@ int __archive_write_program_write(struct archive_write_filter *, struct archive_write_program_data *, const void *, size_t); /* - * Get a encryption passphrase. + * Get an encryption passphrase. */ const char * __archive_write_get_passphrase(struct archive_write *a); #endif diff --git a/contrib/libarchive/libarchive/archive_write_set_format_gnutar.c b/contrib/libarchive/libarchive/archive_write_set_format_gnutar.c index 92b06c5f5fb4..a88350b87411 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_gnutar.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_gnutar.c @@ -387,7 +387,7 @@ archive_write_gnutar_header(struct archive_write *a, if (r != 0) { if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, - "Can't allocate memory for Pathame"); + "Can't allocate memory for pathname"); ret = ARCHIVE_FATAL; goto exit_write_header; } diff --git a/contrib/libarchive/libarchive/archive_write_set_passphrase.c b/contrib/libarchive/libarchive/archive_write_set_passphrase.c index 977fc4a9ee6b..f871c8e2f810 100644 --- a/contrib/libarchive/libarchive/archive_write_set_passphrase.c +++ b/contrib/libarchive/libarchive/archive_write_set_passphrase.c @@ -30,14 +30,9 @@ #endif #include "archive_write_private.h" -int -archive_write_set_passphrase(struct archive *_a, const char *p) +static int +set_passphrase(struct archive_write *a, const char *p) { - struct archive_write *a = (struct archive_write *)_a; - - archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, - "archive_write_set_passphrase"); - if (p == NULL || p[0] == '\0') { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Empty passphrase is unacceptable"); @@ -54,6 +49,18 @@ archive_write_set_passphrase(struct archive *_a, const char *p) } +int +archive_write_set_passphrase(struct archive *_a, const char *p) +{ + struct archive_write *a = (struct archive_write *)_a; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, + "archive_write_set_passphrase"); + + return (set_passphrase(a, p)); +} + + int archive_write_set_passphrase_callback(struct archive *_a, void *client_data, archive_passphrase_callback *cb) @@ -80,15 +87,9 @@ __archive_write_get_passphrase(struct archive_write *a) const char *p; p = a->passphrase_callback(&a->archive, a->passphrase_client_data); - if (p != NULL) { - a->passphrase = strdup(p); - if (a->passphrase == NULL) { - archive_set_error(&a->archive, ENOMEM, - "Can't allocate data for passphrase"); - return (NULL); - } - return (a->passphrase); - } + set_passphrase(a, p); + a->passphrase_callback = NULL; + a->passphrase_client_data = NULL; } - return (NULL); + return (a->passphrase); } diff --git a/contrib/libarchive/libarchive/libarchive_internals.3 b/contrib/libarchive/libarchive/libarchive_internals.3 index d4696f648292..2978b48c3e97 100644 --- a/contrib/libarchive/libarchive/libarchive_internals.3 +++ b/contrib/libarchive/libarchive/libarchive_internals.3 @@ -124,7 +124,7 @@ to read the entire file into memory at once and return the entire file to libarchive as a single block; other clients may begin asynchronous I/O operations for the next block on each request. -.Ss Decompresssion Layer +.Ss Decompression Layer The decompression layer not only handles decompression, it also buffers data so that the format handlers see a much nicer I/O model. diff --git a/contrib/libarchive/libarchive/test/test_read_format_xar_doublelink.c b/contrib/libarchive/libarchive/test/test_read_format_xar_doublelink.c new file mode 100644 index 000000000000..78d6626a09bf --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_xar_doublelink.c @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2024 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +#define __LIBARCHIVE_BUILD + +DEFINE_TEST(test_read_format_xar_doublelink) +{ + const char *refname = "test_read_format_xar_doublelink.xar"; + struct archive *a; + struct archive_entry *ae; + + extract_reference_file(refname); + + /* Verify with seeking reader. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + if(ARCHIVE_OK != archive_read_support_format_xar(a)) { + skipping("XAR format unsupported"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, + 10240)); + + assertA(ARCHIVE_FATAL == archive_read_next_header(a, &ae)); + assertEqualString(archive_error_string(a), + "File with multiple link attributes"); + assert(archive_errno(a) != 0); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/contrib/libarchive/libarchive/test/test_read_format_xar_doublelink.xar.uu b/contrib/libarchive/libarchive/test/test_read_format_xar_doublelink.xar.uu new file mode 100644 index 000000000000..7aa638a86e7c --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_xar_doublelink.xar.uu @@ -0,0 +1,12 @@ +begin 664 test_read_format_xar_doublelink.xar +M>&%R(0`<``$````````!0`````````/7`````7B<[9/!<L(@%$7W?@7#/H60 +MU'0R!'?]`KOICDF>D3&``]'1?GT!-1U;;:=[5[G<=WB0=P>^..@![<%Y94V# +M\R>*$9C6=LKT#7Y;OF8O>"%F_""=F"$^VC9\$&\=R#'LR$:E03#*RHR6&2N6 +MM*KIO,YS3JZ1M&D-[<;O-/+C<8`&^[7,<:P@;E<K#Z.@G)Q5<KWZB,TY22*V +M()<>:;52`R#5A6N?VQ@9CHIN.#_IY(['+:!!F4V#K5.],G+`8BU=%SU.8OF? +MH#*V`U%5K"@9)Z=5*G2P5RT8*YY+3J9%*ND(T?D\%/3$[U0G<DK#+T9ULCPX +MH75PHDA6/U']A>J=W6T3=E+);&^E4=0%?0^#N\00;G(;8U7`]!<F?\'D%"J) +MX[Y.@WU/@]U)(_\SACO$8_X_YA_&$]\F)^FE?@)<4AJ<B%QTTZN3JTL:$,<5 +<`XH;(KD-Q0=XG.V3P7+"(!1%]WX%PSZ%D-1T,@`` +` +end diff --git a/contrib/libarchive/libarchive/test/test_write_disk_appledouble.c b/contrib/libarchive/libarchive/test/test_write_disk_appledouble.c index 3265a94d2fed..8de6c8b50413 100644 --- a/contrib/libarchive/libarchive/test/test_write_disk_appledouble.c +++ b/contrib/libarchive/libarchive/test/test_write_disk_appledouble.c @@ -236,3 +236,87 @@ DEFINE_TEST(test_write_disk_appledouble) assertEqualFile("hfscmp/file3", "nocmp/file3"); #endif } + +/* Test writing apple doubles to disk from zip format */ +DEFINE_TEST(test_write_disk_appledouble_zip) +{ +#if !defined(__APPLE__) || !defined(UF_COMPRESSED) || !defined(HAVE_SYS_XATTR_H)\ + || !defined(HAVE_ZLIB_H) + skipping("MacOS-specific AppleDouble test"); +#else + const char *refname = "test_write_disk_appledouble_zip.zip"; + struct archive *ad, *a; + struct archive_entry *ae; + struct stat st; + + extract_reference_file(refname); + + /* + * Extract an archive to disk. + */ + assert((ad = archive_write_disk_new()) != NULL); + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_disk_set_standard_lookup(ad)); + assertEqualIntA(ad, ARCHIVE_OK, + archive_write_disk_set_options(ad, + ARCHIVE_EXTRACT_TIME | + ARCHIVE_EXTRACT_SECURE_SYMLINKS | + ARCHIVE_EXTRACT_SECURE_NODOTDOT)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, + refname, 512 * 20)); + + /* Skip The top level directory */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("apple_double_dir/", archive_entry_pathname(ae)); + + /* Extract apple_double_test */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("apple_double_dir/apple_double_dir_test/", archive_entry_pathname(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + + /* Extract ._apple_double_dir_test which will be merged into apple_double_dir_test as metadata. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("apple_double_dir/._apple_double_dir_test", archive_entry_pathname(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + + /* Extract test_file */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("apple_double_dir/test_file", archive_entry_pathname(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + + /* Extract ._test_file which will be merged into test_file as metadata. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("apple_double_dir/._test_file", archive_entry_pathname(ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + + /* Test test_file */ + assertEqualInt(0, stat("apple_double_dir/test_file", &st)); + assertFileSize("apple_double_dir/test_file", 5); + failure("'%s' should have Resource Fork", "test_file"); + assertEqualInt(1, has_xattr("apple_double_dir/test_file", "com.apple.ResourceFork")); + + /* Test apple_double_dir_test */ + failure("'%s' should have quarantine xattr", "apple_double_dir_test"); + assertEqualInt(1, has_xattr("apple_double_dir/apple_double_dir_test", "com.apple.quarantine")); + + /* Test ._test_file. */ + failure("'apple_double_dir/._test_file' should be merged and removed"); + assertFileNotExists("apple_double_dir/._test_file"); + + /* Test ._apple_double_dir_test */ + failure("'apple_double_dir/._._apple_double_dir_test' should be merged and removed"); + assertFileNotExists("apple_double_dir/._apple_double_dir_test"); + + assertChdir(".."); + +#endif +} diff --git a/contrib/libarchive/libarchive/test/test_write_disk_appledouble_zip.zip.uu b/contrib/libarchive/libarchive/test/test_write_disk_appledouble_zip.zip.uu new file mode 100644 index 000000000000..5ab67533d559 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_write_disk_appledouble_zip.zip.uu @@ -0,0 +1,27 @@ +begin 644 test_write_disk_appledouble_zip.zip +M4$L#!`H```````MM?%@````````````````1`!``87!P;&5?9&]U8FQE7V1I +M<B]56`P`O=4%9K75!6;U`10`4$L#!`H```````MM?%@````````````````G +M`!``87!P;&5?9&]U8FQE7V1I<B]A<'!L95]D;W5B;&5?9&ER7W1E<W0O55@, +M`+W5!6:UU05F]0$4`%!+`P04``@`"``+;7Q8````````````````*``0`&%P +M<&QE7V1O=6)L95]D:7(O+E]A<'!L95]D;W5B;&5?9&ER7W1E<W156`P`O=4% +M9K75!6;U`10`8V`58V=@8F#P34Q6\`]6B%"``I`8`R<0&P%Q!1"#^*L8B`*. +M(2%!4"9(QPP@%D)3PH@0%TW.S]5++"C(2=4K+$TL2LPKR<Q+92C4-S"P,+8V +M@`)K:P8`4$L'"!2N=6M7````J@```%!+`P04``@`"`!93GQ8```````````` +M````&@`0`&%P<&QE7V1O=6)L95]D:7(O=&5S=%]F:6QE55@,`+'5!6;IGP5F +M]0$4`"M)+2[A`@!02P<(QC6Y.P<````%````4$L#!!0`"``(`%E.?%@````` +M```````````<`!``87!P;&5?9&]U8FQE7V1I<B\N7W1E<W1?9FEL9558#`"Q +MU05FZ9\%9O4!%`!C8!5C9V!B8/!-3%;P#U:(4(`"D!@#)Q`;`;$;$(/X%4#, +MQT`0.(:$!$&9%5",`8I2B_-+BY)3%=+RB[*Y`%!+!P@HPLP3/@```(8```!0 +M2P$"%0,*```````+;7Q8````````````````$0`,``````````!`[4$````` +M87!P;&5?9&]U8FQE7V1I<B]56`@`O=4%9K75!6902P$"%0,*```````+;7Q8 +M````````````````)P`,``````````!`[4$_````87!P;&5?9&]U8FQE7V1I +M<B]A<'!L95]D;W5B;&5?9&ER7W1E<W0O55@(`+W5!6:UU05F4$L!`A4#%``( +M``@`"VU\6!2N=6M7````J@```"@`#```````````0*2!E````&%P<&QE7V1O +M=6)L95]D:7(O+E]A<'!L95]D;W5B;&5?9&ER7W1E<W156`@`O=4%9K75!690 +M2P$"%0,4``@`"`!93GQ8QC6Y.P<````%````&@`,``````````!`I(%1`0`` +M87!P;&5?9&]U8FQE7V1I<B]T97-T7V9I;&556`@`L=4%9NF?!6902P$"%0,4 +M``@`"`!93GQ8*,+,$SX```"&````'``,``````````!`I(&P`0``87!P;&5? +M9&]U8FQE7V1I<B\N7W1E<W1?9FEL9558"`"QU05FZ9\%9E!+!08`````!0`% ++`+@!``!(`@`````` +` +end diff --git a/contrib/libarchive/libarchive_fe/passphrase.c b/contrib/libarchive/libarchive_fe/passphrase.c index 9d95d527067b..90fef32d254c 100644 --- a/contrib/libarchive/libarchive_fe/passphrase.c +++ b/contrib/libarchive/libarchive_fe/passphrase.c @@ -76,6 +76,7 @@ #if defined(_WIN32) && !defined(__CYGWIN__) +#include <string.h> #include <windows.h> static char * @@ -113,8 +114,7 @@ readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) WriteFile(hStdout, "\r\n", 2, NULL, NULL); buf[rbytes] = '\0'; /* Remove trailing carriage return(s). */ - if (rbytes > 2 && buf[rbytes - 2] == '\r' && buf[rbytes - 1] == '\n') - buf[rbytes - 2] = '\0'; + buf[strcspn(buf, "\r\n")] = '\0'; return (buf); } diff --git a/contrib/libarchive/tar/bsdtar.1 b/contrib/libarchive/tar/bsdtar.1 index e570d2a48a01..fe9ec9504674 100644 --- a/contrib/libarchive/tar/bsdtar.1 +++ b/contrib/libarchive/tar/bsdtar.1 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd March 1, 2024 +.Dd April 23, 2024 .Dt TAR 1 .Os .Sh NAME @@ -644,14 +644,13 @@ A decimal integer from 4 to 7 specifying the lz4 compression block size .It Cm lz4:block-dependence Use the previous block of the block being compressed for a compression dictionary to improve compression ratio. -.It Cm zstd:compression-level -A decimal integer specifying the zstd compression level. Supported values depend +.It Cm zstd:compression-level Ns = Ns Ar N +A decimal integer specifying the zstd compression level. +Supported values depend on the library version, common values are from 1 to 22. -.It Cm zstd:threads -Specify the number of worker threads to use. -Setting threads to a special value 0 makes -.Xr zstd 1 -use as many threads as there are CPU cores on the system. +.It Cm zstd:threads Ns = Ns Ar N +Specify the number of worker threads to use, or 0 to use as many +threads as there are CPU cores in the system. .It Cm zstd:frame-per-file Start a new compression frame at the beginning of each file in the archive. diff --git a/contrib/libarchive/tar/bsdtar.c b/contrib/libarchive/tar/bsdtar.c index b070e0faeb66..42baab2861bd 100644 --- a/contrib/libarchive/tar/bsdtar.c +++ b/contrib/libarchive/tar/bsdtar.c @@ -157,6 +157,7 @@ main(int argc, char **argv) char *tptr, *uptr; char possible_help_request; char buff[16]; + long l; /* * Use a pointer for consistency, but stack-allocated storage @@ -301,16 +302,15 @@ main(int argc, char **argv) /* libarchive doesn't need this; just ignore it. */ break; case 'b': /* SUSv2 */ - errno = 0; tptr = NULL; - t = (int)strtol(bsdtar->argument, &tptr, 10); - if (errno || t <= 0 || t > 8192 || + l = strtol(bsdtar->argument, &tptr, 10); + if (l <= 0 || l > 8192L || *(bsdtar->argument) == '\0' || tptr == NULL || *tptr != '\0') { lafe_errc(1, 0, "Invalid or out of range " "(1..8192) argument to -b"); } - bsdtar->bytes_per_block = 512 * t; + bsdtar->bytes_per_block = 512 * (int)l; /* Explicit -b forces last block size. */ bsdtar->bytes_in_last_block = bsdtar->bytes_per_block; break; @@ -369,44 +369,42 @@ main(int argc, char **argv) *** 263 LINES SKIPPED ***