diff options
| author | Martin Matuska <mm@FreeBSD.org> | 2026-04-13 13:22:49 +0000 |
|---|---|---|
| committer | Martin Matuska <mm@FreeBSD.org> | 2026-04-13 13:29:20 +0000 |
| commit | f2cd95a372000681bafe284df6ba857d5c2541c2 (patch) | |
| tree | 750d581c1606b7a02f4a8cbdb2485219b7f44215 | |
| parent | 01333e8c4dd7b5e2bb90cc773332613cf085ccf4 (diff) | |
108 files changed, 3063 insertions, 401 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 523d9cb61fac..3c99d430a348 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -5,26 +5,21 @@ env: FreeBSD_task: matrix: - env: - BS: autotools - env: - BS: cmake - matrix: - - name: 15.0-STABLE (UFS) - freebsd_instance: - image_family: freebsd-15-0-amd64-ufs-snap - - name: 15.0-RELEASE (UFS) + - name: 15.0-RELEASE (UFS) cmake freebsd_instance: image_family: freebsd-15-0-amd64-ufs + env: + BS: cmake - name: 15.0-RELEASE (ZFS) freebsd_instance: image_family: freebsd-15-0-amd64-zfs + env: + BS: autotools - name: 14.3-RELEASE freebsd_instance: image_family: freebsd-14-3 - - name: 13.5-RELEASE - freebsd_instance: - image_family: freebsd-13-5 + env: + BS: cmake prepare_script: - ./build/ci/cirrus_ci/ci.sh prepare configure_script: diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ab6291332fb..4d9c5ccfe5b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -747,6 +747,7 @@ LA_CHECK_INCLUDE_FILE("signal.h" HAVE_SIGNAL_H) LA_CHECK_INCLUDE_FILE("spawn.h" HAVE_SPAWN_H) LA_CHECK_INCLUDE_FILE("stdarg.h" HAVE_STDARG_H) LA_CHECK_INCLUDE_FILE("stdint.h" HAVE_STDINT_H) +LA_CHECK_INCLUDE_FILE("stdio.h" HAVE_STDIO_H) LA_CHECK_INCLUDE_FILE("stdlib.h" HAVE_STDLIB_H) LA_CHECK_INCLUDE_FILE("string.h" HAVE_STRING_H) LA_CHECK_INCLUDE_FILE("strings.h" HAVE_STRINGS_H) diff --git a/Makefile.am b/Makefile.am index a3b04e75a04f..c34e8da922d2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -475,6 +475,7 @@ libarchive_test_SOURCES= \ libarchive/test/test_read_format_ar.c \ libarchive/test/test_read_format_cab.c \ libarchive/test/test_read_format_cab_filename.c \ + libarchive/test/test_read_format_cab_lzx_oob.c \ libarchive/test/test_read_format_cpio_afio.c \ libarchive/test/test_read_format_cpio_bin.c \ libarchive/test/test_read_format_cpio_bin_Z.c \ @@ -512,10 +513,12 @@ libarchive_test_SOURCES= \ libarchive/test/test_read_format_isorr_new_bz2.c \ libarchive/test/test_read_format_isorr_rr_moved.c \ libarchive/test/test_read_format_isozisofs_bz2.c \ + libarchive/test/test_read_format_iso_zisofs_overflow.c \ libarchive/test/test_read_format_lha.c \ libarchive/test/test_read_format_lha_bugfix_0.c \ libarchive/test/test_read_format_lha_filename.c \ libarchive/test/test_read_format_lha_filename_utf16.c \ + libarchive/test/test_read_format_lha_oversize_header.c \ libarchive/test/test_read_format_mtree.c \ libarchive/test/test_read_format_mtree_crash747.c \ libarchive/test/test_read_format_pax_bz2.c \ @@ -528,6 +531,7 @@ libarchive_test_SOURCES= \ libarchive/test/test_read_format_rar_invalid1.c \ libarchive/test/test_read_format_rar_overflow.c \ libarchive/test/test_read_format_rar5.c \ + libarchive/test/test_read_format_rar5_loop_bug.c \ libarchive/test/test_read_format_raw.c \ libarchive/test/test_read_format_tar.c \ libarchive/test/test_read_format_tar_V_negative_size.c \ @@ -588,6 +592,7 @@ libarchive_test_SOURCES= \ libarchive/test/test_tar_large.c \ libarchive/test/test_ustar_filenames.c \ libarchive/test/test_ustar_filename_encoding.c \ + libarchive/test/test_v7tar_filename_encoding.c \ libarchive/test/test_warn_missing_hardlink_target.c \ libarchive/test/test_write_disk.c \ libarchive/test/test_write_disk_appledouble.c \ @@ -829,9 +834,11 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_7zip_lzma2_sparc.7z.uu \ libarchive/test/test_read_format_7zip_malformed.7z.uu \ libarchive/test/test_read_format_7zip_malformed2.7z.uu \ + libarchive/test/test_read_format_7zip_malformed3.7z.uu \ libarchive/test/test_read_format_7zip_packinfo_digests.7z.uu \ libarchive/test/test_read_format_7zip_ppmd.7z.uu \ libarchive/test/test_read_format_7zip_sfx_elf.elf.uu \ + libarchive/test/test_read_format_7zip_sfx_elf64trunc.elf.uu \ libarchive/test/test_read_format_7zip_sfx_modified_pe.exe.uu \ libarchive/test/test_read_format_7zip_sfx_pe.exe.uu \ libarchive/test/test_read_format_7zip_solid_zstd.7z.uu \ @@ -847,6 +854,7 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_cab_2.cab.uu \ libarchive/test/test_read_format_cab_3.cab.uu \ libarchive/test/test_read_format_cab_filename_cp932.cab.uu \ + libarchive/test/test_read_format_cab_lzx_oob.cab.uu \ libarchive/test/test_read_format_cpio_bin_be.cpio.uu \ libarchive/test/test_read_format_cpio_bin_le.cpio.uu \ libarchive/test/test_read_format_cpio_filename_cp866.cpio.uu \ @@ -883,6 +891,7 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_iso_rockridge_rr_moved.iso.Z.uu \ libarchive/test/test_read_format_iso_xorriso.iso.Z.uu \ libarchive/test/test_read_format_iso_zisofs.iso.Z.uu \ + libarchive/test/test_read_format_iso_zisofs_overflow.iso.uu \ libarchive/test/test_read_format_lha_bugfix_0.lzh.uu \ libarchive/test/test_read_format_lha_filename_cp932.lzh.uu \ libarchive/test/test_read_format_lha_filename_utf16.lzh.uu \ @@ -893,6 +902,7 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_lha_lh0.lzh.uu \ libarchive/test/test_read_format_lha_lh6.lzh.uu \ libarchive/test/test_read_format_lha_lh7.lzh.uu \ + libarchive/test/test_read_format_lha_oversize_header.lzh.uu \ libarchive/test/test_read_format_lha_withjunk.lzh.uu \ libarchive/test/test_read_format_mtree.mtree.uu \ libarchive/test/test_read_format_mtree_nomagic.mtree.uu \ @@ -947,6 +957,7 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_rar5_invalid_dict_reference.rar.uu \ libarchive/test/test_read_format_rar5_leftshift1.rar.uu \ libarchive/test/test_read_format_rar5_leftshift2.rar.uu \ + libarchive/test/test_read_format_rar5_loop_bug.rar.uu \ libarchive/test/test_read_format_rar5_multiarchive.part01.rar.uu \ libarchive/test/test_read_format_rar5_multiarchive.part02.rar.uu \ libarchive/test/test_read_format_rar5_multiarchive.part03.rar.uu \ @@ -1083,11 +1094,13 @@ libarchive_test_EXTRA_DIST=\ # noinst_HEADERS+= \ libarchive_fe/lafe_err.h \ + libarchive_fe/lafe_getline.h \ libarchive_fe/lafe_platform.h \ libarchive_fe/line_reader.h \ libarchive_fe/passphrase.h libarchive_fe_la_SOURCES= \ libarchive_fe/lafe_err.c \ + libarchive_fe/lafe_getline.c \ libarchive_fe/line_reader.c \ libarchive_fe/passphrase.c @@ -1551,12 +1564,10 @@ bsdcat_test_EXTRA_DIST= \ noinst_HEADERS+= \ unzip/bsdunzip.h \ unzip/bsdunzip_platform.h \ - unzip/la_getline.h \ unzip/la_queue.h bsdunzip_SOURCES= \ unzip/bsdunzip.c \ - unzip/cmdline.c \ - unzip/la_getline.c + unzip/cmdline.c if INC_WINDOWS_FILES noinst_HEADERS+= @@ -1,3 +1,7 @@ +Apr 13, 2026: libarchive 3.8.7 released + +Mar 10, 2026: libarchive 3.8.6 released + Jan 05, 2026: libarchive 3.8.5 released Dec 01, 2025: libarchive 3.8.4 released diff --git a/README.md b/README.md index e9691f1b710b..3009e1b54d18 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,13 @@ The top-level directory contains the following information files: * **CMakeLists.txt** - input for "cmake" build tool, see INSTALL * **configure** - configuration script, see INSTALL for details. If your copy of the source lacks a `configure` script, you can try to construct it by running the script in `build/autogen.sh` (or use `cmake`). -The following files in the top-level directory are used by the 'configure' script: +The following files in the top-level directory are related to the 'configure' script and are only needed by maintainers: -* `Makefile.am`, `aclocal.m4`, `configure.ac` - used to build this distribution, only needed by maintainers -* `Makefile.in`, `config.h.in` - templates used by configure script +* `configure.ac` - used (by autoconf) to build the configure script and related files +* `Makefile.am` - used (by automake) to generate Makefile.in +* `aclocal.m4` - auto-generated file (created by aclocal) used to build the configure script +* `Makefile.in` - auto-generated template (created by automake) used by the configure script to create Makefile +* `config.h.in` - auto-generated template (created by autoheader) used by the configure script to create config.h ## Documentation diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in index 06f66b4378c1..97ff59476720 100644 --- a/build/cmake/config.h.in +++ b/build/cmake/config.h.in @@ -642,6 +642,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the `getea' function. */ #cmakedefine HAVE_GETEA 1 +/* Define to 1 if you have the `getegid' function. */ +#cmakedefine HAVE_GETEGID 1 + /* Define to 1 if you have the `geteuid' function. */ #cmakedefine HAVE_GETEUID 1 @@ -1025,6 +1028,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the <stdint.h> header file. */ #cmakedefine HAVE_STDINT_H 1 +/* Define to 1 if you have the <stdio.h> header file. */ +#cmakedefine HAVE_STDIO_H 1 + /* Define to 1 if you have the <stdlib.h> header file. */ #cmakedefine HAVE_STDLIB_H 1 diff --git a/build/version b/build/version index 3f78540c6288..99c36462af96 100644 --- a/build/version +++ b/build/version @@ -1 +1 @@ -3008005 +3008007 diff --git a/configure.ac b/configure.ac index b60b886e62d5..84fe33fd8a9d 100644 --- a/configure.ac +++ b/configure.ac @@ -4,8 +4,8 @@ dnl First, define all of the version numbers up front. dnl In particular, this allows the version macro to be used in AC_INIT dnl These first two version numbers are updated automatically on each release. -m4_define([LIBARCHIVE_VERSION_S],[3.8.5]) -m4_define([LIBARCHIVE_VERSION_N],[3008005]) +m4_define([LIBARCHIVE_VERSION_S],[3.8.7]) +m4_define([LIBARCHIVE_VERSION_N],[3008007]) dnl bsdtar and bsdcpio versioning tracks libarchive m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S()) diff --git a/contrib/android/Android.mk b/contrib/android/Android.mk index 20e46a699643..1fdd2bf7cf35 100644 --- a/contrib/android/Android.mk +++ b/contrib/android/Android.mk @@ -159,6 +159,7 @@ libarchive_host_src_files := endif libarchive_fe_src_files := libarchive_fe/lafe_err.c \ + libarchive_fe/lafe_getline.c \ libarchive_fe/line_reader.c \ libarchive_fe/passphrase.c diff --git a/contrib/oss-fuzz/libarchive_linkify_fuzzer.cc b/contrib/oss-fuzz/libarchive_linkify_fuzzer.cc index 64c22dca959c..c8d05a2b934b 100644 --- a/contrib/oss-fuzz/libarchive_linkify_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_linkify_fuzzer.cc @@ -76,14 +76,19 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { // This is the main function we want to fuzz (zero coverage) archive_entry_linkify(resolver, &entry, &spare); - // entry and spare may be modified by linkify - // We still need to free the original entries we allocated + // Update entries[i] to reflect ownership changes from linkify. + // If linkify cached the entry internally, entry is now NULL and the + // resolver owns the object. If linkify swapped it with a previously + // cached entry, entry points to that other object. + entries[i] = entry; + + // Free any entry returned via spare (complete hardlink pair) if (spare != NULL) { archive_entry_free(spare); } } - // Free remaining entries from the resolver + // Free remaining entries from the resolver (drain loop) struct archive_entry *entry = NULL; struct archive_entry *spare = NULL; while (1) { @@ -98,7 +103,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { } } - // Free all our created entries + // Free all our created entries that were NOT consumed by the resolver for (int i = 0; i < num_entries; i++) { if (entries[i] != NULL) { archive_entry_free(entries[i]); diff --git a/contrib/untar.c b/contrib/untar.c index 6d5e88e2f097..0d862b8a8e0a 100644 --- a/contrib/untar.c +++ b/contrib/untar.c @@ -60,11 +60,11 @@ parseoct(const char *p, size_t n) { unsigned long i = 0; - while ((*p < '0' || *p > '7') && n > 0) { + while (n > 0 && (*p < '0' || *p > '7')) { ++p; --n; } - while (*p >= '0' && *p <= '7' && n > 0) { + while (n > 0 && *p >= '0' && *p <= '7') { i *= 8; i += *p - '0'; ++p; diff --git a/cpio/CMakeLists.txt b/cpio/CMakeLists.txt index 7678ed658ae7..683f542d70f2 100644 --- a/cpio/CMakeLists.txt +++ b/cpio/CMakeLists.txt @@ -15,6 +15,8 @@ IF(ENABLE_CPIO) cpio_platform.h ../libarchive_fe/lafe_err.c ../libarchive_fe/lafe_err.h + ../libarchive_fe/lafe_getline.c + ../libarchive_fe/lafe_getline.h ../libarchive_fe/lafe_platform.h ../libarchive_fe/line_reader.c ../libarchive_fe/line_reader.h diff --git a/cpio/cmdline.c b/cpio/cmdline.c index db06c03c011d..a3d029c65161 100644 --- a/cpio/cmdline.c +++ b/cpio/cmdline.c @@ -11,6 +11,9 @@ #ifdef HAVE_ERRNO_H #include <errno.h> #endif +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif #ifdef HAVE_GRP_H #include <grp.h> #endif @@ -347,9 +350,10 @@ owner_parse(const char *spec, struct cpio_owner *owner, const char **errmsg) owner->gid = pwent->pw_gid; } else { char *end; + unsigned long val; errno = 0; - owner->uid = (int)strtoul(user, &end, 10); - if (errno || *end != '\0') { + val = strtoul(user, &end, 10); + if (errno || *end != '\0' || val > (unsigned)INT_MAX) { snprintf(errbuff, sizeof(errbuff), "Couldn't lookup user ``%s''", user); errbuff[sizeof(errbuff) - 1] = '\0'; @@ -357,6 +361,7 @@ owner_parse(const char *spec, struct cpio_owner *owner, const char **errmsg) *errmsg = errbuff; return (-1); } + owner->uid = (int)val; } free(user); } @@ -373,15 +378,17 @@ owner_parse(const char *spec, struct cpio_owner *owner, const char **errmsg) } } else { char *end; + unsigned long val; errno = 0; - owner->gid = (int)strtoul(g, &end, 10); - if (errno || *end != '\0') { + val = strtoul(g, &end, 10); + if (errno || *end != '\0' || val > (unsigned)INT_MAX) { snprintf(errbuff, sizeof(errbuff), "Couldn't lookup group ``%s''", g); errbuff[sizeof(errbuff) - 1] = '\0'; *errmsg = errbuff; return (-1); } + owner->gid = (int)val; } } return (0); diff --git a/cpio/cpio.c b/cpio/cpio.c index 77eefe809f37..6e6c2c3356c0 100644 --- a/cpio/cpio.c +++ b/cpio/cpio.c @@ -8,6 +8,8 @@ #include "cpio_platform.h" +#include "lafe_getline.h" + #include <sys/types.h> #include <archive.h> #include <archive_entry.h> @@ -33,6 +35,9 @@ #ifdef HAVE_LOCALE_H #include <locale.h> #endif +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif #ifdef HAVE_PWD_H #include <pwd.h> #endif @@ -83,7 +88,7 @@ struct name_cache { static int extract_data(struct archive *, struct archive *); const char * cpio_i64toa(int64_t); -static const char *cpio_rename(const char *name); +static void cpio_rename(struct archive_entry *); static int entry_to_archive(struct cpio *, struct archive_entry *); static int file_to_archive(struct cpio *, const char *); static void free_cache(struct name_cache *cache); @@ -110,19 +115,16 @@ static void passphrase_free(char *); int main(int argc, char *argv[]) { - static char buff[16384]; struct cpio _cpio; /* Allocated on stack. */ struct cpio *cpio; struct cpio_owner owner; const char *errmsg; char *tptr; - int opt, t; + int opt; + long t; cpio = &_cpio; memset(cpio, 0, sizeof(*cpio)); - cpio->buff = buff; - cpio->buff_size = sizeof(buff); - #if defined(HAVE_SIGACTION) { @@ -204,13 +206,13 @@ main(int argc, char *argv[]) case 'C': /* NetBSD/OpenBSD */ errno = 0; tptr = NULL; - t = (int)strtol(cpio->argument, &tptr, 10); - if (errno || t <= 0 || *(cpio->argument) == '\0' || + t = strtol(cpio->argument, &tptr, 10); + if (errno || t <= 0 || t > INT_MAX || *(cpio->argument) == '\0' || tptr == NULL || *tptr != '\0') { lafe_errc(1, 0, "Invalid blocksize: %s", cpio->argument); } - cpio->bytes_per_block = t; + cpio->bytes_per_block = (int)t; break; case 'c': /* POSIX 1997 */ cpio->format = "odc"; @@ -222,7 +224,7 @@ main(int argc, char *argv[]) if (archive_match_include_pattern_from_file( cpio->matching, cpio->argument, cpio->option_null) != ARCHIVE_OK) - lafe_errc(1, 0, "Error : %s", + lafe_errc(1, 0, "%s", archive_error_string(cpio->matching)); break; case 'F': /* NetBSD/OpenBSD/GNU cpio */ @@ -231,7 +233,7 @@ main(int argc, char *argv[]) case 'f': /* POSIX 1997 */ if (archive_match_exclude_pattern(cpio->matching, cpio->argument) != ARCHIVE_OK) - lafe_errc(1, 0, "Error : %s", + lafe_errc(1, 0, "%s", archive_error_string(cpio->matching)); break; case OPTION_GRZIP: @@ -247,7 +249,7 @@ main(int argc, char *argv[]) cpio->filename = cpio->argument; break; case 'i': /* POSIX 1997 */ - if (cpio->mode != '\0') + if (cpio->mode != '\0' && cpio->mode != opt) lafe_errc(1, 0, "Cannot use both -i and -%c", cpio->mode); cpio->mode = opt; @@ -289,13 +291,13 @@ main(int argc, char *argv[]) cpio->filename = cpio->argument; break; case 'o': /* POSIX 1997 */ - if (cpio->mode != '\0') + if (cpio->mode != '\0' && cpio->mode != opt) lafe_errc(1, 0, "Cannot use both -o and -%c", cpio->mode); cpio->mode = opt; break; case 'p': /* POSIX 1997 */ - if (cpio->mode != '\0') + if (cpio->mode != '\0' && cpio->mode != opt) lafe_errc(1, 0, "Cannot use both -p and -%c", cpio->mode); cpio->mode = opt; @@ -316,17 +318,21 @@ main(int argc, char *argv[]) if (owner_parse(cpio->argument, &owner, &errmsg) != 0) { if (!errmsg) errmsg = "Error parsing owner"; - lafe_warnc(-1, "%s", errmsg); + lafe_warnc(0, "%s", errmsg); usage(); } if (owner.uid != -1) cpio->uid_override = owner.uid; - if (owner.uname != NULL) + if (owner.uname != NULL) { + free(cpio->uname_override); cpio->uname_override = owner.uname; + } if (owner.gid != -1) cpio->gid_override = owner.gid; - if (owner.gname != NULL) + if (owner.gname != NULL) { + free(cpio->gname_override); cpio->gname_override = owner.gname; + } break; case 'r': /* POSIX 1997 */ cpio->option_rename = 1; @@ -409,7 +415,7 @@ main(int argc, char *argv[]) while (*cpio->argv != NULL) { if (archive_match_include_pattern(cpio->matching, *cpio->argv) != ARCHIVE_OK) - lafe_errc(1, 0, "Error : %s", + lafe_errc(1, 0, "%s", archive_error_string(cpio->matching)); --cpio->argc; ++cpio->argv; @@ -427,7 +433,7 @@ main(int argc, char *argv[]) break; default: lafe_errc(1, 0, - "Must specify at least one of -i, -o, or -p"); + "Must specify one of -i, -o, or -p"); } archive_match_free(cpio->matching); @@ -524,7 +530,7 @@ mode_out(struct cpio *cpio) int r; if (cpio->option_append) - lafe_errc(1, 0, "Append mode not yet supported."); + lafe_errc(1, 0, "Append mode not yet supported"); cpio->archive_read_disk = archive_read_disk_new(); if (cpio->archive_read_disk == NULL) @@ -638,7 +644,7 @@ mode_out(struct cpio *cpio) int64_t blocks = (archive_filter_bytes(cpio->archive, 0) + 511) / 512; - fprintf(stderr, "%lu %s\n", (unsigned long)blocks, + fprintf(stderr, "%lld %s\n", (long long)blocks, blocks == 1 ? "block" : "blocks"); } archive_write_free(cpio->archive); @@ -696,7 +702,6 @@ remove_leading_slash(const char *p) static int file_to_archive(struct cpio *cpio, const char *srcpath) { - const char *destpath; struct archive_entry *entry, *spare; size_t len; int r; @@ -738,7 +743,6 @@ file_to_archive(struct cpio *cpio, const char *srcpath) * pass mode or the name that will go into the archive in * output mode. */ - destpath = srcpath; if (cpio->destdir) { len = cpio->destdir_len + strlen(srcpath) + 8; if (len >= cpio->pass_destpath_alloc) { @@ -754,15 +758,17 @@ file_to_archive(struct cpio *cpio, const char *srcpath) } strcpy(cpio->pass_destpath, cpio->destdir); strcat(cpio->pass_destpath, remove_leading_slash(srcpath)); - destpath = cpio->pass_destpath; + archive_entry_set_pathname(entry, cpio->pass_destpath); + } else { + archive_entry_set_pathname(entry, srcpath); } if (cpio->option_rename) - destpath = cpio_rename(destpath); - if (destpath == NULL) { + cpio_rename(entry); + + if (archive_entry_pathname(entry) == NULL) { archive_entry_free(entry); return (0); } - archive_entry_copy_pathname(entry, destpath); /* * If we're trying to preserve hardlinks, match them here. @@ -791,7 +797,6 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry) const char *destpath = archive_entry_pathname(entry); const char *srcpath = archive_entry_sourcepath(entry); int fd = -1; - ssize_t bytes_read; int r; /* Print out the destination name to the user. */ @@ -869,21 +874,23 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry) exit(1); if (r >= ARCHIVE_WARN && archive_entry_size(entry) > 0 && fd >= 0) { - bytes_read = read(fd, cpio->buff, (unsigned)cpio->buff_size); + static char buff[16384]; + ssize_t bytes_read; + + bytes_read = read(fd, buff, sizeof(buff)); while (bytes_read > 0) { ssize_t bytes_write; bytes_write = archive_write_data(cpio->archive, - cpio->buff, bytes_read); + buff, bytes_read); if (bytes_write < 0) lafe_errc(1, archive_errno(cpio->archive), "%s", archive_error_string(cpio->archive)); if (bytes_write < bytes_read) { lafe_warnc(0, "Truncated write; file may have " - "grown while being archived."); + "grown while being archived"); } - bytes_read = read(fd, cpio->buff, - (unsigned)cpio->buff_size); + bytes_read = read(fd, buff, sizeof(buff)); } } @@ -997,11 +1004,9 @@ mode_in(struct cpio *cpio) } if (archive_match_path_excluded(cpio->matching, entry)) continue; - if (cpio->option_rename) { - destpath = cpio_rename(archive_entry_pathname(entry)); - archive_entry_set_pathname(entry, destpath); - } else - destpath = archive_entry_pathname(entry); + if (cpio->option_rename) + cpio_rename(entry); + destpath = archive_entry_pathname(entry); if (destpath == NULL) continue; if (cpio->verbose) @@ -1040,7 +1045,7 @@ mode_in(struct cpio *cpio) if (!cpio->quiet) { int64_t blocks = (archive_filter_bytes(a, 0) + 511) / 512; - fprintf(stderr, "%lu %s\n", (unsigned long)blocks, + fprintf(stderr, "%lld %s\n", (long long)blocks, blocks == 1 ? "block" : "blocks"); } archive_read_free(a); @@ -1125,7 +1130,7 @@ mode_list(struct cpio *cpio) if (!cpio->quiet) { int64_t blocks = (archive_filter_bytes(a, 0) + 511) / 512; - fprintf(stderr, "%lu %s\n", (unsigned long)blocks, + fprintf(stderr, "%lld %s\n", (long long)blocks, blocks == 1 ? "block" : "blocks"); } archive_read_free(a); @@ -1292,54 +1297,60 @@ mode_pass(struct cpio *cpio, const char *destdir) * that an input of '.' means the name should be unchanged. GNU cpio * treats '.' as a literal new name. */ -static const char * -cpio_rename(const char *name) +void +cpio_rename(struct archive_entry *entry) { - static char buff[1024]; + char *buff = NULL, *p, *ret = NULL; FILE *t; - char *p, *ret; + size_t n = 0; + ssize_t r; #if defined(_WIN32) && !defined(__CYGWIN__) FILE *to; t = fopen("CONIN$", "r"); if (t == NULL) - return (name); + return; to = fopen("CONOUT$", "w"); if (to == NULL) { fclose(t); - return (name); + return; } - fprintf(to, "%s (Enter/./(new name))? ", name); + fprintf(to, "%s (Enter/./(new name))? ", archive_entry_pathname(entry)); fclose(to); #else t = fopen("/dev/tty", "r+"); if (t == NULL) - return (name); - fprintf(t, "%s (Enter/./(new name))? ", name); + return; + fprintf(t, "%s (Enter/./(new name))? ", archive_entry_pathname(entry)); fflush(t); #endif - p = fgets(buff, sizeof(buff), t); + r = getline(&buff, &n, t); fclose(t); - if (p == NULL) + if (r < 1) /* End-of-file is a blank line. */ - return (NULL); + goto done; + p = buff; while (*p == ' ' || *p == '\t') ++p; if (*p == '\n' || *p == '\0') /* Empty line. */ - return (NULL); - if (*p == '.' && p[1] == '\n') + goto done; + if (*p == '.' && p[1] == '\n') { /* Single period preserves original name. */ - return (name); + free(buff); + return; + } ret = p; /* Trim the final newline. */ while (*p != '\0' && *p != '\n') ++p; /* Overwrite the final \n with a null character. */ *p = '\0'; - return (ret); +done: + archive_entry_set_pathname(entry, ret); + free(buff); } static void diff --git a/cpio/cpio.h b/cpio/cpio.h index 9bc631b544fe..2621a4c3dda3 100644 --- a/cpio/cpio.h +++ b/cpio/cpio.h @@ -71,8 +71,6 @@ struct cpio { /* Work data. */ struct archive *matching; - char *buff; - size_t buff_size; char *ppbuff; }; diff --git a/cpio/test/test_format_newc.c b/cpio/test/test_format_newc.c index 33aa16d07a81..9d4e4e9fb674 100644 --- a/cpio/test/test_format_newc.c +++ b/cpio/test/test_format_newc.c @@ -6,6 +6,13 @@ */ #include "test.h" +#ifdef HAVE_GETEUID +#define getuid() geteuid() +#endif +#ifdef HAVE_GETEGID +#define getgid() getegid() +#endif + /* Number of bytes needed to pad 'n' to multiple of 'block', assuming * that 'block' is a power of two. This trick can be more easily * remembered as -n & (block - 1), but many compilers quite reasonably diff --git a/libarchive/archive.h b/libarchive/archive.h index a9d34beb4f5a..41a5440cac75 100644 --- a/libarchive/archive.h +++ b/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 3008005 +#define ARCHIVE_VERSION_NUMBER 3008007 #include <sys/stat.h> #include <stddef.h> /* for wchar_t */ @@ -177,7 +177,7 @@ __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_ONLY_STRING "3.8.5" +#define ARCHIVE_VERSION_ONLY_STRING "3.8.7" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); diff --git a/libarchive/archive_acl.c b/libarchive/archive_acl.c index 362e3308f43f..ab601833def6 100644 --- a/libarchive/archive_acl.c +++ b/libarchive/archive_acl.c @@ -1256,8 +1256,12 @@ archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text, tag = 0; s = field[n].start; - st = field[n].start + 1; len = field[n].end - field[n].start; + if (len == 0) { + ret = ARCHIVE_WARN; + continue; + } + st = s + 1; switch (*s) { case L'u': diff --git a/libarchive/archive_check_magic.c b/libarchive/archive_check_magic.c index 6b8e0c5595f4..b6e1257949e1 100644 --- a/libarchive/archive_check_magic.c +++ b/libarchive/archive_check_magic.c @@ -148,14 +148,14 @@ __archive_check_magic(struct archive *a, unsigned int magic, if (!handle_type) { errmsg("PROGRAMMER ERROR: Function "); errmsg(function); - errmsg(" invoked with invalid archive handle.\n"); + errmsg(" invoked with invalid archive handle\n"); diediedie(); } if (a->magic != magic) { archive_set_error(a, -1, "PROGRAMMER ERROR: Function '%s' invoked" - " on '%s' archive object, which is not supported.", + " on '%s' archive object, which is not supported", function, handle_type); a->state = ARCHIVE_STATE_FATAL; diff --git a/libarchive/archive_cryptor_private.h b/libarchive/archive_cryptor_private.h index 272f2f84b9c9..1f9298ffdc46 100644 --- a/libarchive/archive_cryptor_private.h +++ b/libarchive/archive_cryptor_private.h @@ -109,6 +109,10 @@ typedef struct { #include <nettle/version.h> #define ARCHIVE_CRYPTOR_USE_NETTLE 1 +#ifndef AES_MAX_KEY_SIZE +#define AES_MAX_KEY_SIZE AES256_KEY_SIZE +#endif + typedef struct { #if NETTLE_VERSION_MAJOR < 3 struct aes_ctx ctx; diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h index b43435692c27..7122a74ed007 100644 --- a/libarchive/archive_entry.h +++ b/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 3008005 +#define ARCHIVE_VERSION_NUMBER 3008007 /* * Note: archive_entry.h is for use outside of libarchive; the diff --git a/libarchive/archive_hmac.c b/libarchive/archive_hmac.c index 210cca70744d..458092f41b29 100644 --- a/libarchive/archive_hmac.c +++ b/libarchive/archive_hmac.c @@ -198,6 +198,7 @@ static void __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) } #elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H) +#include <nettle/version.h> static int __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) @@ -216,7 +217,12 @@ __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, static void __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) { +#if NETTLE_VERSION_MAJOR < 4 hmac_sha1_digest(ctx, (unsigned)*out_len, out); +#else + hmac_sha1_digest(ctx, out); + *out_len = SHA1_DIGEST_SIZE; +#endif } static void diff --git a/libarchive/archive_options.c b/libarchive/archive_options.c index 6e2c0d2a5971..66491bd4183b 100644 --- a/libarchive/archive_options.c +++ b/libarchive/archive_options.c @@ -90,7 +90,9 @@ _archive_set_either_option(struct archive *a, const char *m, const char *o, cons if (r2 == ARCHIVE_FATAL) return (ARCHIVE_FATAL); - if (r2 == ARCHIVE_WARN - 1) + if (r1 == ARCHIVE_WARN - 1) + return r2; + if (r2 == ARCHIVE_WARN -1) return r1; return r1 > r2 ? r1 : r2; } diff --git a/libarchive/archive_pathmatch.c b/libarchive/archive_pathmatch.c index 19e0889ffe55..db0d2b791adf 100644 --- a/libarchive/archive_pathmatch.c +++ b/libarchive/archive_pathmatch.c @@ -202,7 +202,7 @@ pm(const char *p, const char *s, int flags) if (*p == '\0') return (1); while (*s) { - if (archive_pathmatch(p, s, flags)) + if (pm(p, s, flags)) return (1); ++s; } @@ -307,7 +307,7 @@ pm_w(const wchar_t *p, const wchar_t *s, int flags) if (*p == L'\0') return (1); while (*s) { - if (archive_pathmatch_w(p, s, flags)) + if (pm_w(p, s, flags)) return (1); ++s; } diff --git a/libarchive/archive_ppmd8.c b/libarchive/archive_ppmd8.c index 30196d64a9f5..04b1c0c3e165 100644 --- a/libarchive/archive_ppmd8.c +++ b/libarchive/archive_ppmd8.c @@ -61,7 +61,7 @@ typedef struct CPpmd8_Node_ #define EMPTY_NODE 0xFFFFFFFF -void Ppmd8_Construct(CPpmd8 *p) +static void Ppmd8_Construct(CPpmd8 *p) { unsigned i, k, m; @@ -89,14 +89,14 @@ void Ppmd8_Construct(CPpmd8 *p) } } -void Ppmd8_Free(CPpmd8 *p) +static void Ppmd8_Free(CPpmd8 *p) { free(p->Base); p->Size = 0; p->Base = 0; } -Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size) +static Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size) { if (p->Base == 0 || p->Size != size) { @@ -407,7 +407,7 @@ static void RestartModel(CPpmd8 *p) } } -void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod) +static void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod) { p->MaxOrder = maxOrder; p->RestoreMethod = restoreMethod; @@ -1042,7 +1042,7 @@ static void Rescale(CPpmd8 *p) p->FoundState = STATS(p->MinContext); } -CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked1, UInt32 *escFreq) +static CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked1, UInt32 *escFreq) { CPpmd_See *see; if (p->MinContext->NumStats != 0xFF) @@ -1078,7 +1078,7 @@ static void NextContext(CPpmd8 *p) } } -void Ppmd8_Update1(CPpmd8 *p) +static void Ppmd8_Update1(CPpmd8 *p) { CPpmd_State *s = p->FoundState; s->Freq += 4; @@ -1093,7 +1093,7 @@ void Ppmd8_Update1(CPpmd8 *p) NextContext(p); } -void Ppmd8_Update1_0(CPpmd8 *p) +static void Ppmd8_Update1_0(CPpmd8 *p) { p->PrevSuccess = (2 * p->FoundState->Freq >= p->MinContext->SummFreq); p->RunLength += p->PrevSuccess; @@ -1103,7 +1103,7 @@ void Ppmd8_Update1_0(CPpmd8 *p) NextContext(p); } -void Ppmd8_UpdateBin(CPpmd8 *p) +static void Ppmd8_UpdateBin(CPpmd8 *p) { p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 196)); p->PrevSuccess = 1; @@ -1111,7 +1111,7 @@ void Ppmd8_UpdateBin(CPpmd8 *p) NextContext(p); } -void Ppmd8_Update2(CPpmd8 *p) +static void Ppmd8_Update2(CPpmd8 *p) { p->MinContext->SummFreq += 4; if ((p->FoundState->Freq += 4) > MAX_FREQ) @@ -1127,7 +1127,7 @@ This code is based on: PPMd var.I (2002): Dmitry Shkarin : Public domain Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ -Bool Ppmd8_RangeDec_Init(CPpmd8 *p) +static Bool Ppmd8_RangeDec_Init(CPpmd8 *p) { unsigned i; p->Low = 0; @@ -1161,7 +1161,7 @@ static void RangeDec_Decode(CPpmd8 *p, UInt32 start, UInt32 size) #define MASK(sym) ((signed char *)charMask)[sym] -int Ppmd8_DecodeSymbol(CPpmd8 *p) +static int Ppmd8_DecodeSymbol(CPpmd8 *p) { size_t charMask[256 / sizeof(size_t)]; if (p->MinContext->NumStats != 0) diff --git a/libarchive/archive_ppmd8_private.h b/libarchive/archive_ppmd8_private.h index 454b75f41f25..f0493de04623 100644 --- a/libarchive/archive_ppmd8_private.h +++ b/libarchive/archive_ppmd8_private.h @@ -83,12 +83,6 @@ typedef struct UInt16 BinSumm[25][64]; } CPpmd8; -void Ppmd8_Construct(CPpmd8 *p); -Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size); -void Ppmd8_Free(CPpmd8 *p); -void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod); -#define Ppmd8_WasAllocated(p) ((p)->Base != NULL) - /* ---------- Internal Functions ---------- */ @@ -104,30 +98,11 @@ extern const Byte PPMD8_kExpEscape[16]; #define Ppmd8_GetStats(p, ctx) ((CPpmd_State *)Ppmd8_GetPtr((p), ((ctx)->Stats))) #endif -void Ppmd8_Update1(CPpmd8 *p); -void Ppmd8_Update1_0(CPpmd8 *p); -void Ppmd8_Update2(CPpmd8 *p); -void Ppmd8_UpdateBin(CPpmd8 *p); - #define Ppmd8_GetBinSumm(p) \ &p->BinSumm[p->NS2Indx[Ppmd8Context_OneState(p->MinContext)->Freq - 1]][ \ p->NS2BSIndx[Ppmd8_GetContext(p, p->MinContext->Suffix)->NumStats] + \ p->PrevSuccess + p->MinContext->Flags + ((p->RunLength >> 26) & 0x20)] -CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked, UInt32 *scale); - - -/* ---------- Decode ---------- */ - -Bool Ppmd8_RangeDec_Init(CPpmd8 *p); -#define Ppmd8_RangeDec_IsFinishedOK(p) ((p)->Code == 0) -int Ppmd8_DecodeSymbol(CPpmd8 *p); /* returns: -1 as EndMarker, -2 as DataError */ - -/* ---------- Encode ---------- */ - -#define Ppmd8_RangeEnc_Init(p) { (p)->Low = 0; (p)->Range = 0xFFFFFFFF; } -void Ppmd8_RangeEnc_FlushData(CPpmd8 *p); -void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol); /* symbol = -1 means EndMarker */ typedef struct { diff --git a/libarchive/archive_read.c b/libarchive/archive_read.c index c9b9d5981516..e5f89bdc8772 100644 --- a/libarchive/archive_read.c +++ b/libarchive/archive_read.c @@ -171,7 +171,7 @@ static int64_t client_skip_proxy(struct archive_read_filter *self, int64_t request) { if (request < 0) - __archive_errx(1, "Negative skip requested."); + __archive_errx(1, "Negative skip requested"); if (request == 0) return 0; @@ -379,7 +379,7 @@ archive_read_set_callback_data2(struct archive *_a, void *client_data, if (a->client.dataset == NULL) { archive_set_error(&a->archive, ENOMEM, - "No memory."); + "No memory"); return ARCHIVE_FATAL; } a->client.nodes = 1; @@ -388,7 +388,7 @@ archive_read_set_callback_data2(struct archive *_a, void *client_data, if (iindex > a->client.nodes - 1) { archive_set_error(&a->archive, EINVAL, - "Invalid index specified."); + "Invalid index specified"); return ARCHIVE_FATAL; } a->client.dataset[iindex].data = client_data; @@ -409,14 +409,14 @@ archive_read_add_callback_data(struct archive *_a, void *client_data, "archive_read_add_callback_data"); if (iindex > a->client.nodes) { archive_set_error(&a->archive, EINVAL, - "Invalid index specified."); + "Invalid index specified"); return ARCHIVE_FATAL; } p = realloc(a->client.dataset, sizeof(*a->client.dataset) * (++(a->client.nodes))); if (p == NULL) { archive_set_error(&a->archive, ENOMEM, - "No memory."); + "No memory"); return ARCHIVE_FATAL; } a->client.dataset = (struct archive_read_data_node *)p; @@ -625,7 +625,7 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) r1 = archive_read_data_skip(&a->archive); if (r1 == ARCHIVE_EOF) archive_set_error(&a->archive, EIO, - "Premature end-of-file."); + "Premature end-of-file"); if (r1 == ARCHIVE_EOF || r1 == ARCHIVE_FATAL) { a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); diff --git a/libarchive/archive_read_append_filter.c b/libarchive/archive_read_append_filter.c index cd88df119906..d578b06fe714 100644 --- a/libarchive/archive_read_append_filter.c +++ b/libarchive/archive_read_append_filter.c @@ -104,6 +104,10 @@ archive_read_append_filter(struct archive *_a, int code) strcpy(str, "lrzip"); r1 = archive_read_support_filter_lrzip(_a); break; + case ARCHIVE_FILTER_GRZIP: + strcpy(str, "grzip"); + r1 = archive_read_support_filter_grzip(_a); + break; default: archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, "Invalid filter code specified"); diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c index 94fa8fef963f..a7176bdd939d 100644 --- a/libarchive/archive_read_disk_posix.c +++ b/libarchive/archive_read_disk_posix.c @@ -921,7 +921,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, r = archive_match_path_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Failed : %s", archive_error_string(a->matching)); + "%s", archive_error_string(a->matching)); return (r); } if (r) { @@ -1035,7 +1035,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, r = archive_match_time_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Failed : %s", archive_error_string(a->matching)); + "%s", archive_error_string(a->matching)); return (r); } if (r) { @@ -1061,7 +1061,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, r = archive_match_owner_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Failed : %s", archive_error_string(a->matching)); + "%s", archive_error_string(a->matching)); return (r); } if (r) { diff --git a/libarchive/archive_read_disk_windows.c b/libarchive/archive_read_disk_windows.c index 117ca505fadd..0e890497a443 100644 --- a/libarchive/archive_read_disk_windows.c +++ b/libarchive/archive_read_disk_windows.c @@ -947,7 +947,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, r = archive_match_path_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Failed : %s", archive_error_string(a->matching)); + "%s", archive_error_string(a->matching)); return (r); } if (r) { @@ -1019,7 +1019,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, r = archive_match_time_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Failed : %s", archive_error_string(a->matching)); + "%s", archive_error_string(a->matching)); return (r); } if (r) { @@ -1045,7 +1045,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, r = archive_match_owner_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Failed : %s", archive_error_string(a->matching)); + "%s", archive_error_string(a->matching)); return (r); } if (r) { diff --git a/libarchive/archive_read_open_filename.c b/libarchive/archive_read_open_filename.c index a910eefcbfd2..9ec1e6c0e808 100644 --- a/libarchive/archive_read_open_filename.c +++ b/libarchive/archive_read_open_filename.c @@ -122,13 +122,14 @@ archive_read_open_filenames(struct archive *a, const char **filenames, archive_clear_error(a); do { + size_t len; if (filename == NULL) filename = ""; - mine = calloc(1, - sizeof(*mine) + strlen(filename)); + len = strlen(filename); + mine = calloc(1, sizeof(*mine) + len); if (mine == NULL) goto no_memory; - strcpy(mine->filename.m, filename); + memcpy(mine->filename.m, filename, len + 1); mine->block_size = block_size; mine->fd = -1; mine->buffer = NULL; diff --git a/libarchive/archive_read_support_filter_grzip.c b/libarchive/archive_read_support_filter_grzip.c index 15b6757cb90c..8ec5d1f855cb 100644 --- a/libarchive/archive_read_support_filter_grzip.c +++ b/libarchive/archive_read_support_filter_grzip.c @@ -62,7 +62,7 @@ archive_read_support_filter_grzip(struct archive *_a) { struct archive_read *a = (struct archive_read *)_a; - if (__archive_read_register_bidder(a, NULL, NULL, + if (__archive_read_register_bidder(a, NULL, "grzip", &grzip_bidder_vtable) != ARCHIVE_OK) return (ARCHIVE_FATAL); diff --git a/libarchive/archive_read_support_filter_lz4.c b/libarchive/archive_read_support_filter_lz4.c index 144572ef2362..acd7f5157997 100644 --- a/libarchive/archive_read_support_filter_lz4.c +++ b/libarchive/archive_read_support_filter_lz4.c @@ -363,7 +363,7 @@ lz4_filter_read(struct archive_read_filter *self, const void **p) case READ_LEGACY_STREAM: /* Reading a lz4 stream already failed. */ archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, "Invalid sequence."); + ARCHIVE_ERRNO_MISC, "Invalid sequence"); return (ARCHIVE_FATAL); case READ_DEFAULT_BLOCK: ret = lz4_filter_read_default_stream(self, p); @@ -377,7 +377,7 @@ lz4_filter_read(struct archive_read_filter *self, const void **p) break; default: archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, "Program error."); + ARCHIVE_ERRNO_MISC, "Program error"); return (ARCHIVE_FATAL); } diff --git a/libarchive/archive_read_support_filter_lzop.c b/libarchive/archive_read_support_filter_lzop.c index b0c4bb13e8b3..12ed78c578cd 100644 --- a/libarchive/archive_read_support_filter_lzop.c +++ b/libarchive/archive_read_support_filter_lzop.c @@ -110,7 +110,7 @@ archive_read_support_filter_lzop(struct archive *_a) { struct archive_read *a = (struct archive_read *)_a; - if (__archive_read_register_bidder(a, NULL, NULL, + if (__archive_read_register_bidder(a, NULL, "lzop", &lzop_bidder_vtable) != ARCHIVE_OK) return (ARCHIVE_FATAL); diff --git a/libarchive/archive_read_support_filter_program.c b/libarchive/archive_read_support_filter_program.c index 2c8e45302d8e..9f187f852df3 100644 --- a/libarchive/archive_read_support_filter_program.c +++ b/libarchive/archive_read_support_filter_program.c @@ -149,6 +149,8 @@ archive_read_support_filter_program_signature(struct archive *_a, if (signature != NULL && signature_len > 0) { state->signature_len = signature_len; state->signature = malloc(signature_len); + if (state->signature == NULL) + goto memerr; memcpy(state->signature, signature, signature_len); } diff --git a/libarchive/archive_read_support_format_7zip.c b/libarchive/archive_read_support_format_7zip.c index 330d5515dd50..8926ac50a1ed 100644 --- a/libarchive/archive_read_support_format_7zip.c +++ b/libarchive/archive_read_support_format_7zip.c @@ -34,6 +34,9 @@ #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif #ifdef HAVE_BZLIB_H #include <bzlib.h> #endif @@ -80,7 +83,7 @@ /* * ELF format */ -#define ELF_HDR_MIN_LEN 0x3f +#define ELF_HDR_MIN_LEN 0x40 /* sizeof(Elf64_Ehdr) */ #define ELF_HDR_EI_CLASS_OFFSET 0x04 #define ELF_HDR_EI_DATA_OFFSET 0x05 @@ -855,13 +858,18 @@ find_elf_data_sec(struct archive_read *a) while (e_shnum > 0) { name_offset = (*dec32)(h + sec_tbl_offset); if (name_offset == data_sym_offset) { + uint64_t sel_offset; + if (format_64) { - min_addr = (*dec64)( + sel_offset = (*dec64)( h + sec_tbl_offset + 0x18); } else { - min_addr = (*dec32)( + sel_offset = (*dec32)( h + sec_tbl_offset + 0x10); } + if (sel_offset > SSIZE_MAX) + break; + min_addr = (ssize_t)sel_offset; break; } sec_tbl_offset += e_shentsize; @@ -967,7 +975,7 @@ archive_read_format_7zip_read_header(struct archive_read *a, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Pathname cannot be converted " - "from %s to current locale.", + "from %s to current locale", archive_string_conversion_charset_name(zip->sconv)); ret = ARCHIVE_WARN; } @@ -1573,7 +1581,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip, -15 /* Don't check for zlib header */); if (r != Z_OK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Couldn't initialize zlib stream."); + "Couldn't initialize zlib stream"); return (ARCHIVE_FAILED); } zip->stream_valid = 1; @@ -1715,7 +1723,7 @@ decompress(struct archive_read *a, struct _7zip *zip, if (bytes < 0) { archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, - "BCJ2 conversion Failed"); + "BCJ2 conversion failed"); return (ARCHIVE_FAILED); } zip->main_stream_bytes_remaining -= @@ -1769,7 +1777,7 @@ decompress(struct archive_read *a, struct _7zip *zip, default: archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, - "Decompression failed(%d)", + "Decompression failed (%d)", r); return (ARCHIVE_FAILED); } @@ -1971,7 +1979,7 @@ decompress(struct archive_read *a, struct _7zip *zip, bytes = Bcj2_Decode(zip, bcj2_next_out, bcj2_avail_out); if (bytes < 0) { archive_set_error(&(a->archive), - ARCHIVE_ERRNO_MISC, "BCJ2 conversion Failed"); + ARCHIVE_ERRNO_MISC, "BCJ2 conversion failed"); return (ARCHIVE_FAILED); } zip->main_stream_bytes_remaining -= diff --git a/libarchive/archive_read_support_format_cab.c b/libarchive/archive_read_support_format_cab.c index 63755ef9e579..bf8ac6b1ca77 100644 --- a/libarchive/archive_read_support_format_cab.c +++ b/libarchive/archive_read_support_format_cab.c @@ -383,8 +383,10 @@ archive_read_support_format_cab(struct archive *_a) NULL, NULL); - if (r != ARCHIVE_OK) + if (r != ARCHIVE_OK) { + archive_wstring_free(&cab->ws); free(cab); + } return (ARCHIVE_OK); } @@ -978,7 +980,7 @@ archive_read_format_cab_read_header(struct archive_read *a, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Pathname cannot be converted " - "from %s to current locale.", + "from %s to current locale", archive_string_conversion_charset_name(sconv)); err = ARCHIVE_WARN; } @@ -1024,7 +1026,7 @@ archive_read_format_cab_read_data(struct archive_read *a, *offset = 0; archive_clear_error(&a->archive); archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Cannot restore this file split in multivolume."); + "Cannot restore this file split in multivolume"); return (ARCHIVE_FAILED); default: break; @@ -1173,6 +1175,9 @@ cab_checksum_finish(struct archive_read *a) l = 4; if (cab->cfheader.flags & RESERVE_PRESENT) l += cab->cfheader.cfdata; + if (cfdata->memimage == NULL) { + return (ARCHIVE_FAILED); + } cfdata->sum_calculated = cab_checksum_cfdata( cfdata->memimage + CFDATA_cbData, l, cfdata->sum_calculated); if (cfdata->sum_calculated != cfdata->sum) { @@ -1360,7 +1365,7 @@ cab_read_ahead_cfdata(struct archive_read *a, ssize_t *avail) return (cab_read_ahead_cfdata_lzx(a, avail)); default: /* Unsupported compression. */ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Unsupported CAB compression : %s", + "Unsupported CAB compression: %s", cab->entry_cffolder->compname); *avail = ARCHIVE_FAILED; return (NULL); @@ -1447,7 +1452,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail) -15 /* Don't check for zlib header */); if (r != Z_OK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Can't initialize deflate decompression."); + "Can't initialize deflate decompression"); *avail = ARCHIVE_FATAL; return (NULL); } @@ -1667,7 +1672,7 @@ cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail) cab->entry_cffolder->compdata); if (r != ARCHIVE_OK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Can't initialize LZX decompression."); + "Can't initialize LZX decompression"); *avail = ARCHIVE_FATAL; return (NULL); } @@ -1685,6 +1690,13 @@ cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail) cab->uncompressed_buffer + cab->xstrm.total_out; cab->xstrm.avail_out = cfdata->uncompressed_size - cab->xstrm.total_out; + + if ((size_t)cfdata->uncompressed_size > cab->uncompressed_buffer_size) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid CFDATA uncompressed size"); + *avail = ARCHIVE_FATAL; + return (NULL); + } d = __archive_read_ahead(a, 1, &bytes_avail); if (d == NULL) { diff --git a/libarchive/archive_read_support_format_cpio.c b/libarchive/archive_read_support_format_cpio.c index 526096b39f75..43169f61806d 100644 --- a/libarchive/archive_read_support_format_cpio.c +++ b/libarchive/archive_read_support_format_cpio.c @@ -397,7 +397,7 @@ archive_read_format_cpio_read_header(struct archive_read *a, return (ARCHIVE_FATAL); } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Pathname can't be converted from %s to current locale.", + "Pathname can't be converted from %s to current locale", archive_string_conversion_charset_name(sconv)); r = ARCHIVE_WARN; } @@ -426,7 +426,7 @@ archive_read_format_cpio_read_header(struct archive_read *a, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Linkname can't be converted from %s to " - "current locale.", + "current locale", archive_string_conversion_charset_name(sconv)); r = ARCHIVE_WARN; } diff --git a/libarchive/archive_read_support_format_iso9660.c b/libarchive/archive_read_support_format_iso9660.c index 1635228d5071..c69fcd272bcd 100644 --- a/libarchive/archive_read_support_format_iso9660.c +++ b/libarchive/archive_read_support_format_iso9660.c @@ -1322,7 +1322,7 @@ archive_read_format_iso9660_read_header(struct archive_read *a, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Pathname cannot be converted " - "from %s to current locale.", + "from %s to current locale", archive_string_conversion_charset_name( iso9660->sconv_utf16be)); @@ -1400,7 +1400,7 @@ archive_read_format_iso9660_read_header(struct archive_read *a, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Linkname cannot be converted " - "from %s to current locale.", + "from %s to current locale", archive_string_conversion_charset_name( iso9660->sconv_utf16be)); rd_r = ARCHIVE_WARN; @@ -1663,7 +1663,7 @@ zisofs_read_data(struct archive_read *a, r = inflateInit(&zisofs->stream); if (r != Z_OK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Can't initialize zisofs decompression."); + "Can't initialize zisofs decompression"); return (ARCHIVE_FATAL); } zisofs->stream_valid = 1; @@ -1728,7 +1728,7 @@ zisofs_read_data(struct archive_read *a, (void)size;/* UNUSED */ (void)offset;/* UNUSED */ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "zisofs is not supported on this platform."); + "zisofs is not supported on this platform"); return (ARCHIVE_FAILED); } @@ -2756,11 +2756,19 @@ parse_rockridge_ZF1(struct file_info *file, const unsigned char *data, { if (data[0] == 0x70 && data[1] == 0x7a && data_length == 12) { - /* paged zlib */ - file->pz = 1; - file->pz_log2_bs = data[3]; - file->pz_uncompressed_size = archive_le32dec(&data[4]); - } + /* paged zlib */ + file->pz = 1; + file->pz_log2_bs = data[3]; + if (file->pz_log2_bs < 15 || file->pz_log2_bs > 17) { + /* TODO: Return an error here instead of silently + * disabling zisofs. That requires propagating an + * error return through parse_rockridge() and its + * callers. */ + file->pz = 0; + return; + } + file->pz_uncompressed_size = archive_le32dec(&data[4]); + } } static void diff --git a/libarchive/archive_read_support_format_lha.c b/libarchive/archive_read_support_format_lha.c index cf6a147abda6..ff6dbb8df1cd 100644 --- a/libarchive/archive_read_support_format_lha.c +++ b/libarchive/archive_read_support_format_lha.c @@ -613,7 +613,7 @@ archive_read_format_lha_read_header(struct archive_read *a, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Pathname cannot be converted " - "from %s to Unicode.", + "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)) @@ -634,7 +634,7 @@ archive_read_format_lha_read_header(struct archive_read *a, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Pathname cannot be converted " - "from %s to Unicode.", + "from %s to Unicode", archive_string_conversion_charset_name(lha->sconv_fname)); err = ARCHIVE_FATAL; } @@ -1101,6 +1101,13 @@ lha_read_file_header_3(struct archive_read *a, struct lha *lha) header_crc = lha_crc16(0, p, H3_FIXED_SIZE); __archive_read_consume(a, H3_FIXED_SIZE); + /* Reject rediculously large header */ + if (lha->header_size > 65536) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "LHa header size too large"); + return (ARCHIVE_FATAL); + } + /* Read extended headers */ err = lha_read_file_extended_header(a, lha, &header_crc, 4, lha->header_size - H3_FIXED_SIZE, &extdsize); diff --git a/libarchive/archive_read_support_format_mtree.c b/libarchive/archive_read_support_format_mtree.c index 10c07b05d965..4a5a49ca8136 100644 --- a/libarchive/archive_read_support_format_mtree.c +++ b/libarchive/archive_read_support_format_mtree.c @@ -300,7 +300,12 @@ cleanup(struct archive_read *a) struct mtree_entry *p, *q; mtree = (struct mtree *)(a->format->data); - + + /* Close any dangling file descriptor before freeing */ + if (mtree->fd >= 0) { + close(mtree->fd); + mtree->fd = -1; + } p = mtree->entries; while (p != NULL) { q = p->next; diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c index 9b401c00ba34..0ed2540cd0a8 100644 --- a/libarchive/archive_read_support_format_rar.c +++ b/libarchive/archive_read_support_format_rar.c @@ -955,7 +955,7 @@ archive_read_format_rar_read_header(struct archive_read *a, if ((h = __archive_read_ahead(a, 7, NULL)) == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Failed to read next header."); + "Failed to read next header"); return (ARCHIVE_FATAL); } p = h; @@ -1005,7 +1005,7 @@ archive_read_format_rar_read_header(struct archive_read *a, archive_entry_set_is_data_encrypted(entry, 1); rar->has_encrypted_entries = 1; archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "RAR encryption support unavailable."); + "RAR encryption support unavailable"); return (ARCHIVE_FATAL); } @@ -1141,7 +1141,7 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff, default: archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Unsupported compression method for RAR file."); + "Unsupported compression method for RAR file"); ret = ARCHIVE_FATAL; break; } @@ -1432,14 +1432,14 @@ read_header(struct archive_read *a, struct archive_entry *entry, else { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "RAR solid archive support unavailable."); + "RAR solid archive support unavailable"); return (ARCHIVE_FATAL); } if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Failed to read full header content."); + "Failed to read full header content"); return (ARCHIVE_FATAL); } @@ -1471,7 +1471,7 @@ read_header(struct archive_read *a, struct archive_entry *entry, archive_entry_set_is_data_encrypted(entry, 1); rar->has_encrypted_entries = 1; archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "RAR encryption support unavailable."); + "RAR encryption support unavailable"); /* Since it is only the data part itself that is encrypted we can at least extract information about the currently processed entry and don't need to return ARCHIVE_FATAL here. */ @@ -1503,7 +1503,7 @@ read_header(struct archive_read *a, struct archive_entry *entry, if (rar->packed_size < 0 || rar->unp_size < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Invalid sizes specified."); + "Invalid sizes specified"); return (ARCHIVE_FATAL); } @@ -1516,19 +1516,19 @@ read_header(struct archive_read *a, struct archive_entry *entry, size_t distance = p - (const char *)h; if (rar->packed_size > INT64_MAX - header_size) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Extended header size too large."); + "Extended header size too large"); return (ARCHIVE_FATAL); } header_size += rar->packed_size; if ((uintmax_t)header_size > SIZE_MAX) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Unable to read extended header data."); + "Unable to read extended header data"); return (ARCHIVE_FATAL); } /* Make sure we have the extended data. */ if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Failed to read extended header data."); + "Failed to read extended header data"); return (ARCHIVE_FATAL); } p = h; @@ -1547,7 +1547,7 @@ read_header(struct archive_read *a, struct archive_entry *entry, newptr = realloc(rar->filename, newsize); if (newptr == NULL) { archive_set_error(&a->archive, ENOMEM, - "Couldn't allocate memory."); + "Couldn't allocate memory"); return (ARCHIVE_FATAL); } rar->filename = newptr; @@ -1701,7 +1701,7 @@ read_header(struct archive_read *a, struct archive_entry *entry, newsize = sizeof(*rar->dbo) * (rar->nodes + 1); if ((newdbo = realloc(rar->dbo, newsize)) == NULL) { - archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory."); + archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory"); return (ARCHIVE_FATAL); } rar->dbo = newdbo; @@ -1715,7 +1715,7 @@ read_header(struct archive_read *a, struct archive_entry *entry, if (rar->packed_size > INT64_MAX - a->filter->position) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Unable to store offsets."); + "Unable to store offsets"); return (ARCHIVE_FATAL); } rar->dbo[rar->cursor].start_offset = a->filter->position; @@ -1734,7 +1734,7 @@ read_header(struct archive_read *a, struct archive_entry *entry, newsize = filename_size + 1; if ((newptr = realloc(rar->filename_save, newsize)) == NULL) { - archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory."); + archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory"); return (ARCHIVE_FATAL); } rar->filename_save = newptr; @@ -1745,7 +1745,7 @@ read_header(struct archive_read *a, struct archive_entry *entry, free(rar->dbo); if ((rar->dbo = calloc(1, sizeof(*rar->dbo))) == NULL) { - archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory."); + archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory"); return (ARCHIVE_FATAL); } rar->dbo[0].header_size = header_size; @@ -1776,7 +1776,7 @@ read_header(struct archive_read *a, struct archive_entry *entry, __archive_read_consume(a, header_size - 7); if (rar->packed_size > INT64_MAX - a->filter->position) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Unable to store offsets."); + "Unable to store offsets"); return (ARCHIVE_FATAL); } rar->dbo[0].start_offset = a->filter->position; @@ -1848,7 +1848,7 @@ read_header(struct archive_read *a, struct archive_entry *entry, return (ARCHIVE_FATAL); } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Pathname cannot be converted from %s to current locale.", + "Pathname cannot be converted from %s to current locale", archive_string_conversion_charset_name(fn_sconv)); ret = (ARCHIVE_WARN); } @@ -1979,13 +1979,13 @@ read_symlink_stored(struct archive_read *a, struct archive_entry *entry, if ((uintmax_t)rar->packed_size > SIZE_MAX) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Unable to read link."); + "Unable to read link"); return (ARCHIVE_FATAL); } if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Failed to read link."); + "Failed to read link"); return (ARCHIVE_FATAL); } p = h; @@ -2000,7 +2000,7 @@ read_symlink_stored(struct archive_read *a, struct archive_entry *entry, return (ARCHIVE_FATAL); } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "link cannot be converted from %s to current locale.", + "link cannot be converted from %s to current locale", archive_string_conversion_charset_name(sconv)); ret = (ARCHIVE_WARN); } @@ -2201,7 +2201,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, case 3: archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Parsing filters is unsupported."); + "Parsing filters is unsupported"); return (ARCHIVE_FAILED); case 4: @@ -2473,7 +2473,7 @@ parse_codes(struct archive_read *a) free(precode.tree); free(precode.table); archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Internal error extracting RAR file."); + "Internal error extracting RAR file"); return (ARCHIVE_FATAL); } @@ -2548,7 +2548,8 @@ parse_codes(struct archive_read *a) return (r); } - if (!rar->dictionary_size || !rar->lzss.window) + if (!rar->dictionary_size || !rar->lzss.window || + (unsigned int)(rar->lzss.mask + 1) < rar->dictionary_size) { /* Seems as though dictionary sizes are not used. Even so, minimize * memory usage as much as possible. @@ -2562,13 +2563,13 @@ parse_codes(struct archive_read *a) new_size = rar_fls((unsigned int)rar->unp_size) << 1; if (new_size == 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Zero window size is invalid."); + "Zero window size is invalid"); return (ARCHIVE_FATAL); } new_window = realloc(rar->lzss.window, new_size); if (new_window == NULL) { archive_set_error(&a->archive, ENOMEM, - "Unable to allocate memory for uncompressed data."); + "Unable to allocate memory for uncompressed data"); return (ARCHIVE_FATAL); } rar->lzss.window = (unsigned char *)new_window; @@ -2686,7 +2687,7 @@ create_code(struct archive_read *a, struct huffman_code *code, code->numallocatedentries = 0; if (new_node(code) < 0) { archive_set_error(&a->archive, ENOMEM, - "Unable to allocate memory for node data."); + "Unable to allocate memory for node data"); return (ARCHIVE_FATAL); } code->numentries = 1; @@ -2769,12 +2770,12 @@ add_value(struct archive_read *a, struct huffman_code *code, int value, if ((repeatnode = new_node(code)) < 0) { archive_set_error(&a->archive, ENOMEM, - "Unable to allocate memory for node data."); + "Unable to allocate memory for node data"); return (ARCHIVE_FATAL); } if ((nextnode = new_node(code)) < 0) { archive_set_error(&a->archive, ENOMEM, - "Unable to allocate memory for node data."); + "Unable to allocate memory for node data"); return (ARCHIVE_FATAL); } @@ -2794,7 +2795,7 @@ add_value(struct archive_read *a, struct huffman_code *code, int value, { if (new_node(code) < 0) { archive_set_error(&a->archive, ENOMEM, - "Unable to allocate memory for node data."); + "Unable to allocate memory for node data"); return (ARCHIVE_FATAL); } code->tree[lastnode].branches[bit] = code->numentries++; @@ -2863,13 +2864,13 @@ make_table_recurse(struct archive_read *a, struct huffman_code *code, int node, if (!code->tree) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Huffman tree was not created."); + "Huffman tree was not created"); return (ARCHIVE_FATAL); } if (node < 0 || node >= code->numentries) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Invalid location to Huffman tree specified."); + "Invalid location to Huffman tree specified"); return (ARCHIVE_FATAL); } @@ -3149,6 +3150,11 @@ copy_from_lzss_window(struct archive_read *a, uint8_t *buffer, windowoffs = lzss_offset_for_position(&rar->lzss, startpos); firstpart = lzss_size(&rar->lzss) - windowoffs; + if (length > lzss_size(&rar->lzss)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Bad RAR file data"); + return (ARCHIVE_FATAL); + } if (firstpart < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Bad RAR file data"); @@ -3180,7 +3186,7 @@ copy_from_lzss_window_to_unp(struct archive_read *a, const void **buffer, if ((rar->unp_buffer = malloc(rar->unp_buffer_size)) == NULL) { archive_set_error(&a->archive, ENOMEM, - "Unable to allocate memory for uncompressed data."); + "Unable to allocate memory for uncompressed data"); return (ARCHIVE_FATAL); } } @@ -3315,7 +3321,8 @@ parse_filter(struct archive_read *a, const uint8_t *bytes, uint16_t length, uint else blocklength = prog ? prog->oldfilterlength : 0; - if (blocklength > rar->dictionary_size) + if (blocklength > rar->dictionary_size || + blocklength > (uint32_t)(rar->lzss.mask + 1)) return 0; registers[3] = PROGRAM_SYSTEM_GLOBAL_ADDRESS; diff --git a/libarchive/archive_read_support_format_rar5.c b/libarchive/archive_read_support_format_rar5.c index 17e501e02e9f..63dd97b3008a 100644 --- a/libarchive/archive_read_support_format_rar5.c +++ b/libarchive/archive_read_support_format_rar5.c @@ -375,6 +375,7 @@ static int rar5_read_data_skip(struct archive_read *a); static int push_data_ready(struct archive_read* a, struct rar5* rar, const uint8_t* buf, size_t size, int64_t offset); static void clear_data_ready_stack(struct rar5* rar); +static void rar5_deinit(struct rar5* rar); /* CDE_xxx = Circular Double Ended (Queue) return values. */ enum CDE_RETURN_VALUES { @@ -429,8 +430,7 @@ static int cdeque_front(struct cdeque* d, void** value) { return CDE_OUT_OF_BOUNDS; } -/* Pushes a new element into the end of this circular deque object. If current - * size will exceed capacity, the oldest element will be overwritten. */ +/* Pushes a new element into the end of this circular deque object. */ static int cdeque_push_back(struct cdeque* d, void* item) { if(d == NULL) return CDE_PARAM; @@ -554,7 +554,11 @@ static struct filter_info* add_new_filter(struct rar5* rar) { return NULL; } - cdeque_push_back(&rar->cstate.filters, cdeque_filter(f)); + if (CDE_OK != cdeque_push_back(&rar->cstate.filters, cdeque_filter(f))) { + free(f); + return NULL; + } + return f; } @@ -671,7 +675,7 @@ static int run_filter(struct archive_read* a, struct filter_info* flt) { rar->cstate.filtered_buf = malloc(flt->block_length); if(!rar->cstate.filtered_buf) { archive_set_error(&a->archive, ENOMEM, - "Can't allocate memory for filter data."); + "Can't allocate memory for filter data"); return ARCHIVE_FATAL; } @@ -1847,7 +1851,7 @@ static int process_head_file(struct archive_read* a, struct rar5* rar, rar->cstate.window_buf == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Declared solid file, but no window buffer " - "initialized yet."); + "initialized yet"); return ARCHIVE_FATAL; } @@ -1857,7 +1861,7 @@ static int process_head_file(struct archive_read* a, struct rar5* rar, (rar->file.dir == 0 && window_size == 0)) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Declared dictionary size is not supported."); + "Declared dictionary size is not supported"); return ARCHIVE_FATAL; } @@ -1869,7 +1873,7 @@ static int process_head_file(struct archive_read* a, struct rar5* rar, { 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. "); + "the window size used in previous solid file"); return ARCHIVE_FATAL; } } @@ -1895,7 +1899,7 @@ static int process_head_file(struct archive_read* a, struct rar5* rar, if(!new_window_buf) { archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, "Not enough memory when trying to realloc the window " - "buffer."); + "buffer"); return ARCHIVE_FATAL; } @@ -3040,7 +3044,9 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) { if(block_length < 4 || block_length > 0x400000 || filter_type > FILTER_ARM || - !is_valid_filter_block_start(rar, block_start)) + !is_valid_filter_block_start(rar, block_start) || + (rar->cstate.window_size > 0 && + (ssize_t)block_length > rar->cstate.window_size >> 1)) { archive_set_error(&ar->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid filter encountered"); @@ -3051,7 +3057,7 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) { filt = add_new_filter(rar); if(filt == NULL) { archive_set_error(&ar->archive, ENOMEM, - "Can't allocate memory for a filter descriptor."); + "Can't allocate memory for a filter descriptor"); return ARCHIVE_FATAL; } @@ -3500,7 +3506,7 @@ static int merge_block(struct archive_read* a, ssize_t block_size, rar->vol.push_buf = malloc(block_size + 8); if(!rar->vol.push_buf) { archive_set_error(&a->archive, ENOMEM, - "Can't allocate memory for a merge block buffer."); + "Can't allocate memory for a merge block buffer"); return ARCHIVE_FATAL; } @@ -3533,7 +3539,7 @@ static int merge_block(struct archive_read* a, ssize_t block_size, if(partial_offset + cur_block_size > block_size) { archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, - "Consumed too much data when merging blocks."); + "Consumed too much data when merging blocks"); return ARCHIVE_FATAL; } @@ -3802,7 +3808,7 @@ static int push_data_ready(struct archive_read* a, struct rar5* rar, * as an internal error. */ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, - "Error: premature end of data_ready stack"); + "Premature end of data_ready stack"); return ARCHIVE_FATAL; } @@ -4328,7 +4334,7 @@ static int rar5_cleanup(struct archive_read *a) { free(rar->vol.push_buf); free_filters(rar); - cdeque_free(&rar->cstate.filters); + rar5_deinit(rar); free(rar); a->format->data = NULL; @@ -4353,6 +4359,7 @@ static int rar5_has_encrypted_entries(struct archive_read *_a) { return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; } +/* Must match deallocations in rar5_deinit */ static int rar5_init(struct rar5* rar) { memset(rar, 0, sizeof(struct rar5)); @@ -4368,6 +4375,11 @@ static int rar5_init(struct rar5* rar) { return ARCHIVE_OK; } +/* Must match allocations in rar5_init */ +static void rar5_deinit(struct rar5* rar) { + cdeque_free(&rar->cstate.filters); +} + int archive_read_support_format_rar5(struct archive *_a) { struct archive_read* ar; int ret; @@ -4404,8 +4416,9 @@ int archive_read_support_format_rar5(struct archive *_a) { rar5_has_encrypted_entries); if(ret != ARCHIVE_OK) { - (void) rar5_cleanup(ar); + rar5_deinit(rar); + free(rar); } - return ret; + return ARCHIVE_OK; } diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c index 98f7d699570a..2979492767ed 100644 --- a/libarchive/archive_read_support_format_tar.c +++ b/libarchive/archive_read_support_format_tar.c @@ -1202,7 +1202,7 @@ set_conversion_failed_error(struct archive_read *a, return (ARCHIVE_FATAL); } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "%s can't be converted from %s to current locale.", + "%s can't be converted from %s to current locale", name, archive_string_conversion_charset_name(sconv)); return (ARCHIVE_WARN); } @@ -2255,12 +2255,12 @@ pax_attribute_SCHILY_acl(struct archive_read *a, struct tar *tar, if (r != ARCHIVE_OK) { if (r == ARCHIVE_FATAL) { archive_set_error(&a->archive, ENOMEM, - "%s %s", "Can't allocate memory for ", + "%s %s", "Can't allocate memory for", errstr); return (r); } archive_set_error(&a->archive, - ARCHIVE_ERRNO_MISC, "%s %s", "Parse error: ", errstr); + ARCHIVE_ERRNO_MISC, "%s %s", "Parse error:", errstr); } return (r); } diff --git a/libarchive/archive_read_support_format_xar.c b/libarchive/archive_read_support_format_xar.c index 36b5ab3ae04c..874501fc0782 100644 --- a/libarchive/archive_read_support_format_xar.c +++ b/libarchive/archive_read_support_format_xar.c @@ -733,7 +733,7 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry) } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Gname cannot be converted from %s to current locale.", + "Gname cannot be converted from %s to current locale", archive_string_conversion_charset_name(xar->sconv)); r = ARCHIVE_WARN; } @@ -748,7 +748,7 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry) } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Uname cannot be converted from %s to current locale.", + "Uname cannot be converted from %s to current locale", archive_string_conversion_charset_name(xar->sconv)); r = ARCHIVE_WARN; } @@ -762,7 +762,7 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry) } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Pathname cannot be converted from %s to current locale.", + "Pathname cannot be converted from %s to current locale", archive_string_conversion_charset_name(xar->sconv)); r = ARCHIVE_WARN; } @@ -778,7 +778,7 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry) } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Linkname cannot be converted from %s to current locale.", + "Linkname cannot be converted from %s to current locale", archive_string_conversion_charset_name(xar->sconv)); r = ARCHIVE_WARN; } @@ -1008,7 +1008,7 @@ move_reading_point(struct archive_read *a, uint64_t offset) if (pos == ARCHIVE_FAILED) { archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, - "Cannot seek."); + "Cannot seek"); return (ARCHIVE_FAILED); } xar->offset = pos; @@ -1476,7 +1476,7 @@ decompression_init(struct archive_read *a, enum enctype encoding) r = inflateInit(&(xar->stream)); if (r != Z_OK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Couldn't initialize zlib stream."); + "Couldn't initialize zlib stream"); return (ARCHIVE_FATAL); } xar->stream_valid = 1; @@ -1691,7 +1691,7 @@ decompress(struct archive_read *a, const void **buff, size_t *outbytes, default: archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, - "%s decompression failed(%d)", + "%s decompression failed (%d)", (xar->entry_encoding == XZ)?"xz":"lzma", r); return (ARCHIVE_FATAL); diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c index 0c86ce935e26..00796b288a48 100644 --- a/libarchive/archive_read_support_format_zip.c +++ b/libarchive/archive_read_support_format_zip.c @@ -1008,7 +1008,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Pathname cannot be converted " - "from %s to current locale.", + "from %s to current locale", archive_string_conversion_charset_name(sconv)); ret = ARCHIVE_WARN; } @@ -1256,7 +1256,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Symlink cannot be converted " - "from %s to current locale.", + "from %s to current locale", archive_string_conversion_charset_name( sconv)); ret = ARCHIVE_WARN; @@ -1726,7 +1726,7 @@ zipx_xz_init(struct archive_read *a, struct zip *zip) r = lzma_stream_decoder(&zip->zipx_lzma_stream, UINT64_MAX, 0); if (r != LZMA_OK) { archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, - "xz initialization failed(%d)", + "xz initialization failed (%d)", r); return (ARCHIVE_FAILED); @@ -1778,7 +1778,7 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip) r = lzma_alone_decoder(&zip->zipx_lzma_stream, UINT64_MAX); if (r != LZMA_OK) { archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, - "lzma initialization failed(%d)", r); + "lzma initialization failed (%d)", r); return (ARCHIVE_FAILED); } @@ -1921,7 +1921,7 @@ zip_read_data_zipx_xz(struct archive_read *a, const void **buff, switch(lz_ret) { case LZMA_DATA_ERROR: archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "xz data error (error %d)", (int) lz_ret); + "xz data error (%d)", (int) lz_ret); return (ARCHIVE_FATAL); case LZMA_NO_CHECK: @@ -1930,7 +1930,7 @@ zip_read_data_zipx_xz(struct archive_read *a, const void **buff, default: archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "xz unknown error %d", (int) lz_ret); + "xz unknown error (%d)", (int) lz_ret); return (ARCHIVE_FATAL); case LZMA_STREAM_END: @@ -2018,7 +2018,7 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff, switch(lz_ret) { case LZMA_DATA_ERROR: archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "lzma data error (error %d)", (int) lz_ret); + "lzma data error (%d)", (int) lz_ret); return (ARCHIVE_FATAL); /* This case is optional in lzma alone format. It can happen, @@ -2041,7 +2041,7 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff, default: archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "lzma unknown error %d", (int) lz_ret); + "lzma unknown error (%d)", (int) lz_ret); return (ARCHIVE_FATAL); } @@ -2261,7 +2261,7 @@ zipx_bzip2_init(struct archive_read *a, struct zip *zip) r = BZ2_bzDecompressInit(&zip->bzstream, 0, 1); if(r != BZ_OK) { archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, - "bzip2 initialization failed(%d)", + "bzip2 initialization failed (%d)", r); return ARCHIVE_FAILED; @@ -2527,7 +2527,7 @@ zip_deflate_init(struct archive_read *a, struct zip *zip) -15 /* Don't check for zlib header */); if (r != Z_OK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Can't initialize ZIP decompression."); + "Can't initialize ZIP decompression"); return (ARCHIVE_FATAL); } /* Stream structure has been set up. */ @@ -3193,7 +3193,7 @@ archive_read_format_zip_read_data(struct archive_read *a, != (zip->entry_uncompressed_bytes_read & UINT32_MAX)) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "ZIP uncompressed data is wrong size " - "(read %jd, expected %jd)\n", + "(read %jd, expected %jd)", (intmax_t)zip->entry_uncompressed_bytes_read, (intmax_t)zip->entry->uncompressed_size); return (ARCHIVE_FAILED); diff --git a/libarchive/archive_string.c b/libarchive/archive_string.c index a776dc85c688..c6ae8968d54f 100644 --- a/libarchive/archive_string.c +++ b/libarchive/archive_string.c @@ -772,7 +772,7 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as, int r; defchar_used = 0; - if (to_cp == CP_UTF8 || sc == NULL) + if (to_cp == CP_UTF8) dp = NULL; else dp = &defchar_used; @@ -1713,7 +1713,7 @@ get_sconv_object(struct archive *a, const char *fc, const char *tc, int flag) if (a != NULL) { #if HAVE_ICONV archive_set_error(a, ARCHIVE_ERRNO_MISC, - "iconv_open failed : Cannot handle ``%s''", + "iconv_open failed: Cannot handle ``%s''", (flag & SCONV_TO_CHARSET)?tc:fc); #else archive_set_error(a, ARCHIVE_ERRNO_MISC, @@ -1873,6 +1873,9 @@ archive_string_conversion_free(struct archive *a) const char * archive_string_conversion_charset_name(struct archive_string_conv *sc) { + if (sc == NULL) { + return "current locale"; + } if (sc->flag & SCONV_TO_CHARSET) return (sc->to_charset); else @@ -4123,7 +4126,12 @@ archive_mstring_get_mbs_l(struct archive *a, struct archive_mstring *aes, * character-set. */ if ((aes->aes_set & AES_SET_MBS) == 0) { const char *pm; /* unused */ - archive_mstring_get_mbs(a, aes, &pm); /* ignore errors, we'll handle it later */ + if (archive_mstring_get_mbs(a, aes, &pm) != 0) { + /* We have another form, but failed to convert it to + * the native locale. Transitively, we've failed to + * convert it to the specified character set. */ + ret = -1; + } } /* If we already have an MBS form, use it to be translated to * specified character-set. */ @@ -4141,6 +4149,8 @@ archive_mstring_get_mbs_l(struct archive *a, struct archive_mstring *aes, if (length != NULL) *length = aes->aes_mbs_in_locale.length; } else { + /* Either we have no string in any form, + * or conversion failed and set 'ret != 0'. */ *p = NULL; if (length != NULL) *length = 0; diff --git a/libarchive/archive_write.c b/libarchive/archive_write.c index e1ce5d57288d..14dc7339ec5a 100644 --- a/libarchive/archive_write.c +++ b/libarchive/archive_write.c @@ -742,7 +742,7 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry) if (a->format_write_header == NULL) { archive_set_error(&(a->archive), -1, - "Format must be set before you can write to an archive."); + "Format must be set before you can write to an archive"); a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); } diff --git a/libarchive/archive_write_add_filter_b64encode.c b/libarchive/archive_write_add_filter_b64encode.c index dbedf9d305c3..d2c4742d2ef6 100644 --- a/libarchive/archive_write_add_filter_b64encode.c +++ b/libarchive/archive_write_add_filter_b64encode.c @@ -28,6 +28,9 @@ #ifdef HAVE_ERRNO_H #include <errno.h> #endif +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif @@ -116,12 +119,20 @@ archive_filter_b64encode_options(struct archive_write_filter *f, const char *key struct private_b64encode *state = (struct private_b64encode *)f->data; if (strcmp(key, "mode") == 0) { + int64_t val; + if (value == NULL) { archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, "mode option requires octal digits"); return (ARCHIVE_FAILED); } - state->mode = (int)atol8(value, strlen(value)) & 0777; + val = atol8(value, strlen(value)); + if (val < 0 || val > INT_MAX) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "invalid mode option"); + return (ARCHIVE_FAILED); + } + state->mode = (int)val & 0777; return (ARCHIVE_OK); } else if (strcmp(key, "name") == 0) { if (value == NULL) { @@ -286,14 +297,19 @@ atol8(const char *p, size_t char_cnt) { int64_t l; int digit; - + + if (char_cnt == 0) + return (-1); + l = 0; while (char_cnt-- > 0) { if (*p >= '0' && *p <= '7') digit = *p - '0'; else - break; + return (-1); p++; + if (l > (INT64_MAX >> 3)) + return (-1); l <<= 3; l |= digit; } diff --git a/libarchive/archive_write_add_filter_bzip2.c b/libarchive/archive_write_add_filter_bzip2.c index 2434528d5133..94b342d41b74 100644 --- a/libarchive/archive_write_add_filter_bzip2.c +++ b/libarchive/archive_write_add_filter_bzip2.c @@ -127,8 +127,11 @@ archive_compressor_bzip2_options(struct archive_write_filter *f, if (strcmp(key, "compression-level") == 0) { if (value == NULL || !(value[0] >= '0' && value[0] <= '9') || - value[1] != '\0') - return (ARCHIVE_WARN); + value[1] != '\0') { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "compression-level invalid"); + return (ARCHIVE_FAILED); + } data->compression_level = value[0] - '0'; /* Make '0' be a synonym for '1'. */ /* This way, bzip2 compressor supports the same 0..9 diff --git a/libarchive/archive_write_add_filter_gzip.c b/libarchive/archive_write_add_filter_gzip.c index b09e669b753d..0a2f22408bad 100644 --- a/libarchive/archive_write_add_filter_gzip.c +++ b/libarchive/archive_write_add_filter_gzip.c @@ -160,8 +160,11 @@ archive_compressor_gzip_options(struct archive_write_filter *f, const char *key, if (strcmp(key, "compression-level") == 0) { if (value == NULL || !(value[0] >= '0' && value[0] <= '9') || - value[1] != '\0') - return (ARCHIVE_WARN); + value[1] != '\0') { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "compression-level invalid"); + return (ARCHIVE_FAILED); + } data->compression_level = value[0] - '0'; return (ARCHIVE_OK); } @@ -172,8 +175,11 @@ archive_compressor_gzip_options(struct archive_write_filter *f, const char *key, if (strcmp(key, "original-filename") == 0) { free((void*)data->original_filename); data->original_filename = NULL; - if (value) + if (value) { data->original_filename = strdup(value); + if (data->original_filename == NULL) + return (ARCHIVE_WARN); + } return (ARCHIVE_OK); } diff --git a/libarchive/archive_write_add_filter_lrzip.c b/libarchive/archive_write_add_filter_lrzip.c index fe974c93d5d0..cda34dc738d3 100644 --- a/libarchive/archive_write_add_filter_lrzip.c +++ b/libarchive/archive_write_add_filter_lrzip.c @@ -97,8 +97,11 @@ archive_write_lrzip_options(struct archive_write_filter *f, const char *key, struct write_lrzip *data = (struct write_lrzip *)f->data; if (strcmp(key, "compression") == 0) { - if (value == NULL) - return (ARCHIVE_WARN); + if (value == NULL) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "compression option requires an argument"); + return (ARCHIVE_FAILED); + } else if (strcmp(value, "bzip2") == 0) data->compression = bzip2; else if (strcmp(value, "gzip") == 0) @@ -109,13 +112,19 @@ archive_write_lrzip_options(struct archive_write_filter *f, const char *key, data->compression = none; else if (strcmp(value, "zpaq") == 0) data->compression = zpaq; - else - return (ARCHIVE_WARN); + else { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "compression invalid"); + return (ARCHIVE_FAILED); + } return (ARCHIVE_OK); } else if (strcmp(key, "compression-level") == 0) { if (value == NULL || !(value[0] >= '1' && value[0] <= '9') || - value[1] != '\0') - return (ARCHIVE_WARN); + value[1] != '\0') { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "compression-level invalid"); + return (ARCHIVE_FAILED); + } data->compression_level = value[0] - '0'; return (ARCHIVE_OK); } diff --git a/libarchive/archive_write_add_filter_lz4.c b/libarchive/archive_write_add_filter_lz4.c index 24061a169521..efc408e2a3f8 100644 --- a/libarchive/archive_write_add_filter_lz4.c +++ b/libarchive/archive_write_add_filter_lz4.c @@ -160,8 +160,11 @@ archive_filter_lz4_options(struct archive_write_filter *f, if (strcmp(key, "compression-level") == 0) { int val; if (value == NULL || !((val = value[0] - '0') >= 1 && val <= 9) || - value[1] != '\0') - return (ARCHIVE_WARN); + value[1] != '\0') { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "compression-level invalid"); + return (ARCHIVE_FAILED); + } #ifndef HAVE_LZ4HC_H if(val >= 3) @@ -184,8 +187,11 @@ archive_filter_lz4_options(struct archive_write_filter *f, } if (strcmp(key, "block-size") == 0) { if (value == NULL || !(value[0] >= '4' && value[0] <= '7') || - value[1] != '\0') - return (ARCHIVE_WARN); + value[1] != '\0') { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "block-size invalid"); + return (ARCHIVE_FAILED); + } data->block_maximum_size = value[0] - '0'; return (ARCHIVE_OK); } diff --git a/libarchive/archive_write_add_filter_lzop.c b/libarchive/archive_write_add_filter_lzop.c index 8580e58844af..42d62db63a13 100644 --- a/libarchive/archive_write_add_filter_lzop.c +++ b/libarchive/archive_write_add_filter_lzop.c @@ -211,8 +211,11 @@ archive_write_lzop_options(struct archive_write_filter *f, const char *key, if (strcmp(key, "compression-level") == 0) { if (value == NULL || !(value[0] >= '1' && value[0] <= '9') || - value[1] != '\0') - return (ARCHIVE_WARN); + value[1] != '\0') { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "compression-level invalid"); + return (ARCHIVE_FAILED); + } data->compression_level = value[0] - '0'; return (ARCHIVE_OK); } diff --git a/libarchive/archive_write_add_filter_uuencode.c b/libarchive/archive_write_add_filter_uuencode.c index 99c7a2cb7a7e..d25236fa9b26 100644 --- a/libarchive/archive_write_add_filter_uuencode.c +++ b/libarchive/archive_write_add_filter_uuencode.c @@ -28,6 +28,9 @@ #ifdef HAVE_ERRNO_H #include <errno.h> #endif +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif @@ -105,12 +108,20 @@ archive_filter_uuencode_options(struct archive_write_filter *f, const char *key, struct private_uuencode *state = (struct private_uuencode *)f->data; if (strcmp(key, "mode") == 0) { + int64_t val; + if (value == NULL) { archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, "mode option requires octal digits"); return (ARCHIVE_FAILED); } - state->mode = (int)atol8(value, strlen(value)) & 0777; + val = atol8(value, strlen(value)); + if (val < 0 || val > INT_MAX) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "invalid mode option"); + return (ARCHIVE_FAILED); + } + state->mode = (int)val & 0777; return (ARCHIVE_OK); } else if (strcmp(key, "name") == 0) { if (value == NULL) { @@ -277,14 +288,19 @@ atol8(const char *p, size_t char_cnt) { int64_t l; int digit; - + + if (char_cnt == 0) + return (-1); + l = 0; while (char_cnt-- > 0) { if (*p >= '0' && *p <= '7') digit = *p - '0'; else - break; + return (-1); p++; + if (l > (INT64_MAX >> 3)) + return (-1); l <<= 3; l |= digit; } diff --git a/libarchive/archive_write_add_filter_xz.c b/libarchive/archive_write_add_filter_xz.c index 098f0c95570b..56cf02070754 100644 --- a/libarchive/archive_write_add_filter_xz.c +++ b/libarchive/archive_write_add_filter_xz.c @@ -29,6 +29,9 @@ #ifdef HAVE_ERRNO_H #include <errno.h> #endif +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif @@ -376,23 +379,33 @@ archive_compressor_xz_options(struct archive_write_filter *f, if (strcmp(key, "compression-level") == 0) { if (value == NULL || !(value[0] >= '0' && value[0] <= '9') || - value[1] != '\0') - return (ARCHIVE_WARN); + value[1] != '\0') { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "compression-level invalid"); + return (ARCHIVE_FAILED); + } data->compression_level = value[0] - '0'; if (data->compression_level > 9) data->compression_level = 9; return (ARCHIVE_OK); } else if (strcmp(key, "threads") == 0) { char *endptr; + unsigned long val; - if (value == NULL) - return (ARCHIVE_WARN); + if (value == NULL) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "threads option requires an argument"); + return (ARCHIVE_FAILED); + } errno = 0; - data->threads = (int)strtoul(value, &endptr, 10); - if (errno != 0 || *endptr != '\0') { + val = strtoul(value, &endptr, 10); + if (errno != 0 || *endptr != '\0' || val > (unsigned)INT_MAX) { data->threads = 1; - return (ARCHIVE_WARN); + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "threads invalid"); + return (ARCHIVE_FAILED); } + data->threads = (int)val; if (data->threads == 0) { #ifdef HAVE_LZMA_STREAM_ENCODER_MT data->threads = lzma_cputhreads(); diff --git a/libarchive/archive_write_add_filter_zstd.c b/libarchive/archive_write_add_filter_zstd.c index d4752c247157..7149abb2b8a8 100644 --- a/libarchive/archive_write_add_filter_zstd.c +++ b/libarchive/archive_write_add_filter_zstd.c @@ -245,7 +245,9 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key, if (strcmp(key, "compression-level") == 0) { intmax_t level; if (string_to_number(value, &level) != ARCHIVE_OK) { - return (ARCHIVE_WARN); + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "compression-level invalid"); + return (ARCHIVE_FAILED); } /* If we don't have the library, hard-code the max level */ int minimum = CLEVEL_MIN; @@ -263,14 +265,18 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key, } #endif if (level < minimum || level > maximum) { - return (ARCHIVE_WARN); + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "compression-level out of range"); + return (ARCHIVE_FAILED); } data->compression_level = (int)level; return (ARCHIVE_OK); } else if (strcmp(key, "threads") == 0) { intmax_t threads; if (string_to_number(value, &threads) != ARCHIVE_OK) { - return (ARCHIVE_WARN); + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "threads invalid"); + return (ARCHIVE_FAILED); } #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) @@ -286,7 +292,9 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key, } #endif if (threads < 0 || threads > INT_MAX) { - return (ARCHIVE_WARN); + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "threads out of rnage"); + return (ARCHIVE_FAILED); } data->threads = (int)threads; return (ARCHIVE_OK); @@ -296,26 +304,34 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key, return (ARCHIVE_OK); } else if (strcmp(key, "min-frame-in") == 0) { if (string_to_size(value, &data->min_frame_in) != ARCHIVE_OK) { - return (ARCHIVE_WARN); + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "min-frame-in invalid"); + return (ARCHIVE_FAILED); } return (ARCHIVE_OK); } else if (strcmp(key, "min-frame-out") == 0 || strcmp(key, "min-frame-size") == 0) { if (string_to_size(value, &data->min_frame_out) != ARCHIVE_OK) { - return (ARCHIVE_WARN); + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "min-frame-out invalid"); + return (ARCHIVE_FAILED); } return (ARCHIVE_OK); } else if (strcmp(key, "max-frame-in") == 0 || strcmp(key, "max-frame-size") == 0) { if (string_to_size(value, &data->max_frame_in) != ARCHIVE_OK || data->max_frame_in < 1024) { - return (ARCHIVE_WARN); + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "max-frame-size invalid"); + return (ARCHIVE_FAILED); } return (ARCHIVE_OK); } else if (strcmp(key, "max-frame-out") == 0) { if (string_to_size(value, &data->max_frame_out) != ARCHIVE_OK || data->max_frame_out < 1024) { - return (ARCHIVE_WARN); + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "max-frame-out invalid"); + return (ARCHIVE_FAILED); } return (ARCHIVE_OK); #endif @@ -323,22 +339,30 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key, else if (strcmp(key, "long") == 0) { intmax_t long_distance; if (string_to_number(value, &long_distance) != ARCHIVE_OK) { - return (ARCHIVE_WARN); + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "long invalid"); + return (ARCHIVE_FAILED); } #if HAVE_ZSTD_H && HAVE_ZSTD_compressStream && ZSTD_VERSION_NUMBER >= MINVER_LONG ZSTD_bounds bounds = ZSTD_cParam_getBounds(ZSTD_c_windowLog); if (ZSTD_isError(bounds.error)) { int max_distance = ((int)(sizeof(size_t) == 4 ? 30 : 31)); - if (((int)long_distance) < 10 || (int)long_distance > max_distance) - return (ARCHIVE_WARN); + if (((int)long_distance) < 10 || (int)long_distance > max_distance) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "long out of range"); + return (ARCHIVE_FAILED); + } } else { - if ((int)long_distance < bounds.lowerBound || (int)long_distance > bounds.upperBound) - return (ARCHIVE_WARN); + if ((int)long_distance < bounds.lowerBound || (int)long_distance > bounds.upperBound) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "long out of range"); + return (ARCHIVE_FAILED); + } } #else int max_distance = ((int)(sizeof(size_t) == 4 ? 30 : 31)); if (((int)long_distance) < 10 || (int)long_distance > max_distance) - return (ARCHIVE_WARN); + return (ARCHIVE_FAILED); #endif data->long_distance = (int)long_distance; return (ARCHIVE_OK); diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c index d1f043d24437..7b90fc25fa54 100644 --- a/libarchive/archive_write_disk_posix.c +++ b/libarchive/archive_write_disk_posix.c @@ -1975,7 +1975,7 @@ archive_write_disk_gid(struct archive *_a, const char *name, la_int64_t id) return (a->lookup_gid)(a->lookup_gid_data, name, id); return (id); } - + int64_t archive_write_disk_uid(struct archive *_a, const char *name, la_int64_t id) { @@ -2119,7 +2119,7 @@ restore_entry(struct archive_write_disk *a) if ((en == ENOENT) && (archive_entry_hardlink(a->entry) != NULL)) { archive_set_error(&a->archive, en, - "Hard-link target '%s' does not exist.", + "Hard-link target '%s' does not exist", archive_entry_hardlink(a->entry)); return (ARCHIVE_FAILED); } @@ -2406,7 +2406,7 @@ create_filesystem_object(struct archive_write_disk *a) */ mode = final_mode & 0777 & ~a->user_umask; - /* + /* * Always create writable such that [f]setxattr() works if we're not * root. */ @@ -3024,7 +3024,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, /* * We are not the last element and we want to * follow symlinks if they are a directory. - * + * * This is needed to extract hardlinks over * symlinks. */ @@ -3435,7 +3435,7 @@ create_dir(struct archive_write_disk *a, char *path) le = new_fixup(a, path); if (le == NULL) return (ARCHIVE_FATAL); - le->fixup |=TODO_MODE_BASE; + le->fixup |= TODO_MODE_BASE; le->mode = mode_final; } return (ARCHIVE_OK); @@ -3447,8 +3447,17 @@ create_dir(struct archive_write_disk *a, char *path) * don't add it to the fixup list here, as it's already been * added. */ - if (la_stat(path, &st) == 0 && S_ISDIR(st.st_mode)) - return (ARCHIVE_OK); + if (errno == EEXIST) { + if (la_stat(path, &st) == 0) { + if (S_ISDIR(st.st_mode)) + return (ARCHIVE_OK); + /* path exists but is not a directory */ + errno = ENOTDIR; + } else { + /* restore original errno */ + errno = EEXIST; + } + } archive_set_error(&a->archive, errno, "Failed to create dir '%s'", path); @@ -4010,7 +4019,7 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, #elif defined(HAVE_CHFLAGS) if (S_ISLNK(a->st.st_mode)) { archive_set_error(&a->archive, errno, - "Can't set file flags on symlink."); + "Can't set file flags on symlink"); return (ARCHIVE_WARN); } if (chflags(name, a->st.st_flags) == 0) @@ -4569,7 +4578,7 @@ set_xattrs(struct archive_write_disk *a) } else archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Cannot restore extended " - "attributes on this file system."); + "attributes on this file system"); } archive_string_free(&errlist); @@ -4671,7 +4680,7 @@ set_xattrs(struct archive_write_disk *a) } else archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Cannot restore extended " - "attributes on this file system."); + "attributes on this file system"); } archive_string_free(&errlist); @@ -4767,4 +4776,3 @@ static void close_file_descriptor(struct archive_write_disk* a) #endif /* !_WIN32 || __CYGWIN__ */ - diff --git a/libarchive/archive_write_disk_windows.c b/libarchive/archive_write_disk_windows.c index d4f6f1820e96..8a970de1ad04 100644 --- a/libarchive/archive_write_disk_windows.c +++ b/libarchive/archive_write_disk_windows.c @@ -1516,7 +1516,7 @@ restore_entry(struct archive_write_disk *a) if ((en == ENOENT) && (archive_entry_hardlink(a->entry) != NULL)) { archive_set_error(&a->archive, en, - "Hard-link target '%s' does not exist.", + "Hard-link target '%s' does not exist", archive_entry_hardlink(a->entry)); return (ARCHIVE_FAILED); } diff --git a/libarchive/archive_write_set_format_7zip.c b/libarchive/archive_write_set_format_7zip.c index ebdb16e9022a..1bbd24d632e7 100644 --- a/libarchive/archive_write_set_format_7zip.c +++ b/libarchive/archive_write_set_format_7zip.c @@ -28,6 +28,9 @@ #ifdef HAVE_ERRNO_H #include <errno.h> #endif +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif @@ -333,6 +336,7 @@ string_to_number(const char *string, intmax_t *numberp) if (string == NULL || *string == '\0') return (ARCHIVE_WARN); + errno = 0; *numberp = strtoimax(string, &end, 10); if (end == string || *end != '\0' || errno == EOVERFLOW) { *numberp = 0; @@ -487,8 +491,9 @@ _7z_options(struct archive_write *a, const char *key, const char *value) } char *end = NULL; + errno = 0; long lvl = strtol(value, &end, 10); - if (end == NULL || *end != '\0') { + if (errno != 0 || end == NULL || *end != '\0') { archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, "parsing compression-level option value failed `%s'", value); return (ARCHIVE_FAILED); @@ -525,7 +530,7 @@ _7z_options(struct archive_write *a, const char *key, const char *value) if (string_to_number(value, &threads) != ARCHIVE_OK) { return (ARCHIVE_WARN); } - if (threads < 0) { + if (threads < 0 || threads > INT_MAX) { return (ARCHIVE_WARN); } if (threads == 0) { diff --git a/libarchive/archive_write_set_format_cpio_binary.c b/libarchive/archive_write_set_format_cpio_binary.c index aefb2ca6f514..4777e75f2912 100644 --- a/libarchive/archive_write_set_format_cpio_binary.c +++ b/libarchive/archive_write_set_format_cpio_binary.c @@ -506,12 +506,12 @@ write_header(struct archive_write *a, struct archive_entry *entry) if ((a->archive.archive_format == ARCHIVE_FORMAT_CPIO_PWB) && (archive_entry_size(entry) > 256*256*256-1)) { archive_set_error(&a->archive, ERANGE, - "File is too large for PWB binary cpio format."); + "File is too large for PWB binary cpio format"); ret_final = ARCHIVE_FAILED; goto exit_write_header; } else if (archive_entry_size(entry) > INT32_MAX) { archive_set_error(&a->archive, ERANGE, - "File is too large for binary cpio format."); + "File is too large for binary cpio format"); ret_final = ARCHIVE_FAILED; goto exit_write_header; } diff --git a/libarchive/archive_write_set_format_cpio_newc.c b/libarchive/archive_write_set_format_cpio_newc.c index 254d5a9901c3..d72434d8ae88 100644 --- a/libarchive/archive_write_set_format_cpio_newc.c +++ b/libarchive/archive_write_set_format_cpio_newc.c @@ -322,7 +322,7 @@ write_header(struct archive_write *a, struct archive_entry *entry) h + c_filesize_offset, c_filesize_size); if (ret) { archive_set_error(&a->archive, ERANGE, - "File is too large for this format."); + "File is too large for this format"); ret_final = ARCHIVE_FAILED; goto exit_write_header; } diff --git a/libarchive/archive_write_set_format_cpio_odc.c b/libarchive/archive_write_set_format_cpio_odc.c index c72c6b2796bf..ffac716b8e75 100644 --- a/libarchive/archive_write_set_format_cpio_odc.c +++ b/libarchive/archive_write_set_format_cpio_odc.c @@ -380,7 +380,7 @@ write_header(struct archive_write *a, struct archive_entry *entry) h + c_filesize_offset, c_filesize_size); if (ret) { archive_set_error(&a->archive, ERANGE, - "File is too large for cpio format."); + "File is too large for cpio format"); ret_final = ARCHIVE_FAILED; goto exit_write_header; } diff --git a/libarchive/archive_write_set_format_gnutar.c b/libarchive/archive_write_set_format_gnutar.c index 14ef4cd2444d..b67007a631c0 100644 --- a/libarchive/archive_write_set_format_gnutar.c +++ b/libarchive/archive_write_set_format_gnutar.c @@ -293,6 +293,17 @@ archive_write_gnutar_header(struct archive_write *a, } else sconv = gnutar->opt_sconv; + /* Sanity check. */ + if (archive_entry_pathname(entry) == NULL +#if defined(_WIN32) && !defined(__CYGWIN__) + && archive_entry_pathname_w(entry) == NULL +#endif + ) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't record entry in tar file without pathname"); + return ARCHIVE_FAILED; + } + /* Only regular files (not hardlinks) have data. */ if (archive_entry_hardlink(entry) != NULL || archive_entry_symlink(entry) != NULL || @@ -385,17 +396,30 @@ archive_write_gnutar_header(struct archive_write *a, r = archive_entry_pathname_l(entry, &(gnutar->pathname), &(gnutar->pathname_length), sconv); if (r != 0) { + const char* p_mbs; if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for pathname"); ret = ARCHIVE_FATAL; goto exit_write_header; } - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Can't translate pathname '%s' to %s", - archive_entry_pathname(entry), - archive_string_conversion_charset_name(sconv)); - ret2 = ARCHIVE_WARN; + p_mbs = archive_entry_pathname(entry); + if (p_mbs) { + /* We have a wrongly-encoded MBS pathname. + * Warn and use it. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname '%s' to %s", p_mbs, + archive_string_conversion_charset_name(sconv)); + ret2 = ARCHIVE_WARN; + } else { + /* We have no MBS pathname. Fail. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname to %s", + archive_string_conversion_charset_name(sconv)); + return ARCHIVE_FAILED; + } } r = archive_entry_uname_l(entry, &(gnutar->uname), &(gnutar->uname_length), sconv); diff --git a/libarchive/archive_write_set_format_iso9660.c b/libarchive/archive_write_set_format_iso9660.c index c275c1ec92b9..359a2737365f 100644 --- a/libarchive/archive_write_set_format_iso9660.c +++ b/libarchive/archive_write_set_format_iso9660.c @@ -1381,7 +1381,7 @@ iso9660_options(struct archive_write *a, const char *key, const char *value) archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Option ``%s'' " - "is not supported on this platform.", key); + "is not supported on this platform", key); return (ARCHIVE_FATAL); #endif } @@ -1503,7 +1503,7 @@ iso9660_options(struct archive_write *a, const char *key, const char *value) archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "``zisofs'' " - "is not supported on this platform."); + "is not supported on this platform"); return (ARCHIVE_FATAL); #endif } @@ -1539,7 +1539,7 @@ iso9660_write_header(struct archive_write *a, struct archive_entry *entry) if (archive_entry_filetype(entry) == AE_IFLNK && iso9660->opt.rr == OPT_RR_DISABLED) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Ignore symlink file."); + "Ignore symlink file"); iso9660->cur_file = NULL; return (ARCHIVE_WARN); } @@ -1549,7 +1549,7 @@ iso9660_write_header(struct archive_write *a, struct archive_entry *entry) archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Ignore over %lld bytes file. " - "This file too large.", + "This file too large", MULTI_EXTENT_SIZE); iso9660->cur_file = NULL; return (ARCHIVE_WARN); @@ -2103,7 +2103,7 @@ iso9660_close(struct archive_write *a) if (iso9660->directories_too_deep != NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "%s: Directories too deep.", + "%s: Directories too deep", archive_entry_pathname( iso9660->directories_too_deep->file->entry)); return (ARCHIVE_WARN); @@ -3799,7 +3799,7 @@ set_file_identifier(unsigned char *bp, int from, int to, enum vdc vdc, isoent = isoent_find_entry(vdd->rootent, ids); if (isoent == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Not Found %s `%s'.", + "Not Found %s `%s'", label, ids); return (ARCHIVE_FATAL); } @@ -7080,7 +7080,7 @@ isoent_make_path_table(struct archive_write *a) * See also ISO9660 Standard 9.4. */ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Too many directories(%d) over 65535.", dir_number); + "Too many directories(%d) over 65535", dir_number); return (ARCHIVE_FATAL); } @@ -7203,7 +7203,7 @@ isoent_create_boot_catalog(struct archive_write *a, struct isoent *rootent) else { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Boot image file(``%s'') size is too big " - "for fd type.", + "for fd type", iso9660->el_torito.boot_filename.s); return (ARCHIVE_FATAL); } @@ -7964,7 +7964,7 @@ zisofs_extract(struct archive_write *a, struct zisofs_extract *zisofs, r = inflateInit(&zisofs->stream); if (r != Z_OK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Can't initialize zisofs decompression."); + "Can't initialize zisofs decompression"); return (ARCHIVE_FATAL); } zisofs->stream_valid = 1; diff --git a/libarchive/archive_write_set_format_mtree.c b/libarchive/archive_write_set_format_mtree.c index 8131574c8da2..a4ffec8954d9 100644 --- a/libarchive/archive_write_set_format_mtree.c +++ b/libarchive/archive_write_set_format_mtree.c @@ -2262,7 +2262,7 @@ mtree_entry_exchange_same_entry(struct archive_write *a, struct mtree_entry *np, if ((np->mode & AE_IFMT) != (file->mode & AE_IFMT)) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Found duplicate entries for `%s' with " - "differing file types.", + "differing file types", np->pathname.s); return (ARCHIVE_FAILED); } diff --git a/libarchive/archive_write_set_format_pax.c b/libarchive/archive_write_set_format_pax.c index 66e6d75196ec..f3589d6859e3 100644 --- a/libarchive/archive_write_set_format_pax.c +++ b/libarchive/archive_write_set_format_pax.c @@ -1062,7 +1062,7 @@ archive_write_pax_header(struct archive_write *a, } /* If numeric GID is too large, add 'gid' to pax extended attrs. */ - if ((unsigned int)archive_entry_gid(entry_main) >= (1 << 18)) { + if (archive_entry_gid(entry_main) >= (1 << 18)) { add_pax_attr_int(&(pax->pax_header), "gid", archive_entry_gid(entry_main)); need_extension = 1; @@ -1078,7 +1078,7 @@ archive_write_pax_header(struct archive_write *a, } /* If numeric UID is too large, add 'uid' to pax extended attrs. */ - if ((unsigned int)archive_entry_uid(entry_main) >= (1 << 18)) { + if (archive_entry_uid(entry_main) >= (1 << 18)) { add_pax_attr_int(&(pax->pax_header), "uid", archive_entry_uid(entry_main)); need_extension = 1; @@ -1471,7 +1471,7 @@ archive_write_pax_header(struct archive_write *a, if (r < ARCHIVE_WARN) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "archive_write_pax_header: " - "'x' header failed?! This can't happen.\n"); + "'x' header failed?! This can't happen"); archive_entry_free(entry_main); archive_string_free(&entry_name); return (ARCHIVE_FATAL); diff --git a/libarchive/archive_write_set_format_ustar.c b/libarchive/archive_write_set_format_ustar.c index 4084eb455968..97724c1588b3 100644 --- a/libarchive/archive_write_set_format_ustar.c +++ b/libarchive/archive_write_set_format_ustar.c @@ -254,11 +254,11 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry) sconv = ustar->opt_sconv; /* Sanity check. */ + if (archive_entry_pathname(entry) == NULL #if defined(_WIN32) && !defined(__CYGWIN__) - if (archive_entry_pathname_w(entry) == NULL) { -#else - if (archive_entry_pathname(entry) == NULL) { + && archive_entry_pathname_w(entry) == NULL #endif + ) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Can't record entry in tar file without pathname"); return (ARCHIVE_FAILED); @@ -409,15 +409,28 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512], */ r = archive_entry_pathname_l(entry, &pp, ©_length, sconv); if (r != 0) { + const char* p_mbs; 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, - "Can't translate pathname '%s' to %s", - pp, archive_string_conversion_charset_name(sconv)); - ret = ARCHIVE_WARN; + p_mbs = archive_entry_pathname(entry); + if (p_mbs) { + /* We have a wrongly-encoded MBS pathname. + * Warn and use it. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname '%s' to %s", p_mbs, + archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + } else { + /* We have no MBS pathname. Fail. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname to %s", + archive_string_conversion_charset_name(sconv)); + return ARCHIVE_FAILED; + } } if (copy_length <= USTAR_name_size) memcpy(h + USTAR_name_offset, pp, copy_length); diff --git a/libarchive/archive_write_set_format_v7tar.c b/libarchive/archive_write_set_format_v7tar.c index 2598fc076c0c..37ba73a1320a 100644 --- a/libarchive/archive_write_set_format_v7tar.c +++ b/libarchive/archive_write_set_format_v7tar.c @@ -232,7 +232,11 @@ archive_write_v7tar_header(struct archive_write *a, struct archive_entry *entry) sconv = v7tar->opt_sconv; /* Sanity check. */ - if (archive_entry_pathname(entry) == NULL) { + if (archive_entry_pathname(entry) == NULL +#if defined(_WIN32) && !defined(__CYGWIN__) + && archive_entry_pathname_w(entry) == NULL +#endif + ) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Can't record entry in tar file without pathname"); return (ARCHIVE_FAILED); @@ -382,15 +386,28 @@ format_header_v7tar(struct archive_write *a, char h[512], */ r = archive_entry_pathname_l(entry, &pp, ©_length, sconv); if (r != 0) { + const char* p_mbs; 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, - "Can't translate pathname '%s' to %s", - pp, archive_string_conversion_charset_name(sconv)); - ret = ARCHIVE_WARN; + p_mbs = archive_entry_pathname(entry); + if (p_mbs) { + /* We have a wrongly-encoded MBS pathname. + * Warn and use it. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname '%s' to %s", p_mbs, + archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + } else { + /* We have no MBS pathname. Fail. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname to %s", + archive_string_conversion_charset_name(sconv)); + return ARCHIVE_FAILED; + } } if (strict && copy_length < V7TAR_name_size) memcpy(h + V7TAR_name_offset, pp, copy_length); diff --git a/libarchive/archive_write_set_format_xar.c b/libarchive/archive_write_set_format_xar.c index ec3219057e4e..6ecccdef6499 100644 --- a/libarchive/archive_write_set_format_xar.c +++ b/libarchive/archive_write_set_format_xar.c @@ -526,12 +526,13 @@ xar_options(struct archive_write *a, const char *key, const char *value) } if (strcmp(key, "threads") == 0) { char *endptr; + unsigned long val; if (value == NULL) return (ARCHIVE_FAILED); errno = 0; - xar->opt_threads = (int)strtoul(value, &endptr, 10); - if (errno != 0 || *endptr != '\0') { + val = strtoul(value, &endptr, 10); + if (errno != 0 || *endptr != '\0' || val > (unsigned)INT_MAX) { xar->opt_threads = 1; archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, @@ -539,6 +540,7 @@ xar_options(struct archive_write *a, const char *key, const char *value) value); return (ARCHIVE_FAILED); } + xar->opt_threads = (int)val; if (xar->opt_threads == 0) { #ifdef HAVE_LZMA_STREAM_ENCODER_MT xar->opt_threads = lzma_cputhreads(); diff --git a/libarchive/archive_write_set_format_zip.c b/libarchive/archive_write_set_format_zip.c index 19121b519148..81d3db0db038 100644 --- a/libarchive/archive_write_set_format_zip.c +++ b/libarchive/archive_write_set_format_zip.c @@ -398,16 +398,17 @@ archive_write_zip_options(struct archive_write *a, const char *key, return (ret); } else if (strcmp(key, "compression-level") == 0) { char *endptr; + unsigned long v; if (val == NULL) return (ARCHIVE_WARN); errno = 0; - zip->compression_level = (short)strtoul(val, &endptr, 10); - if (errno != 0 || *endptr != '\0' || zip->compression_level < 0 || - zip->compression_level > 9) { + v = strtoul(val, &endptr, 10); + if (errno != 0 || *endptr != '\0' || v > 9) { zip->compression_level = 6; // set to default return (ARCHIVE_WARN); } + zip->compression_level = (short)v; if (zip->compression_level == 0) { zip->requested_compression = COMPRESSION_STORE; @@ -435,17 +436,19 @@ archive_write_zip_options(struct archive_write *a, const char *key, } } else if (strcmp(key, "threads") == 0) { char *endptr; + unsigned long v; if (val == NULL) return (ARCHIVE_FAILED); errno = 0; - zip->threads = (short)strtoul(val, &endptr, 10); - if (errno != 0 || *endptr != '\0') { + v = strtoul(val, &endptr, 10); + if (errno != 0 || *endptr != '\0' || v > SHRT_MAX) { zip->threads = 1; archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, "Illegal value `%s'", val); return (ARCHIVE_FAILED); } + zip->threads = (short)v; if (zip->threads == 0) { #ifdef HAVE_LZMA_STREAM_ENCODER_MT zip->threads = lzma_cputhreads(); @@ -802,6 +805,17 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) int version_needed = 10; #define MIN_VERSION_NEEDED(x) do { if (version_needed < x) { version_needed = x; } } while (0) + /* Sanity check. */ + if (archive_entry_pathname(entry) == NULL +#if defined(_WIN32) && !defined(__CYGWIN__) + && archive_entry_pathname_w(entry) == NULL +#endif + ) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't record entry in zip file without pathname"); + return ARCHIVE_FAILED; + } + /* Ignore types of entries that we don't support. */ type = archive_entry_filetype(entry); if (type != AE_IFREG && type != AE_IFDIR && type != AE_IFLNK) { @@ -882,22 +896,33 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) return (ARCHIVE_FATAL); } - if (sconv != NULL) { + { const char *p; size_t len; if (archive_entry_pathname_l(zip->entry, &p, &len, sconv) != 0) { + const char* p_mbs; 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, - "Can't translate Pathname '%s' to %s", - archive_entry_pathname(zip->entry), - archive_string_conversion_charset_name(sconv)); - ret2 = ARCHIVE_WARN; + p_mbs = archive_entry_pathname(zip->entry); + if (p_mbs) { + /* We have a wrongly-encoded MBS pathname. Warn and use it. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname '%s' to %s", p_mbs, + archive_string_conversion_charset_name(sconv)); + ret2 = ARCHIVE_WARN; + } else { + /* We have no MBS pathname. Fail. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname to %s", + archive_string_conversion_charset_name(sconv)); + return ARCHIVE_FAILED; + } } if (len > 0) archive_entry_set_pathname(zip->entry, p); diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt index 02521c2bc1ad..5734cbed5ed8 100644 --- a/libarchive/test/CMakeLists.txt +++ b/libarchive/test/CMakeLists.txt @@ -114,6 +114,8 @@ IF(ENABLE_TEST) test_read_format_ar.c test_read_format_cab.c test_read_format_cab_filename.c + test_read_format_cab_lzx_oob.c + test_read_format_cab_skip_malformed.c test_read_format_cpio_afio.c test_read_format_cpio_bin.c test_read_format_cpio_bin_Z.c @@ -151,10 +153,12 @@ IF(ENABLE_TEST) test_read_format_isorr_new_bz2.c test_read_format_isorr_rr_moved.c test_read_format_isozisofs_bz2.c + test_read_format_iso_zisofs_overflow.c test_read_format_lha.c test_read_format_lha_bugfix_0.c test_read_format_lha_filename.c test_read_format_lha_filename_utf16.c + test_read_format_lha_oversize_header.c test_read_format_mtree.c test_read_format_mtree_crash747.c test_read_format_pax_bz2.c @@ -167,6 +171,7 @@ IF(ENABLE_TEST) test_read_format_rar_filter.c test_read_format_rar_overflow.c test_read_format_rar5.c + test_read_format_rar5_loop_bug.c test_read_format_raw.c test_read_format_tar.c test_read_format_tar_V_negative_size.c @@ -227,6 +232,7 @@ IF(ENABLE_TEST) test_tar_large.c test_ustar_filename_encoding.c test_ustar_filenames.c + test_v7tar_filename_encoding.c test_warn_missing_hardlink_target.c test_write_disk.c test_write_disk_appledouble.c diff --git a/libarchive/test/test_acl_text.c b/libarchive/test/test_acl_text.c index c2904649a3ba..7e80686e84eb 100644 --- a/libarchive/test/test_acl_text.c +++ b/libarchive/test/test_acl_text.c @@ -404,6 +404,29 @@ DEFINE_TEST(test_acl_from_text) archive_entry_acl_clear(ae); free(ws); + + /* + * 6. Malformed "default" prefix with no tag field should return + * ARCHIVE_WARN, not crash (GitHub issue #2744). + * When the ACL text is just "d" or "default" with type DEFAULT, + * the parser recognises the default prefix but field[1] is NULL, + * which previously caused a NULL-pointer dereference. + */ + archive_entry_acl_clear(ae); + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, "d", + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)); + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text_w(ae, L"d", + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)); + archive_entry_acl_clear(ae); + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, "default", + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)); + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text_w(ae, L"default", + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)); + archive_entry_free(ae); } diff --git a/libarchive/test/test_archive_pathmatch.c b/libarchive/test/test_archive_pathmatch.c index 3696d38fcf19..3b212aca9d94 100644 --- a/libarchive/test/test_archive_pathmatch.c +++ b/libarchive/test/test_archive_pathmatch.c @@ -285,4 +285,22 @@ DEFINE_TEST(test_archive_pathmatch) archive_pathmatch("a/b/c$", "a/b/c/d", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); assertEqualInt(1, archive_pathmatch("b/c/d$", "a/b/c/d", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + + /* Anchor characters within pattern not special. */ + assertEqualInt(0, + archive_pathmatch("*^*", "a/b/c", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(1, + archive_pathmatch("*^*", "a^b", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(0, + archive_pathmatch("*$*", "a/b/c", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(1, + archive_pathmatch("*$*", "a$b", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(0, + archive_pathmatch("a*/^b/c", "a/b/c", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(1, + archive_pathmatch("a*/^b/c", "a/^b/c", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(0, + archive_pathmatch("a*/b$/c", "a/b/c", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); + assertEqualInt(1, + archive_pathmatch("a*/b$/c", "a/b$/c", PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END)); } diff --git a/libarchive/test/test_archive_string_conversion.c b/libarchive/test/test_archive_string_conversion.c index 055bddc75068..ecc39dffea7f 100644 --- a/libarchive/test/test_archive_string_conversion.c +++ b/libarchive/test/test_archive_string_conversion.c @@ -883,6 +883,141 @@ DEFINE_TEST(test_archive_string_conversion) test_archive_string_set_get(); } +static void +test_archive_string_conversion_fail_charset(void) +{ + /* Conversion error message construction may use the charset name. */ + assertEqualString("current locale", + archive_string_conversion_charset_name(NULL)); +} + +static void +test_archive_string_conversion_fail_utf16_mbs(struct archive *a, + struct archive_string_conv *sconv) +{ + static const wchar_t wcs_string[] = L"\U0000043f\U00000440\U00000438"; + int r; + const char* p; + size_t len; + + /* WCS to MBS should fail. */ + { + struct archive_string str; + archive_string_init(&str); + r = archive_string_append_from_wcs( + &str, wcs_string, sizeof(wcs_string) / sizeof(*wcs_string) - 1); + assertEqualInt(-1, r); + archive_string_free(&str); + } + { + struct archive_mstring mstr; + memset(&mstr, 0, sizeof(mstr)); + assertEqualInt(ARCHIVE_OK, + archive_mstring_copy_wcs(&mstr, wcs_string)); + r = archive_mstring_get_mbs_l(a, &mstr, &p, &len, NULL); + assertEqualInt(-1, r); + assertEqualInt(0, mstr.aes_set & AES_SET_MBS); + archive_mstring_clean(&mstr); + } + if (sconv) { + struct archive_mstring mstr; + memset(&mstr, 0, sizeof(mstr)); + assertEqualInt(ARCHIVE_OK, + archive_mstring_copy_wcs(&mstr, wcs_string)); + r = archive_mstring_get_mbs_l(a, &mstr, &p, &len, sconv); + assertEqualInt(-1, r); + assertEqualInt(0, mstr.aes_set & AES_SET_MBS); + archive_mstring_clean(&mstr); + } +} + +static void +test_archive_string_conversion_fail_utf8_mbs(struct archive *a, + struct archive_string_conv *sconv) +{ + static const char utf8_string[] = "\xD0\xBF\xD1\x80\xD0\xB8"; + int r; + const char* p; + size_t len; + + /* UTF-8 to MBS should fail. */ + { + struct archive_mstring mstr; + memset(&mstr, 0, sizeof(mstr)); + assertEqualInt(6, + archive_mstring_copy_utf8(&mstr, utf8_string)); + r = archive_mstring_get_mbs_l(a, &mstr, &p, &len, NULL); + assertEqualInt(-1, r); + assertEqualInt(0, mstr.aes_set & AES_SET_MBS); + archive_mstring_clean(&mstr); + } + if (sconv) { + struct archive_mstring mstr; + memset(&mstr, 0, sizeof(mstr)); + assertEqualInt(6, + archive_mstring_copy_utf8(&mstr, utf8_string)); + r = archive_mstring_get_mbs_l(a, &mstr, &p, &len, sconv); + assertEqualInt(-1, r); + assertEqualInt(0, mstr.aes_set & AES_SET_MBS); + archive_mstring_clean(&mstr); + } +} + +DEFINE_TEST(test_archive_string_conversion_fail_c) +{ + struct archive *a; + + /* Test the C locale by not calling setlocale. */ + + test_archive_string_conversion_fail_charset(); + + assert((a = archive_write_new()) != NULL); + + test_archive_string_conversion_fail_utf16_mbs(a, NULL); + test_archive_string_conversion_fail_utf8_mbs(a, NULL); + + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +} + +DEFINE_TEST(test_archive_string_conversion_fail_latin1) +{ + struct archive *a; + struct archive_string_conv *sconv; + + /* Test a Latin-1 locale. */ + if ( +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Windows allows ".<code-page>" to change encoding. */ + setlocale(LC_ALL, ".1252") == NULL +#else + setlocale(LC_ALL, "en_US.ISO8859-1") == NULL +#endif + ) { + skipping("No Latin-1 locale found on this system."); + return; + } + + test_archive_string_conversion_fail_charset(); + + assert((a = archive_write_new()) != NULL); + +#if defined(_WIN32) && !defined(__CYGWIN__) + assertA(NULL != (sconv = + archive_string_conversion_to_charset(a, "CP1252", 0))); + assertEqualString("CP1252", + archive_string_conversion_charset_name(sconv)); +#else + assertA(NULL != (sconv = + archive_string_conversion_to_charset(a, "ISO8859-1", 0))); + assertEqualString("ISO8859-1", + archive_string_conversion_charset_name(sconv)); +#endif + test_archive_string_conversion_fail_utf16_mbs(a, sconv); + test_archive_string_conversion_fail_utf8_mbs(a, sconv); + + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +} + DEFINE_TEST(test_archive_string_conversion_utf16_utf8) { #if !defined(_WIN32) || defined(__CYGWIN__) diff --git a/libarchive/test/test_gnutar_filename_encoding.c b/libarchive/test/test_gnutar_filename_encoding.c index 476ec2149fdf..830b3884f829 100644 --- a/libarchive/test/test_gnutar_filename_encoding.c +++ b/libarchive/test/test_gnutar_filename_encoding.c @@ -491,3 +491,43 @@ DEFINE_TEST(test_gnutar_filename_encoding_UTF16_win) assertEqualMem(buff + 157, "\xE8\xA1\xA8.txt", 7); #endif } + +DEFINE_TEST(test_gnutar_filename_encoding_fail_UTF16_win) +{ +#if !defined(_WIN32) || defined(__CYGWIN__) + skipping("This test is meant to verify unicode string handling" + " on Windows with UTF-16 names"); + return; +#else + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + /* Test the C locale by not calling setlocale. */ + + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_gnutar(a)); + if (archive_write_set_options(a, "hdrcharset=CP437") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from UTF-16 to CP437."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set the filename using a UTF-16 string */ + archive_entry_copy_pathname_w(entry, L"\u8868.txt"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, entry)); + /* The pathname cannot even be represented in the current locale + for inclusion in the error message. */ + assertEqualString("Can't translate pathname to CP437", + archive_error_string(a)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +#endif +} diff --git a/libarchive/test/test_read_format_7zip.c b/libarchive/test/test_read_format_7zip.c index 3236fee2c9d3..6d71f80d12ed 100644 --- a/libarchive/test/test_read_format_7zip.c +++ b/libarchive/test/test_read_format_7zip.c @@ -1383,6 +1383,32 @@ DEFINE_TEST(test_read_format_7zip_sfx_elf) assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } +/* + * A truncated ELF 64-bit MSB file. + */ +DEFINE_TEST(test_read_format_7zip_sfx_elf64trunc) +{ + const char *reffile = "test_read_format_7zip_sfx_elf64trunc.elf"; + struct archive_entry *ae; + struct archive *a; + + 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)); + + extract_reference_file(reffile); + assertEqualIntA(a, ARCHIVE_FATAL, + archive_read_open_filename(a, reffile, 10240)); + + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + assertEqualInt(0, archive_file_count(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + DEFINE_TEST(test_read_format_7zip_extract_second) { struct archive *a; diff --git a/libarchive/test/test_read_format_7zip_malformed.c b/libarchive/test/test_read_format_7zip_malformed.c index f2120879fa8c..bd3452c00aad 100644 --- a/libarchive/test/test_read_format_7zip_malformed.c +++ b/libarchive/test/test_read_format_7zip_malformed.c @@ -59,8 +59,25 @@ test_malformed2(void) assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); } + +static void +test_malformed3(void) +{ + const char *refname = "test_read_format_7zip_malformed3.7z"; + struct archive *a; + + extract_reference_file(refname); + + 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_FATAL, archive_read_open_filename(a, refname, 10240)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); +} + DEFINE_TEST(test_read_format_7zip_malformed) { test_malformed1(); test_malformed2(); + test_malformed3(); } diff --git a/libarchive/test/test_read_format_7zip_malformed3.7z.uu b/libarchive/test/test_read_format_7zip_malformed3.7z.uu new file mode 100644 index 000000000000..4e814980a6da --- /dev/null +++ b/libarchive/test/test_read_format_7zip_malformed3.7z.uu @@ -0,0 +1,24 @@ +begin 644 test_read_format_7zip_malformed3.7z +M?T5,1@("`64N9&5B=0``+ZZNRO_______P```/\Q```````````"```````` +M```L0"!S+F)S,``1<P!```H``FMK__](:VMK:VNAH:$!`*&AH:&A)S$```!C +M;VUP>FEP503_8G-S90``````#0H-_P```'X```````````(````````````` +M`*D``````"\`````____^@````$````````#`/__________<RYD96)U```O +MKJ[*________````_S$```````````(``````````"Q`(',N8G,P`!%S`$`` +M(``":VNAH2<Q```````#Z'K__P5%145%____________`/__________;VUP +M>FEP503_8G-S90``````#0H-_P```'X```````````(``````````````*D` +M`````"\`````____^@````$````````#_P```/______<RYD96)U```OKJ[* +M________````_S$```````````(``````````"Q`(',N8G,P`!%S`$"0`P`" +M:VLR:TAK:VMK:Z&AH0$`H:&AH:$G,@```&-O;7!Z:7!5!/]28W-E```````- +M"@W_````?@```````````@``````````````J0``````+P`````0___Z```` +M`0````````,`__________\PXT$N9&%T80#^E)3+E)24_P3_____________ +M____(________^+______P5%145%____________`/__________________ +M_____________________^?_________145%0``#`/Z4E,N4P<'!P<'!E``` +M`/_R`````'5U=75U=75U=75U=75U=75U=75U=75U=75U=75U=75U=75U=75U +M=75U=75U=75U=75U=75U=75U=75U=75U=75U=75U=75U=75U=0`````"```` +M```````L0"!S+F4```````T*#?\```!^```````````"``````````````"I +M```````O`````/___^0````!`````````P#__W5U=75U=75U=75U=75U=75U +M=0`````"```````````L0"!S+F)S,?P1<P!```,`"&MK,FM(:VMK145%145% +,P45%145%1?____\$ +` +end + diff --git a/libarchive/test/test_read_format_7zip_sfx_elf64trunc.elf.uu b/libarchive/test/test_read_format_7zip_sfx_elf64trunc.elf.uu new file mode 100644 index 000000000000..512da918218b --- /dev/null +++ b/libarchive/test/test_read_format_7zip_sfx_elf64trunc.elf.uu @@ -0,0 +1,5 @@ +begin 664 test_read_format_7zip_sfx_elf64trunc.elf +M?T5,1@("```````````````````````````````````````````````````` +2```````````````````H``$` +` +end diff --git a/libarchive/test/test_read_format_cab_lzx_oob.c b/libarchive/test/test_read_format_cab_lzx_oob.c new file mode 100644 index 000000000000..a4c15d62f789 --- /dev/null +++ b/libarchive/test/test_read_format_cab_lzx_oob.c @@ -0,0 +1,45 @@ +#include "test.h" + +/* + * Regression test for Heap Out-of-Bounds Write in CAB LZX decoder. + * This ensures that a malformed CFDATA uncompressed size does not + * bypass physical buffer limits and cause memory corruption during skips. + */ +DEFINE_TEST(test_read_format_cab_lzx_oob) +{ + const char *refname = "test_read_format_cab_lzx_oob.cab"; + struct archive *a; + struct archive_entry *ae; + const void *buff; + size_t size; + int64_t offset; + + /* * The test framework will automatically find 'test_read_format_cab_lzx_oob.cab.uu', + * decode it, and place the binary '.cab' in the temporary test directory. + */ + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_cab(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + + /* If it fails to open, there's a problem with the test setup/file */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); + + /* Read the header of the malformed entry */ + if (ARCHIVE_OK == archive_read_next_header(a, &ae)) { + /* * We attempt to read a block to initialize the LZX state machine. + * We do not assert the result because the file is intentionally malformed. + * Regardless of success or failure, we force a skip to test state handling + * and trigger the vulnerability. + */ + archive_read_data_block(a, &buff, &size, &offset); + archive_read_data_skip(a); + /* * Optional: We could assert that the error string contains our patch message, + * but simply surviving without a segfault/ASAN violation is the primary goal + * for fuzzing regression tests. + */ + } + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +}
\ No newline at end of file diff --git a/libarchive/test/test_read_format_cab_lzx_oob.cab.uu b/libarchive/test/test_read_format_cab_lzx_oob.cab.uu new file mode 100644 index 000000000000..2f453ef27116 --- /dev/null +++ b/libarchive/test/test_read_format_cab_lzx_oob.cab.uu @@ -0,0 +1,11 @@ +begin 664 test_read_format_cab_lzx_oob.cab +M35-#1@````!!``"2DI*2DI(````````2Y``!``$``,2PW@``'P$```$`0Q`! +M`3O2T@D)"0D)"0D)``````````````"RLK*RLK*RLK*RLK*RLK*RLK(*,``` +M````````````````LK*2X____[:RL@``````````LK*R"C`````````````` +M`````+*RDN/___^VLK(```````````"R'YV)3``````````````0$!`0$!`0 +M$!`0$!D0$!`0$!`0$!`0$!`0$!`0$!#___\/$!`0`````````$`0$`!`,#<P +M-S`R````,#82SWXO+R\`_P`````````````````````````````````````` +M``````#U\DH*-S`R````,#82SWXO+R\`_P`````````````````````````` +.```````````````````` +` +end diff --git a/libarchive/test/test_read_format_cab_skip_malformed.c b/libarchive/test/test_read_format_cab_skip_malformed.c new file mode 100644 index 000000000000..05cc80b79c93 --- /dev/null +++ b/libarchive/test/test_read_format_cab_skip_malformed.c @@ -0,0 +1,41 @@ +#include "test.h" + +DEFINE_TEST(test_read_format_cab_skip_malformed) +{ + /* Reference to the malformed CAB file */ + const char *refname = "test_read_format_cab_skip_malformed.cab"; + struct archive *a; + struct archive_entry *ae; + void *buffer; + size_t buffersize; + + /* Extract the reference file into the test sandbox */ + extract_reference_file(refname); + + /* Read the entire file into memory */ + buffer = slurpfile(&buffersize, "%s", refname); + assert(buffer != NULL); + + /* Initialize the archive reader */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + + /* Read from memory (a prerequisite for triggering this specific bug) */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buffer, buffersize)); + + /* Simulate the parsing flow to trigger the implicit skip routine */ + while (archive_read_next_header(a, &ae) == ARCHIVE_OK) { + const void *buff; + size_t size_read; + int64_t offset; + while (archive_read_data_block(a, &buff, &size_read, &offset) == ARCHIVE_OK) { + /* Consume data. This will fail quickly due to the malformed payload. */ + } + } + + /* Clean up. If the patch is effective, the program reaches here safely. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + free(buffer); +}
\ No newline at end of file diff --git a/libarchive/test/test_read_format_cab_skip_malformed.cab.uu b/libarchive/test/test_read_format_cab_skip_malformed.cab.uu new file mode 100644 index 000000000000..7ec83433546d --- /dev/null +++ b/libarchive/test/test_read_format_cab_skip_malformed.cab.uu @@ -0,0 +1,95 @@ +begin 664 test_read_format_cab_skip_malformed.cab +M35-#1@````!!``"2DI*2DI(````````2Y``!``$``,2PW@``'P$``-(!```! +M.]+2"0D)"0D)"0D)"0D)"0D)"0FRLK*R"0D)"0D)"0D)"0D)LK*RLK*RLK(` +M``````````````````"RLK*RLK*RLK*RLK*RLK*RLK(*,``````````````` +M````LK*RX____[:RL@```````````````#`W,"]`````"G!P`````&UDL@HP +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````%!+`P0````!#`P,#`P,#`P,#`P,#```````````````__\```3_ +M``!(___H````````````````````````````````````````____________ +M____________________________________________________```````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M@```````````````@`````$````````````````````````````````````` +M````````````````````````````````````````````#`H,#````'H,#`P` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````#__P``!/\``$C__^@```````````#_________________________ +M______________________________________\````````````````````` +M`"\O+R\O+R\O+R\O+R\O+R\O+R\O+R\G+PHQ-C4P+U):22\P-S!,4EI)"@HO +M=6YS970@<F$@("T@("!/3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T\@(2`@("`@ +M+2`@("`@("`@(",@("`@("`@("L@("`@("`@("`@("`@("`@("`@("`@("`@ +M("`K('A,4EI)"@H*("`@("`@(``````````````````````````````````` +M```````````````````````````````````````````````````,]@P,#`H* +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````#__P``!/\``$C__^@````` +M`%``````````````````````````````````________________________ +M________________________________________```````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````````````@``````` +M````````@`````$````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````#__P``!/\``$C__^@` +M``````````#_________________________________________________ +M______________\````````````````````````````````````````````` +M`````````````````````%!+`P0````!#`P,#`P,#`P,#`P,#```#`H,#``` +M`'H,```````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````,#`SV``````````````````````P, +M#`H*`/__```$_P``2/__Z````````````%#_________________________ +M______________________________________\````````````````````` +M````````````````````````````````````````````+R\P23@*"DQ:3#`P +M"DQ26DD*"DQ:+PH*,#`W,"\O,#<P+R\O+R\O+S!).`H*3%I,,"\P-S!,4EI) +M"@I,6B\O"F)E9VEN-F%E<RUB-"`Q(%TP-#`P5T%20R\O25HX"DQ,,`I,4EI) +M"@I,6B\O-S`W"DQ:3#`O,#<P3%):20H*3%HO+PIB96=I;BUB87-E-C0@-B`P +M-#`P5T%20R\O25HX"DQ,,`I,4EI)"@I,6B\O-S`W,#<O+R]:4B\O+R\O"C!@ +M-S`W,#$*#8V-C8V-C8V-C8V-C8V-C8V-C5!+`P10"@`*"C`P-S`O+S`W,"\O +M+R\O+R\P23@*"DQ:3#`O,#<P3%):20H*3%HO+PIB96=I;BUB87-E-C0@,2`P +M-#`P5T%20R\O25HX"DQ,"DQ:3#`O,#<P3%):20H*3%HO+PIB96=I;BUB87-E +M-C0@,2`P-#`P5T%20R\O25HV"DQ,,`I,4EI)"@I,6B\*"C`P-S`O+S`W,"\O +M+R\O+R\P23@*"DQ:3#`O,#<P3%):20H*3%HO+PIB90``V/\M`?\-__\-_RO_ +M_?____\F__\+____B?\*)PH``')R<G)R<G)R<G+_____________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________<G)R<G)R +M<G)R<G)R<G)R<G)R<G)R<G)R<G)R<G)R<G)R<G)R<G)R<G)R<G)R<G)``!0` +M`````````````````$#_____"`1W2"__0`#D$P`G_D3________NXEQ<7%QR +M7#`P-S=<,#)<7%Q<7%Q<?%Q<7%Q<<EPP,#<W7#`R7%Q<7%Q<7%Q<,#)<7%Q< +M7%Q<7')<,#`W-UPP,EQ<7%Q<7"L*=75,6B\O"F)E9VEN+6)A<V4V-"`V(#`T +M,#!705)#+R])6C@*3"`Q(#`T,#!705)#+R])6C@*3$P*3%I,,"\P-S!,4EI) +M"@I,6B\O"F)E9VEN+6)A<V4V-"`Q(#`T,#!705)#+R])6C@*3$PP"DQ26DD* +M"DQ:+PH*,#`W,"\O,#<P+R\O+R\O+S!).`H*3%I,,"\P-S!,4EI)"@I,6B\O +M"F)E9VEN+6)A<V4V-"`Q,S`T,#!705)#+R])6C@*3$PP"DQ26DD*"DQ:+R\W +M,#<*3%I,,"\P-S!,4EI)"@I,6B\O"F)E9VEN+6)A<V4V-"`V(#`T,#!705)# +M+R])6C@*3$PP"DQ26DD*"DQ:+R\W,#<P-R\O+UI2+R\O+R\O+R\O-S`W"DQ: +M3#`O04Y325\P-S!,4EI)"@I,6B\O"F)E9VEN+6)A<V4V-"`V(#`T,#!705)# +M+R])6CP*3$PP"DQ26DD*"DQ:+R\W,#<P-R\O+UI2+R\O+R\O+R\O+R\O+R\O +M+R\O+R\O+R\O+R\P23@*"DQ:3"\O+R\O+R\P23@*"DQ:3#`O,#<P3%):20H* +M3%HO+PIB96=I;BUB87-E-C0@,2`P-#`P5T%20R\O25HX"DQ,,`I,4EI)"@I, +M6B\O-S`W"DQ:3#`O,#<P3%):20H*3%HO+PIB96=I;BUB87-/-C0@-B`P-#`P +M5T%20R\O25HX"DQ,,`I,4EI)"@I,6B\O-S`W,#<O+R]:4B\O+R\O+R\O+S<P +M-PI,6DPP+S`W,$Q26DD*"DQ:+R\*8F5G:6XM8F%S938T(#8@,#0P,%=!4D,O +M,#<P3%):20H*3%HO+PIB96=I;BUB87-E-C0@,2!=,#0P,%=!4D,O+TE:.`I, +M3#`*3%):20H*3%HO+S<P-PI,6DPP+S`W,$Q26DD*"DQ:+R\*8F5G:6XM8F%S +M938T(#8@,#0P,%=!4D,O+TE:.`I,3#`*3%):20H*,!^+#@`````````````` +M```````+``````#'<?\```````````L``````,=Q_____U):20```````!`D +M````````3%HO+S<P-S`W+R\O6E(O+R]Z+R\*,&`W,#<P,0H-"@U=2@T*#0HN +M+@H*#0!$`````%Q<7%QA7%Q<55Q<05PR*5Q<7%Q<7%Q<7%PP7%Q!7#(I7%Q< +M7%Q<7%Q<7#!<7$%<,BE<7%Q<85Q<7%5<7$%<,BE<7%Q<7%Q<7%Q<,%Q<7%Q< +M7%Q<7%Q57%Q!7#(I7`D)"0D)"0D)"0D)"0D)"0D)"0D)"@````!%1@"']@`` +!```` +` +end diff --git a/libarchive/test/test_read_format_iso_zisofs_overflow.c b/libarchive/test/test_read_format_iso_zisofs_overflow.c new file mode 100644 index 000000000000..bad52b154acd --- /dev/null +++ b/libarchive/test/test_read_format_iso_zisofs_overflow.c @@ -0,0 +1,104 @@ +/*- + * Copyright (c) 2025 + * 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" + +/* + * Verify that a crafted ISO9660 image with an invalid zisofs block-size + * exponent (pz_log2_bs) is handled gracefully. + * + * The ZF extension in the Rock Ridge entry stores pz_log2_bs as a raw + * byte from the image. The zisofs spec only permits values 15-17. + * Values outside that range can cause: + * - Undefined behavior via oversized bit shifts (any platform) + * - Integer overflow in block pointer allocation on 32-bit platforms, + * leading to a heap buffer overflow write + * + * The test image has pz_log2_bs=2 (out of spec) combined with + * pz_uncompressed_size=0xFFFFFFF9. On 32-bit, (ceil+1)*4 overflows + * size_t to 0, malloc(0) returns a tiny buffer, and the code attempts + * to write ~4GB into it. On 64-bit the allocation is huge and safely + * fails. + * + * We verify the fix by checking archive_entry_size() after reading the + * header. When pz_log2_bs validation rejects the bad value (pz=0), + * the entry keeps its raw on-disk size (small). Without the fix, + * the reader sets the entry size to pz_uncompressed_size (0xFFFFFFF9). + * + * We intentionally do NOT call archive_read_data() here. Without the + * fix, the data-read path triggers a heap buffer overflow on 32-bit + * that silently corrupts the process heap, causing later tests to + * crash rather than this one. + */ +DEFINE_TEST(test_read_format_iso_zisofs_overflow) +{ + const char reffile[] = "test_read_format_iso_zisofs_overflow.iso"; + struct archive *a; + struct archive_entry *ae; + int r = ARCHIVE_OK; + int found_regular_file = 0; + + extract_reference_file(reffile); + 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, reffile, 10240)); + + while ((r = archive_read_next_header(a, &ae)) == ARCHIVE_OK || + r == ARCHIVE_WARN) { + /* + * With the fix, pz_log2_bs=2 is rejected and pz is set + * to 0, so the entry keeps its small raw size from the + * ISO directory record. Without the fix, zisofs sets + * the entry size to pz_uncompressed_size (0xFFFFFFF9). + * + * We intentionally do NOT call archive_read_data(). + * Without the fix, the data-read path triggers a heap + * buffer overflow on 32-bit that silently corrupts the + * process heap, causing later tests to crash rather + * than this one. + */ + if (archive_entry_filetype(ae) == AE_IFREG) { + la_int64_t sz = archive_entry_size(ae); + failure("entry \"%s\" has size %jd" + "; expected < 1 MiB" + " (if size is 4294966265 = 0xFFFFFFF9, the" + " pz_log2_bs validation is missing)", + archive_entry_pathname(ae), (intmax_t)sz); + assert(sz < 1024 * 1024); + found_regular_file = 1; + } + } + + /* Iteration must have completed normally. */ + assertEqualInt(ARCHIVE_EOF, r); + + /* The PoC image contains a regular file; if we never saw one, + * something is wrong with the test image. */ + assert(found_regular_file); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_format_iso_zisofs_overflow.iso.uu b/libarchive/test/test_read_format_iso_zisofs_overflow.iso.uu new file mode 100644 index 000000000000..5e7dcc3750ac --- /dev/null +++ b/libarchive/test/test_read_format_iso_zisofs_overflow.iso.uu @@ -0,0 +1,1096 @@ +begin 664 test_read_format_iso_zisofs_overflow.iso +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````!0T0P,#$!```````````````````````````````````````` +M````4$]#7U=2251%`````````````````````````````````````````!@` +M```````8```````````````````````````````````````````!```!`0`` +M`0`("``*````````"A(`````````````$@`````B`!,````````3``@````` +M"`!Z`1D,`````@```0```0$````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````$````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````/]#1#`P,0$````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````0`3`````0`````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!5`!,````````3``@` +M````"`!Z`1D,`````@```0```0$`4U`'`;[O`%!8+`'M00````!![0(````` +M```"``````````````````````$````````!(@`3````````$P`(``````@` +M>@$9#`````(```$```$!`7T`%````````!00"``````($'H!&0P````````! +M```!#D]615)&3$]7+D))3CLQ`%I&$`%P>@0"^?O__P````!.31$!`$]615)& +M3$]7+D))3E!8+`&D@0````"!I`$````````!``````````````````````(` +M```````"```````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#?D4Y;)V]8'^?O__P0"``!!0D-$04)#1$%"0T1!0D-$04)# +M1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$ +M04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1! +M0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%" +M0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)# +M1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$ +M04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1! +M0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%" +M0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)# +M1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$ +M04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1! +M0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%" +M0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)# +M1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$ +M04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1! +M0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%" +M0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)# +M1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$ +M04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1! +M0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%" +M0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)# +M1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$ +M04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1! +M0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%" +M0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)# +M1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$ +M04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1! +M0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%" +M0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)# +M1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$ +M04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1! +M0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%" +M0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)# +M1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$ +M04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1! +M0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%" +M0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)# +M1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$ +M04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1! +M0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%" +M0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)# +M1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$ +M04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1! +M0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%" +M0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)# +M1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$04)#1$%"0T1!0D-$ +M04)#1``````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +,```````````````` +` +end diff --git a/libarchive/test/test_read_format_lha_oversize_header.c b/libarchive/test/test_read_format_lha_oversize_header.c new file mode 100644 index 000000000000..fbdbd671df7c --- /dev/null +++ b/libarchive/test/test_read_format_lha_oversize_header.c @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 2026 Tim Kientzle + * 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_TEST(test_read_format_lha_oversize_header) +{ + const char *refname = "test_read_format_lha_oversize_header.lzh"; + extract_reference_file(refname); + struct archive_entry *ae; + struct archive *a; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); + + /* First 18 entries in the test file are well-formed */ + for (int i = 0; i < 18; i++) { + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + } + + /* 19th has an oversized header */ + assertEqualInt(ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_format_lha_oversize_header.lzh.uu b/libarchive/test/test_read_format_lha_oversize_header.lzh.uu new file mode 100644 index 000000000000..e562e440a777 --- /dev/null +++ b/libarchive/test/test_read_format_lha_oversize_header.lzh.uu @@ -0,0 +1,60 @@ +begin 644 test_read_format_lha_oversize_header.lzh +M)L`M;&AD+0```````````$@B[!``!&1I<EP``%4`@5$!`.A!Z0/I`R?X+6QH +M9"T```````````!((NP0``5D:7(R7```50"!40$`[4'I`^D#.'PM;&AD+0`` +M`````````4@C[!``%F1I<C)<<WEM;&EN:S%\+BY<9FEL93$``%4``J,"`.VA +MZ0/I`SA^+6QH9"T```````````%((^P0`!9D:7(R7'-Y;6QI;FLR?"XN7&9I +M;&4R``!5``*C`@#MH>D#Z0,GO2UL:#4M(@```#P`````2"+L(``%9FEL93&D +MYU4`@5$!`*2!Z0/I`P`80FYIQ>/Z`=-:'>9%#"P%J!\CH0"/GE$,.W6FMSD% +M*_4G02UL:#4M(@```$X`````2"+L(``%9FEL93+5%54`@5$!`+:!Z0/I`P`8 +M0FYIQV/Z`=.:'.9%#"P%J-\+H0"/'E$,.W6FMSD%*_T9?RUL:&0M&@`````` +M````2"+L(`$```!5!P`"9&ER_P4`4.A!!P!1Z0/I`P<`5(%1`0```!F!+6QH +M9"T;``````````!((NP@`0```%4(``)D:7(R_P4`4.U!!P!1Z0/I`P<`5(%1 +M`0```!YQ+6QH9"TG``````````%((^P@`05F:6QE,0``510``F1I<C+_<WEM +M;&EN:S%\+B[_!0!0[:$'`%'I`^D#!P!4`J,"````'G(M;&AD+2<````````` +M`4@C["`!!69I;&4R``!5%``"9&ER,O]S>6UL:6YK,GPN+O\%`%#MH0<`4>D# +MZ0,'`%0"HP(````>!BUL:#4M-0```#P`````2"+L(`$%9FEL93&DYU4%`%"D +M@0<`4>D#Z0,'`%2!40$`````&$)N:<7C^@'36AWF10PL!:@?(Z$`CYY1##MU +MIK<Y!2OU'G@M;&@U+34```!.`````$@B["`!!69I;&4RU155!0!0MH$'`%'I +M`^D#!P!4@5$!`````!A";FG'8_H!TYH<YD4,+`6HWPNA`(\>40P[=::W.04K +M_34`+6QH9"T``````````(%1`0`@`@``504```7>`P`!!P`"9&ER_P4`4.A! +M!P!1Z0/I`P``-@`M;&AD+0``````````@5$!`"`"``!5!0``")D#``$(``)D +M:7(R_P4`4.U!!P!1Z0/I`P``1P`M;&AD+0```````````J,"`"`"``!5!0`` +MM*D(``%F:6QE,10``F1I<C+_<WEM;&EN:S%\+B[_!0!0[:$'`%'I`^D#``!' +M`"UL:&0M```````````"HP(`(`(``%4%``"'[0@``69I;&4R%``"9&ER,O]S +M>6UL:6YK,GPN+O\%`%#MH0<`4>D#Z0,``#,`+6QH-2TB````/````(%1`0`@ +M`J3G504``/T!"``!9FEL93$%`%"D@0<`4>D#Z0,````80FYIQ>/Z`=-:'>9% +M#"P%J!\CH0"/GE$,.W6FMSD%*_4S`"UL:#4M(@```$X```"!40$`(`+5%54% +M```OQ@@``69I;&4R!0!0MH$'`%'I`^D#````&$)N:<=C^@'3FASF10PL!:C? +M"Z$`CQY1##MUIK<Y!2O]!``M;&AD+0``````````@5$!`"`#``!-?/[___\` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````$:D`P``!0````$)`````F1I +M<O\'````0!``&0```/_M00`````````````,%?Y,1!K^3!T```!!S-]1M/Z5 +MRP&`UD``J+*=`0!Z#]`!ELL!"``````NKP<`````!``M;&AD+0`````````` +M@5$!`"`#``!-?0````D```!&I`,```4````!"@````)D:7(R_P<```!`$``9 +M````_^U!`````````````"$:_DQ$&OY,'0```$%*@6Z[`9;+`8#60`"HLIT! +M`'H/T`&6RP$(`````'T7!P`````$`"UL:#4M)````#P```"!40$`(`.DYTUQ +M````"0```$:D`P``"@````%F:6QE,1D```#_I($`````````````QQ3^3",: +M_DP=````031"HHK^E<L!@-9``*BRG0'^<J2\`9;+`0@`````"O$'```````9 +M0FV1J+1V@'IK0ZGID/-H#J@6.H0"'V^-&353:F^XA-UZ@`0`+6QH-2TD```` +M3@```(%1`0`@`]4537$````)````1J0#```*`````69I;&4R&0```/^D@0`` +M```````````A&OY,(QK^3!T```!!_D5SNP&6RP&`UD``J+*=`5C5IKP!ELL! +M"`````!!W@<``````!E";9&H[':`>G-#B>F0\V@.J,8:A`(>;XT9-5-J;[B$ +MW7Z`-0`M;&AD+0``````````@5$!`"`"``!5!40:_DP=````0<S?4;3^E<L! +M@-9``*BRG0$`>@_0`9;+`0@`````+J\'``````0`+6QH9"T``````````(%1 +M`0`@`P``37T````)````1J0#```%`````0H````"9&ER,O\'````0!``&0`` +M`/_M00`````````````A&OY,1!K^3!T```!!2H%NNP&6RP&`UD``J+*=`0!Z +M#]`!ELL!"`````!]%P<`````!``M;&@U+20````\````@5$!`"`#I.=-<0`` +M``D```!&I`,```H````!9FEL93$9````_Z2!`````````````,<4_DPC&OY, +M'0```$$T0J**_I7+`8#60`"HLIT!_G*DO`&6RP$(``````KQ!P``````&4)M +MD:BT=H!Z:T.IZ9!1Z0/I`P```FUK=XVV['"Z\`>$(6[`2-EZ5P&P^!J*0MPV +M*IM]&^L37/)<Y+,0WC;RYN647;X'R_\P`E;2>[SD(6GCE`4$+,RA<%QVYXC% +M'H1Q`I@_B\H/L@(+W3`0@5CY6X%Q%WW+@7<`8(F7=77U]%5YG?`;3N&I:_6Y +MWA$,3F@?:)>FZ!<!"?.:#C/:',\PG@>:WRP0:TH8%&:/A#VMNUUD[D?+:#XK +M%3NMR(PSF4;V"^\X0/E3JMRQ46+7\I]S@7ZJNTX[ROSD+=\7\.O#I:W._S>P +M-B(W4`=N<T/$OT+5];U>*!<4AM0Y4$L'"(=02P,$\$*.O%TM;&@U+0``KPLX +M+4``2@````````"``````/________\`````````V0````"A```````````` +M````````````+6QH-RT```!8$,P.0&OJER*:CF[S6/=2*T4J8HB@[:HP^'7* +MK?(\7:Y+-"U'*^OXT210`,J%*>9(T9[(@N(DJ+A)A```3`]%Z8U.^3!F0_G- +17YFUYB_%6DWMSZ8'\Z-^CR@` +` +end diff --git a/libarchive/test/test_read_format_rar5_loop_bug.c b/libarchive/test/test_read_format_rar5_loop_bug.c new file mode 100644 index 000000000000..77dd78cccc48 --- /dev/null +++ b/libarchive/test/test_read_format_rar5_loop_bug.c @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 2026 Tim Kientzle + * 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_TEST(test_read_format_rar5_loop_bug) +{ + const char *reffile = "test_read_format_rar5_loop_bug.rar"; + struct archive_entry *ae; + struct archive *a; + const void *buf; + size_t size; + la_int64_t offset; + + extract_reference_file(reffile); + 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, reffile, 10240)); + + // This has just one entry + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + + // Read blocks until the end of the entry + while (ARCHIVE_OK == archive_read_data_block(a, &buf, &size, &offset)) { + } + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_free(a)); +} diff --git a/libarchive/test/test_read_format_rar5_loop_bug.rar.uu b/libarchive/test/test_read_format_rar5_loop_bug.rar.uu new file mode 100644 index 000000000000..3e470043fb70 --- /dev/null +++ b/libarchive/test/test_read_format_rar5_loop_bug.rar.uu @@ -0,0 +1,189 @@ +begin 644 test_read_format_rar5_loop_bug.rar +M4F%R(1H'`0#%&C,R`P$``)T-9%L.`@+P0`"`@`P`@`,``6'(WFP@`?\7_U/^ +M8@!.`B`H```````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +5```````````````````Y^;*!`@4` +` +end diff --git a/libarchive/test/test_read_set_format.c b/libarchive/test/test_read_set_format.c index 615dd8ae8022..2ea39045201f 100644 --- a/libarchive/test/test_read_set_format.c +++ b/libarchive/test/test_read_set_format.c @@ -177,6 +177,40 @@ DEFINE_TEST(test_read_append_wrong_filter) assertEqualInt(ARCHIVE_OK,archive_read_free(a)); } +DEFINE_TEST(test_read_append_lzop_filter) +{ + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR)); + r = archive_read_append_filter(a, ARCHIVE_FILTER_LZOP); + if (archive_liblzo2_version() != NULL) { + assertEqualIntA(a, ARCHIVE_OK, r); + } else if (canLzop()) { + // We're using an external program + assertEqualIntA(a, ARCHIVE_WARN, r); + } + + archive_read_free(a); +} + +DEFINE_TEST(test_read_append_grzip_filter) +{ + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR)); + r = archive_read_append_filter(a, ARCHIVE_FILTER_GRZIP); + // Grzip currently always uses an external program. + if (canGrzip()) { + assertEqualIntA(a, ARCHIVE_WARN, r); + } + + archive_read_free(a); +} + DEFINE_TEST(test_read_append_filter_program) { struct archive_entry *ae; diff --git a/libarchive/test/test_ustar_filename_encoding.c b/libarchive/test/test_ustar_filename_encoding.c index 1242bd1d3cd2..440d1b99276e 100644 --- a/libarchive/test/test_ustar_filename_encoding.c +++ b/libarchive/test/test_ustar_filename_encoding.c @@ -492,3 +492,43 @@ DEFINE_TEST(test_ustar_filename_encoding_UTF16_win) assertEqualMem(buff + 157, "\xE8\xA1\xA8.txt", 7); #endif } + +DEFINE_TEST(test_ustar_filename_encoding_fail_UTF16_win) +{ +#if !defined(_WIN32) || defined(__CYGWIN__) + skipping("This test is meant to verify unicode string handling" + " on Windows with UTF-16 names"); + return; +#else + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + /* Test the C locale by not calling setlocale. */ + + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_ustar(a)); + if (archive_write_set_options(a, "hdrcharset=CP437") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from UTF-16 to CP437."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set the filename using a UTF-16 string */ + archive_entry_copy_pathname_w(entry, L"\u8868.txt"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, entry)); + /* The pathname cannot even be represented in the current locale + for inclusion in the error message. */ + assertEqualString("Can't translate pathname to CP437", + archive_error_string(a)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +#endif +} diff --git a/libarchive/test/test_v7tar_filename_encoding.c b/libarchive/test/test_v7tar_filename_encoding.c new file mode 100644 index 000000000000..96594b12180e --- /dev/null +++ b/libarchive/test/test_v7tar_filename_encoding.c @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2003-2025 Tim Kientzle + * 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" + +#include <locale.h> + +DEFINE_TEST(test_v7tar_filename_encoding_fail_UTF16_win) +{ +#if !defined(_WIN32) || defined(__CYGWIN__) + skipping("This test is meant to verify unicode string handling" + " on Windows with UTF-16 names"); + return; +#else + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + /* Test the C locale by not calling setlocale. */ + + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_v7tar(a)); + if (archive_write_set_options(a, "hdrcharset=CP437") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from UTF-16 to CP437."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set the filename using a UTF-16 string */ + archive_entry_copy_pathname_w(entry, L"\u8868.txt"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, entry)); + /* The pathname cannot even be represented in the current locale + for inclusion in the error message. */ + assertEqualString("Can't translate pathname to CP437", + archive_error_string(a)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +#endif +} diff --git a/libarchive/test/test_warn_missing_hardlink_target.c b/libarchive/test/test_warn_missing_hardlink_target.c index d7fa5eb6c0fc..b3e5b95f06d4 100644 --- a/libarchive/test/test_warn_missing_hardlink_target.c +++ b/libarchive/test/test_warn_missing_hardlink_target.c @@ -37,7 +37,7 @@ DEFINE_TEST(test_warn_missing_hardlink_target) assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); assertEqualInt(ENOENT, archive_errno(a)); - assertEqualString("Hard-link target 'hardlink-target' does not exist.", + assertEqualString("Hard-link target 'hardlink-target' does not exist", archive_error_string(a)); archive_entry_free(ae); diff --git a/libarchive/test/test_write_disk.c b/libarchive/test/test_write_disk.c index fa0743f949f6..1e503cdb178a 100644 --- a/libarchive/test/test_write_disk.c +++ b/libarchive/test/test_write_disk.c @@ -233,6 +233,22 @@ static void create_reg_file_win(struct archive_entry *ae, const char *msg) assertEqualInt(st.st_size, sizeof(data)); free(fname); } +#else +static void create_fail(struct archive_entry *ae, int experr, + const char *msg) +{ + struct archive *ad; + struct stat st; + + /* Write the entry to disk. */ + assert((ad = archive_write_disk_new()) != NULL); + failure("%s", msg); + assertEqualIntA(ad, ARCHIVE_FAILED, archive_write_header(ad, ae)); + assertEqualIntA(ad, experr, archive_errno(ad)); + assertEqualInt(0, archive_write_free(ad)); + assertEqualInt(-1, stat(archive_entry_pathname(ae), &st)); + assertEqualInt(ENOENT, errno); +} #endif /* _WIN32 && !__CYGWIN__ */ DEFINE_TEST(test_write_disk) @@ -344,5 +360,18 @@ DEFINE_TEST(test_write_disk) " with unusable characters in its file name"); archive_entry_free(ae); free(fullpath); +#else /* !_WIN32 || __CYGWIN__ */ + /* A directory with a /../ in the middle */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "a/b/../b/file"); + archive_entry_set_mode(ae, S_IFREG | 0644); + /* First attempt should fail with EACCES */ + assertEqualInt(0, mkdir("a", 0111)); + create_fail(ae, EACCES, + "Test failing to create parent directory with /../"); + /* Now let it succeed */ + assertEqualInt(0, chmod("a", 0755)); + create(ae, "Test creating parent directory with /../"); + archive_entry_free(ae); #endif /* _WIN32 && !__CYGWIN__ */ } diff --git a/libarchive/test/test_write_disk_perms.c b/libarchive/test/test_write_disk_perms.c index 72b55179d86e..4f246e9bc2f0 100644 --- a/libarchive/test/test_write_disk_perms.c +++ b/libarchive/test/test_write_disk_perms.c @@ -26,6 +26,13 @@ #if !defined(_WIN32) || defined(__CYGWIN__) +#ifdef HAVE_GETEUID +#define getuid() geteuid() +#endif +#ifdef HAVE_GETEGID +#define getgid() getegid() +#endif + #define UMASK 022 static long _default_gid = -1; @@ -142,7 +149,7 @@ DEFINE_TEST(test_write_disk_perms) * and we're on a system where group ownership is inherited. * (Because we're not allowed to SGID files with defaultgid().) */ - assertEqualInt(0, chown(".", getuid(), getgid())); + assertChown(".", getuid(), getgid()); /* Create an archive_write_disk object. */ assert((a = archive_write_disk_new()) != NULL); @@ -208,7 +215,7 @@ DEFINE_TEST(test_write_disk_perms) if (getuid() == 0) { original_uid = getuid() + 1; try_to_change_uid = getuid(); - assertEqualInt(0, chown("dir_owner", original_uid, getgid())); + assertChown("dir_owner", original_uid, getgid()); } else { original_uid = getuid(); try_to_change_uid = getuid() + 1; diff --git a/libarchive/test/test_zip_filename_encoding.c b/libarchive/test/test_zip_filename_encoding.c index b6786f2c3b18..1cb394547066 100644 --- a/libarchive/test/test_zip_filename_encoding.c +++ b/libarchive/test/test_zip_filename_encoding.c @@ -622,3 +622,43 @@ DEFINE_TEST(test_zip_filename_encoding_UTF16_win) /* NOTE: ZIP does not support hardlinks */ #endif } + +DEFINE_TEST(test_zip_filename_encoding_fail_UTF16_win) +{ +#if !defined(_WIN32) || defined(__CYGWIN__) + skipping("This test is meant to verify unicode string handling" + " on Windows with UTF-16 names"); + return; +#else + struct archive *a; + struct archive_entry *entry; + char buff[4096]; + size_t used; + + /* Test the C locale by not calling setlocale. */ + + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + if (archive_write_set_options(a, "hdrcharset=CP437") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from UTF-16 to CP437."); + archive_write_free(a); + return; + } + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + entry = archive_entry_new2(a); + /* Set the filename using a UTF-16 string */ + archive_entry_copy_pathname_w(entry, L"\u8868.txt"); + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_size(entry, 0); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, entry)); + /* The pathname cannot even be represented in the current locale + for inclusion in the error message. */ + assertEqualString("Can't translate pathname to CP437", + archive_error_string(a)); + archive_entry_free(entry); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +#endif +} diff --git a/unzip/la_getline.c b/libarchive_fe/lafe_getline.c index 40ab35cde842..ebd9f1a894a7 100644 --- a/unzip/la_getline.c +++ b/libarchive_fe/lafe_getline.c @@ -7,12 +7,15 @@ * All rights reserved. */ -#include "bsdunzip_platform.h" +#include "lafe_platform.h" #ifndef HAVE_GETLINE #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif #ifdef HAVE_STDIO_H #include <stdio.h> #endif @@ -26,8 +29,10 @@ #include <string.h> #endif +#include "lafe_getline.h" + static ssize_t -la_getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) +lafe_getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) { char *ptr, *eptr; @@ -72,6 +77,6 @@ la_getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) ssize_t getline(char **buf, size_t *bufsiz, FILE *fp) { - return la_getdelim(buf, bufsiz, '\n', fp); + return lafe_getdelim(buf, bufsiz, '\n', fp); } #endif diff --git a/unzip/la_getline.h b/libarchive_fe/lafe_getline.h index d7588731943d..b10641ffd1eb 100644 --- a/unzip/la_getline.h +++ b/libarchive_fe/lafe_getline.h @@ -5,12 +5,19 @@ * All rights reserved. */ -#ifndef LA_GETLINE_H_INCLUDED -#define LA_GETLINE_H_INCLUDED +#ifndef LAFE_GETLINE_H_INCLUDED +#define LAFE_GETLINE_H_INCLUDED + +#include "lafe_platform.h" -#include <stdio.h> #ifndef HAVE_GETLINE +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#ifdef HAVE_STDIO_H +#include <stdio.h> +#endif ssize_t getline(char **buf, size_t *bufsiz, FILE *fp); #endif -#endif /* !LA_GETLINE_H_INCLUDED */ +#endif /* !LAFE_GETLINE_H_INCLUDED */ diff --git a/tar/bsdtar.c b/tar/bsdtar.c index 92e86fd6bd94..fbc0627a83b9 100644 --- a/tar/bsdtar.c +++ b/tar/bsdtar.c @@ -525,28 +525,28 @@ main(int argc, char **argv) if (archive_match_include_date(bsdtar->matching, ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER, bsdtar->argument) != ARCHIVE_OK) - lafe_errc(1, 0, "Error : %s", + lafe_errc(1, 0, "%s", archive_error_string(bsdtar->matching)); break; case OPTION_NEWER_CTIME_THAN: if (archive_match_include_file_time(bsdtar->matching, ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER, bsdtar->argument) != ARCHIVE_OK) - lafe_errc(1, 0, "Error : %s", + lafe_errc(1, 0, "%s", archive_error_string(bsdtar->matching)); break; case OPTION_NEWER_MTIME: /* GNU tar */ if (archive_match_include_date(bsdtar->matching, ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER, bsdtar->argument) != ARCHIVE_OK) - lafe_errc(1, 0, "Error : %s", + lafe_errc(1, 0, "%s", archive_error_string(bsdtar->matching)); break; case OPTION_NEWER_MTIME_THAN: if (archive_match_include_file_time(bsdtar->matching, ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER, bsdtar->argument) != ARCHIVE_OK) - lafe_errc(1, 0, "Error : %s", + lafe_errc(1, 0, "%s", archive_error_string(bsdtar->matching)); break; case OPTION_NODUMP: /* star */ @@ -618,28 +618,28 @@ main(int argc, char **argv) if (archive_match_include_date(bsdtar->matching, ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER, bsdtar->argument) != ARCHIVE_OK) - lafe_errc(1, 0, "Error : %s", + lafe_errc(1, 0, "%s", archive_error_string(bsdtar->matching)); break; case OPTION_OLDER_CTIME_THAN: if (archive_match_include_file_time(bsdtar->matching, ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER, bsdtar->argument) != ARCHIVE_OK) - lafe_errc(1, 0, "Error : %s", + lafe_errc(1, 0, "%s", archive_error_string(bsdtar->matching)); break; case OPTION_OLDER_MTIME: if (archive_match_include_date(bsdtar->matching, ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER, bsdtar->argument) != ARCHIVE_OK) - lafe_errc(1, 0, "Error : %s", + lafe_errc(1, 0, "%s", archive_error_string(bsdtar->matching)); break; case OPTION_OLDER_MTIME_THAN: if (archive_match_include_file_time(bsdtar->matching, ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER, bsdtar->argument) != ARCHIVE_OK) - lafe_errc(1, 0, "Error : %s", + lafe_errc(1, 0, "%s", archive_error_string(bsdtar->matching)); break; case OPTION_ONE_FILE_SYSTEM: /* GNU tar */ @@ -819,7 +819,7 @@ main(int argc, char **argv) if (archive_match_exclude_pattern_from_file( bsdtar->matching, bsdtar->argument, 0) != ARCHIVE_OK) - lafe_errc(1, 0, "Error : %s", + lafe_errc(1, 0, "%s", archive_error_string(bsdtar->matching)); break; case 'x': /* SUSv2 */ @@ -1026,7 +1026,7 @@ main(int argc, char **argv) if (bsdtar->return_value != 0) lafe_warnc(0, - "Error exit delayed from previous errors."); + "Error exit delayed from previous errors"); return (bsdtar->return_value); } diff --git a/tar/read.c b/tar/read.c index 7cbcfb19ff0a..4acbf6b2a9dc 100644 --- a/tar/read.c +++ b/tar/read.c @@ -255,7 +255,7 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer) break; p = archive_entry_pathname(entry); if (p == NULL || p[0] == '\0') { - lafe_warnc(0, "Archive entry has empty or unreadable filename ... skipping."); + lafe_warnc(0, "Archive entry has empty or unreadable filename ... skipping"); bsdtar->return_value = 1; continue; } diff --git a/tar/util.c b/tar/util.c index 6e41e49de133..6b21e8aeff2b 100644 --- a/tar/util.c +++ b/tar/util.c @@ -715,8 +715,8 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry) /* Use uname if it's present, else uid. */ p = archive_entry_uname(entry); if ((p == NULL) || (*p == '\0')) { - snprintf(tmp, sizeof(tmp), "%lu ", - (unsigned long)archive_entry_uid(entry)); + snprintf(tmp, sizeof(tmp), "%lld ", + (long long)archive_entry_uid(entry)); p = tmp; } w = strlen(p); @@ -730,8 +730,8 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry) fprintf(out, "%s", p); w = strlen(p); } else { - snprintf(tmp, sizeof(tmp), "%lu", - (unsigned long)archive_entry_gid(entry)); + snprintf(tmp, sizeof(tmp), "%lld", + (long long)archive_entry_gid(entry)); w = strlen(tmp); fprintf(out, "%s", tmp); } diff --git a/tar/write.c b/tar/write.c index b39a397707ba..abff3831bcda 100644 --- a/tar/write.c +++ b/tar/write.c @@ -301,7 +301,7 @@ tar_mode_r(struct bsdtar *bsdtar) archive_read_free(a); close(bsdtar->fd); lafe_errc(1, 0, - "Cannot append to compressed archive."); + "Cannot append to compressed archive"); } /* Keep going until we hit end-of-archive */ format = archive_format(a); @@ -329,7 +329,7 @@ tar_mode_r(struct bsdtar *bsdtar) if (format != (int)(archive_format(a) & ARCHIVE_FORMAT_BASE_MASK) && format != ARCHIVE_FORMAT_EMPTY) { lafe_errc(1, 0, - "Format %s is incompatible with the archive %s.", + "Format %s is incompatible with the archive %s", cset_get_format(bsdtar->cset), bsdtar->filename); } } else { @@ -394,12 +394,12 @@ tar_mode_u(struct bsdtar *bsdtar) archive_read_free(a); close(bsdtar->fd); lafe_errc(1, 0, - "Cannot append to compressed archive."); + "Cannot append to compressed archive"); } if (archive_match_exclude_entry(bsdtar->matching, ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER | ARCHIVE_MATCH_EQUAL, entry) != ARCHIVE_OK) - lafe_errc(1, 0, "Error : %s", + lafe_errc(1, 0, "%s", archive_error_string(bsdtar->matching)); /* Record the last format determination we see */ format = archive_format(a); @@ -786,7 +786,7 @@ copy_file_data_block(struct bsdtar *bsdtar, struct archive *a, * continue. */ lafe_warnc(0, "%s: Truncated write; file may " - "have grown while being archived.", + "have grown while being archived", archive_entry_pathname(entry)); return (0); } @@ -805,7 +805,7 @@ copy_file_data_block(struct bsdtar *bsdtar, struct archive *a, /* Write was truncated; warn but continue. */ lafe_warnc(0, "%s: Truncated write; file may have grown " - "while being archived.", + "while being archived", archive_entry_pathname(entry)); return (0); } @@ -1052,14 +1052,14 @@ test_for_append(struct bsdtar *bsdtar) if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL) lafe_errc(1, 0, "no files or directories specified"); if (bsdtar->filename == NULL) - lafe_errc(1, 0, "Cannot append to stdout."); + lafe_errc(1, 0, "Cannot append to stdout"); if (stat(bsdtar->filename, &s) != 0) return; if (!S_ISREG(s.st_mode) && !S_ISBLK(s.st_mode)) lafe_errc(1, 0, - "Cannot append to %s: not a regular file.", + "Cannot append to %s: not a regular file", bsdtar->filename); /* Is this an appropriate check here on Windows? */ diff --git a/test_utils/test_common.h b/test_utils/test_common.h index a9df300e3be8..2f19597dee6b 100644 --- a/test_utils/test_common.h +++ b/test_utils/test_common.h @@ -163,6 +163,9 @@ /* change file/directory permissions and errors if it fails */ #define assertChmod(pathname, mode) \ assertion_chmod(__FILE__, __LINE__, pathname, mode) +/* change file/directory ownership and errors if it fails */ +#define assertChown(pathname, user, group) \ + assertion_chown(__FILE__, __LINE__, pathname, user, group) /* Assert two files have the same file flags */ #define assertEqualFflags(patha, pathb) \ assertion_compare_fflags(__FILE__, __LINE__, patha, pathb, 0) @@ -279,6 +282,7 @@ void failure(const char *fmt, ...) __LA_PRINTFLIKE(1, 2); int assertion_assert(const char *, int, int, const char *, void *); int assertion_chdir(const char *, int, const char *); int assertion_chmod(const char *, int, const char *, int); +int assertion_chown(const char *, int, const char *, int, int); int assertion_compare_fflags(const char *, int, const char *, const char *, int); int assertion_empty_file(const char *, int, const char *); diff --git a/test_utils/test_main.c b/test_utils/test_main.c index dbd3fcf60e9a..1f641bbe8db7 100644 --- a/test_utils/test_main.c +++ b/test_utils/test_main.c @@ -96,6 +96,12 @@ extern char **environ; # define USE_POSIX_SPAWN 1 # endif #endif +#if !defined(_WIN32) +# if HAVE_PWD_H && HAVE_GETEUID && HAVE_GETEGID +# include <pwd.h> +# define RUN_TEST_UNPRIV 1 +# endif +#endif #ifndef nitems #define nitems(arr) (sizeof(arr) / sizeof((arr)[0])) @@ -179,6 +185,14 @@ const char *testprogfile; const char *testprog; #endif +#ifdef RUN_TEST_UNPRIV +/* Unprivileged user to run as */ +const char *tuser = "nobody"; +/* Original and test credentials */ +uid_t ouid, tuid; +uid_t ogid, tgid; +#endif + #if defined(_WIN32) && !defined(__CYGWIN__) static void *GetFunctionKernel32(const char *); static int my_CreateSymbolicLinkA(const char *, const char *, int); @@ -632,6 +646,22 @@ assertion_chmod(const char *file, int line, const char *pathname, int mode) } +/* change file/directory ownership and errors if it fails */ +int +assertion_chown(const char *file, int line, const char *pathname, int user, + int group) +{ + assertion_count(file, line); +#ifdef HAVE_CHOWN + if (chown(pathname, (uid_t)user, (gid_t)group) == 0) + return (1); +#endif + failure_start(file, line, "chown(\"%s\", %d, %d)", pathname, + user, group); + failure_finish(NULL); + return (0); +} + /* Verify two integers are equal. */ int assertion_equal_int(const char *file, int line, @@ -3610,8 +3640,11 @@ test_run(int i, const char *tmpdir) exit(1); } testworkdir = workdir; - if (!assertMakeDir(testworkdir, 0755) - || !assertChdir(testworkdir)) { + if (!assertMakeDir(testworkdir, 0755) || +#ifdef RUN_TEST_UNPRIV + (tuser != NULL && !assertChown(testworkdir, tuid, tgid)) || +#endif + !assertChdir(testworkdir)) { fprintf(stderr, "ERROR: Can't chdir to work dir %s\n", testworkdir); exit(1); @@ -3620,10 +3653,28 @@ test_run(int i, const char *tmpdir) set_c_locale(); /* Record the umask before we run the test. */ umask(oldumask = umask(0)); +#ifdef RUN_TEST_UNPRIV + /* + * Temporarily drop privileges. + */ + if (tuser != NULL) { + (void)setegid(tuid); + (void)seteuid(tuid); + } +#endif /* * Run the actual test. */ (*tests[i].func)(); +#ifdef RUN_TEST_UNPRIV + /* + * Restore original credentials. + */ + if (tuser != NULL) { + (void)seteuid(ouid); + (void)setegid(ogid); + } +#endif /* * Clean up and report afterwards. */ @@ -3949,6 +4000,9 @@ main(int argc, char **argv) #endif char *pwd, *testprogdir, *tmp2 = NULL, *vlevel = NULL; char tmpdir_timestamp[32]; +#ifdef RUN_TEST_UNPRIV + struct passwd *pw; +#endif (void)argc; /* UNUSED */ @@ -4110,6 +4164,11 @@ main(int argc, char **argv) case 's': fail_if_tests_skipped = 1; break; +#ifdef RUN_TEST_UNPRIV + case 'U': + tuser = optarg; + break; +#endif case 'u': until_failure++; break; @@ -4194,6 +4253,28 @@ main(int argc, char **argv) } #endif +#ifdef RUN_TEST_UNPRIV + /* + * Check if we are root, and get user to run as. + */ + ouid = getuid(); + ogid = getgid(); + if (ouid == 0) { + if ((pw = getpwnam(tuser)) == NULL) { + fprintf(stderr, "ERROR: Unknown user %s\n", tuser); + exit(1); + } + tuid = pw->pw_uid; + tgid = pw->pw_gid; + printf("Will switch to user %s (uid %d gid %d)\n", tuser, + tuid, tgid); + } else { + tuser = NULL; + tuid = ouid; + tgid = ogid; + } +#endif + /* * Create a temp directory for the following tests. * Include the time the tests started as part of the name, diff --git a/unzip/CMakeLists.txt b/unzip/CMakeLists.txt index f3c62cb339c6..9fe21eeebe0a 100644 --- a/unzip/CMakeLists.txt +++ b/unzip/CMakeLists.txt @@ -13,11 +13,11 @@ IF(ENABLE_UNZIP) bsdunzip.h bsdunzip_platform.h cmdline.c - la_getline.c - la_getline.h la_queue.h ../libarchive_fe/lafe_err.c ../libarchive_fe/lafe_err.h + ../libarchive_fe/lafe_getline.c + ../libarchive_fe/lafe_getline.h ../libarchive_fe/lafe_platform.h ../libarchive_fe/passphrase.c ../libarchive_fe/passphrase.h diff --git a/unzip/bsdunzip.c b/unzip/bsdunzip.c index 14bd418f169c..aa849568ba7e 100644 --- a/unzip/bsdunzip.c +++ b/unzip/bsdunzip.c @@ -9,7 +9,7 @@ #include "bsdunzip_platform.h" #include "la_queue.h" -#include "la_getline.h" +#include "lafe_getline.h" #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> #endif @@ -884,9 +884,9 @@ list(struct archive *a, struct archive_entry *e) mtime = archive_entry_mtime(e); tm = localtime(&mtime); if (*y_str) - strftime(buf, sizeof(buf), "%m-%d-%G %R", tm); + strftime(buf, sizeof(buf), "%m-%d-%Y %R", tm); else - strftime(buf, sizeof(buf), "%m-%d-%g %R", tm); + strftime(buf, sizeof(buf), "%m-%d-%y %R", tm); pathname = archive_entry_pathname(e); if (!pathname) diff --git a/unzip/test/CMakeLists.txt b/unzip/test/CMakeLists.txt index 57ed651a58b0..45138202a9a3 100644 --- a/unzip/test/CMakeLists.txt +++ b/unzip/test/CMakeLists.txt @@ -13,6 +13,7 @@ IF(ENABLE_UNZIP AND ENABLE_TEST) test_basic.c test_doubledash.c test_glob.c + test_not_exist.c test_singlefile.c test_C.c test_p.c |
