From 3a77c21a25e12fd60cc6093c74d4ad1a7f247319 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Mon, 29 Apr 2024 10:15:04 +0200 Subject: 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(-) create mode 100644 contrib/libarchive/libarchive/test/test_read_format_xar_doublelink.c create mode 100644 contrib/libarchive/libarchive/test/test_read_format_xar_doublelink.xar.uu create mode 100644 contrib/libarchive/libarchive/test/test_write_disk_appledouble_zip.zip.uu 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 #include /* 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 "keyword=value". * When "unset" is specified, expects a set of "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 #endif +#ifdef HAVE_LIMITS_H +#include +#endif #ifdef HAVE_STDINT_H #include #endif @@ -38,6 +41,9 @@ #ifdef HAVE_STRING_H #include #endif +#ifdef HAVE_UNISTD_H +#include +#endif #ifdef HAVE_ZSTD_H #include #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/!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:;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$[U0GJ=W6T3=E+);&^E4=0%?0^#N\00;G(;8U7`]! #include 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) bsdtar->filename = bsdtar->argument; break; case OPTION_GID: /* cpio */ - errno = 0; tptr = NULL; - t = (int)strtol(bsdtar->argument, &tptr, 10); - if (errno || t < 0 || *(bsdtar->argument) == '\0' || + l = strtol(bsdtar->argument, &tptr, 10); + if (l < 0 || l >= INT_MAX || *(bsdtar->argument) == '\0' || tptr == NULL || *tptr != '\0') { lafe_errc(1, 0, "Invalid argument to --gid"); } - bsdtar->gid = t; + bsdtar->gid = (int)l; break; case OPTION_GNAME: /* cpio */ bsdtar->gname = bsdtar->argument; break; case OPTION_GROUP: /* GNU tar */ - errno = 0; tptr = NULL; uptr = strchr(bsdtar->argument, ':'); - if(uptr != NULL) { - if(uptr[1] == 0) { + if (uptr != NULL) { + if (uptr[1] == '\0') { lafe_errc(1, 0, "Invalid argument to --group (missing id after :)"); } uptr[0] = 0; uptr++; - t = (int)strtol(uptr, &tptr, 10); - if (errno || t < 0 || *uptr == '\0' || + l = strtol(uptr, &tptr, 10); + if (l < 0 || l >= INT_MAX || *uptr == '\0' || tptr == NULL || *tptr != '\0') { lafe_errc(1, 0, "Invalid argument to --group (%s is not a number)", uptr); } else { - bsdtar->gid = t; + bsdtar->gid = (int)l; } bsdtar->gname = bsdtar->argument; } else { - t = (int)strtol(bsdtar->argument, &tptr, 10); - if (errno || t < 0 || *(bsdtar->argument) == '\0' || + l = strtol(bsdtar->argument, &tptr, 10); + if (l < 0 || l >= INT_MAX || *(bsdtar->argument) == '\0' || tptr == NULL || *tptr != '\0') { bsdtar->gname = bsdtar->argument; } else { - bsdtar->gid = t; + bsdtar->gid = (int)l; bsdtar->gname = ""; } } @@ -662,31 +660,30 @@ main(int argc, char **argv) bsdtar->option_options = bsdtar->argument; break; case OPTION_OWNER: /* GNU tar */ - errno = 0; tptr = NULL; uptr = strchr(bsdtar->argument, ':'); - if(uptr != NULL) { - if(uptr[1] == 0) { + if (uptr != NULL) { + if (uptr[1] == 0) { lafe_errc(1, 0, "Invalid argument to --owner (missing id after :)"); } uptr[0] = 0; uptr++; - t = (int)strtol(uptr, &tptr, 10); - if (errno || t < 0 || *uptr == '\0' || + l = strtol(uptr, &tptr, 10); + if (l < 0 || l >= INT_MAX || *uptr == '\0' || tptr == NULL || *tptr != '\0') { lafe_errc(1, 0, "Invalid argument to --owner (%s is not a number)", uptr); } else { - bsdtar->uid = t; + bsdtar->uid = (int)l; } bsdtar->uname = bsdtar->argument; } else { - t = (int)strtol(bsdtar->argument, &tptr, 10); - if (errno || t < 0 || *(bsdtar->argument) == '\0' || + l = strtol(bsdtar->argument, &tptr, 10); + if (l < 0 || l >= INT_MAX || *(bsdtar->argument) == '\0' || tptr == NULL || *tptr != '\0') { bsdtar->uname = bsdtar->argument; } else { - bsdtar->uid = t; + bsdtar->uid = (int)l; bsdtar->uname = ""; } } @@ -748,15 +745,14 @@ main(int argc, char **argv) bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER; break; case OPTION_STRIP_COMPONENTS: /* GNU tar 1.15 */ - errno = 0; tptr = NULL; - t = (int)strtol(bsdtar->argument, &tptr, 10); - if (errno || t < 0 || *(bsdtar->argument) == '\0' || + l = strtol(bsdtar->argument, &tptr, 10); + if (l < 0 || l > 100000L || *(bsdtar->argument) == '\0' || tptr == NULL || *tptr != '\0') { lafe_errc(1, 0, "Invalid argument to " "--strip-components"); } - bsdtar->strip_components = t; + bsdtar->strip_components = (int)l; break; case 'T': /* GNU tar */ bsdtar->names_from_file = bsdtar->argument; @@ -776,14 +772,13 @@ main(int argc, char **argv) set_mode(bsdtar, opt); break; case OPTION_UID: /* cpio */ - errno = 0; tptr = NULL; - t = (int)strtol(bsdtar->argument, &tptr, 10); - if (errno || t < 0 || *(bsdtar->argument) == '\0' || + l = strtol(bsdtar->argument, &tptr, 10); + if (l < 0 || l >= INT_MAX || *(bsdtar->argument) == '\0' || tptr == NULL || *tptr != '\0') { lafe_errc(1, 0, "Invalid argument to --uid"); } - bsdtar->uid = t; + bsdtar->uid = (int)l; break; case OPTION_UNAME: /* cpio */ bsdtar->uname = bsdtar->argument; diff --git a/contrib/libarchive/tar/cmdline.c b/contrib/libarchive/tar/cmdline.c index 72292e8f27f3..2a89f42b0880 100644 --- a/contrib/libarchive/tar/cmdline.c +++ b/contrib/libarchive/tar/cmdline.c @@ -218,12 +218,18 @@ bsdtar_getopt(struct bsdtar *bsdtar) enum { state_start = 0, state_old_tar, state_next_word, state_short, state_long }; - const struct bsdtar_option *popt, *match = NULL, *match2 = NULL; - const char *p, *long_prefix = "--"; + const struct bsdtar_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; bsdtar->argument = NULL; /* First time through, initialize everything. */ @@ -310,7 +316,7 @@ bsdtar_getopt(struct bsdtar *bsdtar) if (opt == '\0') { /* End of this group; recurse to get next option. */ bsdtar->getopt_state = state_next_word; - return bsdtar_getopt(bsdtar); + goto again; } /* Does this option take an argument? */ diff --git a/contrib/libarchive/unzip/cmdline.c b/contrib/libarchive/unzip/cmdline.c index ab1aeb31fe18..4c6efc3e0694 100644 --- a/contrib/libarchive/unzip/cmdline.c +++ b/contrib/libarchive/unzip/cmdline.c @@ -81,12 +81,18 @@ bsdunzip_getopt(struct bsdunzip *bsdunzip) { enum { state_start = 0, state_next_word, state_short, state_long }; - const struct bsdunzip_option *popt, *match = NULL, *match2 = NULL; - const char *p, *long_prefix = "--"; + const struct bsdunzip_option *popt, *match, *match2; + const char *p, *long_prefix; size_t optlength; - int opt = OPTION_NONE; - int required = 0; - + int opt; + int required; + +again: + match = NULL; + match2 = NULL; + long_prefix = "--"; + opt = OPTION_NONE; + required = 0; bsdunzip->argument = NULL; /* First time through, initialize everything. */ @@ -140,7 +146,7 @@ bsdunzip_getopt(struct bsdunzip *bsdunzip) if (opt == '\0') { /* End of this group; recurse to get next option. */ bsdunzip->getopt_state = state_next_word; - return bsdunzip_getopt(bsdunzip); + goto again; } /* Does this option take an argument? */ diff --git a/contrib/libarchive/unzip/test/test_I.c b/contrib/libarchive/unzip/test/test_I.c index a6bad85a011f..5d31ce8d1611 100644 --- a/contrib/libarchive/unzip/test/test_I.c +++ b/contrib/libarchive/unzip/test/test_I.c @@ -25,12 +25,25 @@ */ #include "test.h" +#ifdef HAVE_LOCALE_H +#include +#endif + /* Test I arg - file name encoding */ DEFINE_TEST(test_I) { const char *reffile = "test_I.zip"; int r; +#if HAVE_SETLOCALE + if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { + skipping("en_US.UTF-8 locale not available on this system."); + return; + } +#else + skipping("setlocale() not available on this system."); +#endif + extract_reference_file(reffile); r = systemf("%s -I UTF-8 %s >test.out 2>test.err", testprog, reffile); assertEqualInt(0, r); diff --git a/lib/libarchive/tests/Makefile b/lib/libarchive/tests/Makefile index e14b37621e5c..dc3767c319c3 100644 --- a/lib/libarchive/tests/Makefile +++ b/lib/libarchive/tests/Makefile @@ -188,6 +188,7 @@ TESTS_SRCS= \ test_read_format_ustar_filename.c \ test_read_format_warc.c \ test_read_format_xar.c \ + test_read_format_xar_doublelink.c \ test_read_format_zip.c \ test_read_format_zip_7075_utf8_paths.c \ test_read_format_zip_comment_stored.c \ @@ -611,6 +612,7 @@ ${PACKAGE}FILES+= test_read_format_ustar_filename_cp866.tar.Z.uu ${PACKAGE}FILES+= test_read_format_ustar_filename_eucjp.tar.Z.uu ${PACKAGE}FILES+= test_read_format_ustar_filename_koi8r.tar.Z.uu ${PACKAGE}FILES+= test_read_format_warc.warc.uu +${PACKAGE}FILES+= test_read_format_xar_doublelink.xar.uu ${PACKAGE}FILES+= test_read_format_zip.zip.uu ${PACKAGE}FILES+= test_read_format_zip_7075_utf8_paths.zip.uu ${PACKAGE}FILES+= test_read_format_zip_7z_deflate.zip.uu @@ -679,6 +681,7 @@ ${PACKAGE}FILES+= test_splitted_rar_seek_support_aa.uu ${PACKAGE}FILES+= test_splitted_rar_seek_support_ab.uu ${PACKAGE}FILES+= test_splitted_rar_seek_support_ac.uu ${PACKAGE}FILES+= test_write_disk_appledouble.cpio.gz.uu +${PACKAGE}FILES+= test_write_disk_appledouble_zip.zip.uu ${PACKAGE}FILES+= test_write_disk_hfs_compression.tgz.uu ${PACKAGE}FILES+= test_write_disk_mac_metadata.tar.gz.uu ${PACKAGE}FILES+= test_write_disk_no_hfs_compression.tgz.uu -- cgit v1.2.3