diff --git a/UPDATING b/UPDATING index 4930fd68eb..546e5a2f6f 100644 --- a/UPDATING +++ b/UPDATING @@ -1,5 +1,11 @@ Updating Information for MidnightBSD users. +20260722: + libarchive 3.8.8: fixes CVE-2026-14164, a double-free in the RAR5 + reader (archive_read_support_format_rar5.c) that could crash + applications parsing a crafted RAR5 archive. Rebuild world and + restart applications that use libarchive. + 20260701: openssl: CVE-2026-45447 PKCS#7/S/MIME verification use-after-free fix. Rebuild world and restart applications using diff --git a/contrib/libarchive/NEWS b/contrib/libarchive/NEWS index d5e9769771..5c64b9dddb 100644 --- a/contrib/libarchive/NEWS +++ b/contrib/libarchive/NEWS @@ -1,3 +1,5 @@ +Jun 23, 2026: libarchive 3.8.8 released + Apr 13, 2026: libarchive 3.8.7 released Mar 10, 2026: libarchive 3.8.6 released diff --git a/contrib/libarchive/SECURITY.md b/contrib/libarchive/SECURITY.md index f2f60e792a..33c37e4700 100644 --- a/contrib/libarchive/SECURITY.md +++ b/contrib/libarchive/SECURITY.md @@ -1,9 +1,10 @@ # Security Policy -If you have discovered a security vulnerability in this project, please report it -privately. **Do not disclose it as a public issue.** This gives us time to work with you -to fix the issue before public exposure, reducing the chance that the exploit will be -used before a patch is released. +If you have discovered a security vulnerability in this project, +please report it privately. +**Do not disclose it as a public issue.** +This gives us time to work with you to fix the issue before public exposure, +reducing the chance that the exploit will be used before a patch is released. You may submit the report in the following ways: @@ -15,5 +16,11 @@ Please provide the following information in your report: - A description of the vulnerability and its impact - How to reproduce the issue -This project is maintained by volunteers on a reasonable-effort basis. As such, we ask -that you give us 90 days to work on a fix before public exposure. +While we welcome all reports, we can act most quickly if the report +includes a complete libarchive test case and a proposed fix. +See [doc/WRITING_TESTS.md](doc/WRITING_TESTS.md) for guidance on creating a reproduction test case. +You can provide the test case and proposed fix as separate patch files +prepared with `git format-patch` or `git diff`. + +This project is maintained by volunteers on a reasonable-effort basis. +We ask that you give us 90 days to work on a fix before public exposure. diff --git a/contrib/libarchive/build/ci/github_actions/freebsd.sh b/contrib/libarchive/build/ci/github_actions/freebsd.sh new file mode 100755 index 0000000000..fff74f6a6f --- /dev/null +++ b/contrib/libarchive/build/ci/github_actions/freebsd.sh @@ -0,0 +1,41 @@ +#!/bin/sh +set -eu + +if [ $# != 1 ] +then + echo "Usage: $0 prepare | test" + exit 1 +fi + +if [ "$1" = "prepare" ] +then + set -x -e + env ASSUME_ALWAYS_YES=yes pkg bootstrap -f + sed -i.bak -e 's,pkg+http://pkg.FreeBSD.org/\${ABI}/quarterly,pkg+http://pkg.FreeBSD.org/\${ABI}/latest,' /etc/pkg/FreeBSD.conf + pkg update + mount -u -o acls / + mkdir /tmp_acl_nfsv4 + MD=`mdconfig -a -t swap -s 128M` + newfs /dev/$MD + tunefs -N enable /dev/$MD + mount /dev/$MD /tmp_acl_nfsv4 + chmod 1777 /tmp_acl_nfsv4 + pkg install -y autoconf automake cmake gmake libiconv libtool pkgconf expat libxml2 liblz4 zstd +elif [ "$1" = "test" ] +then + set -e + echo "Additional NFSv4 ACL tests" + CURDIR=`pwd` + if [ "${BS}" = "cmake" ] + then + BIN_SUBDIR="bin" + else + BIN_SUBDIR=. + fi + BUILDDIR="${CURDIR}/build_ci/${BS}" + cd "$BUILDDIR" + TMPDIR=/tmp_acl_nfsv4 ${BIN_SUBDIR}/libarchive_test -r "${CURDIR}/libarchive/test" -v test_acl_platform_nfs4 +else + echo "Usage: $0 prepare | test" + exit 1 +fi diff --git a/contrib/libarchive/build/ci/github_actions/vcpkg.json b/contrib/libarchive/build/ci/github_actions/vcpkg.json new file mode 100644 index 0000000000..c636361a35 --- /dev/null +++ b/contrib/libarchive/build/ci/github_actions/vcpkg.json @@ -0,0 +1,15 @@ +{ + "dependencies": [ + "zlib", + "bzip2", + "liblzma", + "zstd" + ], + "vcpkg-configuration": { + "default-registry": { + "kind": "git", + "repository": "https://github.com/microsoft/vcpkg", + "baseline": "44819aa2a6c10e56065e2b0330e7d6c89d1d2574" + } + } +} diff --git a/contrib/libarchive/build/cmake/discover_tests.cmake.in b/contrib/libarchive/build/cmake/discover_tests.cmake.in new file mode 100644 index 0000000000..1a054bc63f --- /dev/null +++ b/contrib/libarchive/build/cmake/discover_tests.cmake.in @@ -0,0 +1,13 @@ +# Generated by CMake at configure time -- do not edit. +# Scans test source files for DEFINE_TEST() declarations and writes list.h. +set(_sources @SOURCES@) +set(_output "@OUTPUT@") +file(WRITE "${_output}" "") +foreach(_src ${_sources}) + if(_src MATCHES "test_[^/]+\\.c$") + file(STRINGS "${_src}" _lines REGEX "^DEFINE_TEST") + foreach(_line ${_lines}) + file(APPEND "${_output}" "${_line}\n") + endforeach() + endif() +endforeach() diff --git a/contrib/libarchive/contrib/oss-fuzz/libarchive_write_disk_fuzzer.cc b/contrib/libarchive/contrib/oss-fuzz/libarchive_write_disk_fuzzer.cc index 056bd16395..7392e394aa 100644 --- a/contrib/libarchive/contrib/oss-fuzz/libarchive_write_disk_fuzzer.cc +++ b/contrib/libarchive/contrib/oss-fuzz/libarchive_write_disk_fuzzer.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -17,10 +18,134 @@ static constexpr size_t kMaxInputSize = 64 * 1024; static char g_temp_dir[256] = {0}; +static char g_start_dir[512] = {0}; +static char g_extract_dir[512] = {0}; +static char g_outside_dir[512] = {0}; +static char g_sentinel_path[512] = {0}; + +static int write_file(const char* path, const char* data) { + FILE* f = fopen(path, "wb"); + size_t len = strlen(data); + size_t written; + if (f == NULL) { + return -1; + } + written = fwrite(data, 1, len, f); + if (fclose(f) != 0) { + return -1; + } + return written == len ? 0 : -1; +} + +static int sentinel_is_unchanged() { + char buf[32]; + FILE* f = fopen(g_sentinel_path, "rb"); + if (f == NULL) { + return 0; + } + size_t n = fread(buf, 1, sizeof(buf) - 1, f); + fclose(f); + buf[n] = '\0'; + return strcmp(buf, "outside-original") == 0; +} + +static int reset_temp_tree() { + if (g_start_dir[0] != '\0') { + if (chdir(g_start_dir) != 0) { + return -1; + } + } + remove_directory_tree(g_temp_dir); + if (mkdir(g_temp_dir, 0700) != 0) { + return -1; + } + + snprintf(g_extract_dir, sizeof(g_extract_dir), "%s/extract", g_temp_dir); + snprintf(g_outside_dir, sizeof(g_outside_dir), "%s/outside", g_temp_dir); + snprintf(g_sentinel_path, sizeof(g_sentinel_path), "%s/outside/sentinel", + g_temp_dir); + + if (mkdir(g_extract_dir, 0700) != 0 || mkdir(g_outside_dir, 0700) != 0) { + return -1; + } + + char existing[512]; + char existing_dir[512]; + char nested_existing[512]; + snprintf(existing, sizeof(existing), "%s/extract/existing", g_temp_dir); + snprintf(existing_dir, sizeof(existing_dir), "%s/extract/dir", g_temp_dir); + snprintf(nested_existing, sizeof(nested_existing), + "%s/extract/dir/existing", g_temp_dir); + if (mkdir(existing_dir, 0700) != 0) { + return -1; + } + + return write_file(g_sentinel_path, "outside-original") || + write_file(existing, "inside") || + write_file(nested_existing, "inside"); +} + +static void consume_path(DataConsumer* consumer, char* out, size_t out_size) { + static const char* const kPaths[] = { + "file", + "dir/file", + "dir/./file", + "dir//file", + "link", + "link/file", + "link/./file", + "link//file", + "../outside/sentinel", + "../outside/new-file", + "./../outside/sentinel", + "dir/../file", + "hardlink", + "hardlink-with-data", + "symlink", + "existing", + "dir/existing", + }; + uint8_t selector = consumer->consume_byte(); + if ((selector & 0x80) != 0) { + snprintf(out, out_size, "%s/extract/absolute-%u", g_temp_dir, selector); + } else if ((selector & 0x40) != 0) { + snprintf(out, out_size, "%s/outside/sentinel", g_temp_dir); + } else { + snprintf(out, out_size, "%s", + kPaths[selector % (sizeof(kPaths) / sizeof(kPaths[0]))]); + } +} + +static void consume_linkname(DataConsumer* consumer, char* out, + size_t out_size) { + static const char* const kTargets[] = { + "existing", + "dir/existing", + "link/sentinel", + "link/./sentinel", + "link//sentinel", + "../outside/sentinel", + "./../outside/sentinel", + "dir/../existing", + "missing-target", + }; + uint8_t selector = consumer->consume_byte(); + if ((selector & 0x80) != 0) { + snprintf(out, out_size, "%s/outside/sentinel", g_temp_dir); + } else if ((selector & 0x40) != 0) { + snprintf(out, out_size, "%s/extract/existing", g_temp_dir); + } else { + snprintf(out, out_size, "%s", + kTargets[selector % (sizeof(kTargets) / sizeof(kTargets[0]))]); + } +} extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { (void)argc; (void)argv; + if (getcwd(g_start_dir, sizeof(g_start_dir)) == NULL) { + g_start_dir[0] = '\0'; + } // Create a temporary directory for extraction snprintf(g_temp_dir, sizeof(g_temp_dir), "/tmp/fuzz_extract_XXXXXX"); if (mkdtemp(g_temp_dir) == NULL) { @@ -38,10 +163,19 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { return 0; } + if (reset_temp_tree() != 0 || chdir(g_extract_dir) != 0) { + return 0; + } + DataConsumer consumer(buf, len); struct archive *disk = archive_write_disk_new(); if (disk == NULL) { + if (g_start_dir[0] != '\0') { + if (chdir(g_start_dir) != 0) { + return 0; + } + } return 0; } @@ -54,8 +188,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (opt_flags & 0x08) flags |= ARCHIVE_EXTRACT_FFLAGS; if (opt_flags & 0x10) flags |= ARCHIVE_EXTRACT_OWNER; if (opt_flags & 0x20) flags |= ARCHIVE_EXTRACT_XATTR; - if (opt_flags & 0x40) flags |= ARCHIVE_EXTRACT_SECURE_SYMLINKS; - if (opt_flags & 0x80) flags |= ARCHIVE_EXTRACT_SECURE_NODOTDOT; + if (opt_flags & 0x40) flags |= ARCHIVE_EXTRACT_UNLINK; + if (opt_flags & 0x80) flags |= ARCHIVE_EXTRACT_SAFE_WRITES; + + flags |= ARCHIVE_EXTRACT_SECURE_SYMLINKS | + ARCHIVE_EXTRACT_SECURE_NODOTDOT | + ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS; archive_write_disk_set_options(disk, flags); archive_write_disk_set_standard_lookup(disk); @@ -66,45 +204,45 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { struct archive_entry *entry = archive_entry_new(); if (entry == NULL) break; - // Build a safe path within our temp directory - char safe_path[512]; - const char *name = consumer.consume_string(32); - snprintf(safe_path, sizeof(safe_path), "%s/%s", g_temp_dir, name); - - // Sanitize path to prevent traversal - char *p = safe_path; - while (*p) { - if (p[0] == '.' && p[1] == '.') { - p[0] = '_'; - p[1] = '_'; - } - p++; - } - - archive_entry_set_pathname(entry, safe_path); + char pathname[512]; + char linkname[512]; + consume_path(&consumer, pathname, sizeof(pathname)); + archive_entry_set_pathname(entry, pathname); - uint8_t ftype = consumer.consume_byte() % 3; + uint8_t ftype = consumer.consume_byte() % 4; mode_t mode; switch (ftype) { case 0: mode = S_IFREG | 0644; break; case 1: mode = S_IFDIR | 0755; break; + case 2: mode = S_IFLNK | 0777; break; default: mode = S_IFREG | 0644; break; } archive_entry_set_mode(entry, mode); + if (S_ISLNK(mode)) { + consume_linkname(&consumer, linkname, sizeof(linkname)); + archive_entry_set_symlink(entry, linkname); + archive_entry_set_size(entry, 0); + } else if (ftype == 3) { + consume_linkname(&consumer, linkname, sizeof(linkname)); + archive_entry_set_hardlink(entry, linkname); + } + archive_entry_set_uid(entry, 1000); archive_entry_set_gid(entry, 1000); archive_entry_set_mtime(entry, consumer.consume_i64(), 0); + uint8_t data_buf[256]; + size_t data_len = 0; + if (S_ISREG(mode)) { + data_len = consumer.consume_bytes(data_buf, 256); + archive_entry_set_size(entry, data_len); + } + // Write the entry header if (archive_write_header(disk, entry) == ARCHIVE_OK) { - if (S_ISREG(mode)) { - uint8_t data_buf[256]; - size_t data_len = consumer.consume_bytes(data_buf, 256); - archive_entry_set_size(entry, data_len); - if (data_len > 0) { - archive_write_data(disk, data_buf, data_len); - } + if (S_ISREG(mode) && data_len > 0) { + archive_write_data(disk, data_buf, data_len); } archive_write_finish_entry(disk); } @@ -116,6 +254,16 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { archive_write_close(disk); archive_write_free(disk); + if (!sentinel_is_unchanged()) { + abort(); + } + + if (g_start_dir[0] != '\0') { + if (chdir(g_start_dir) != 0) { + abort(); + } + } + // Clean up extracted files using nftw (safer than system()) remove_directory_tree(g_temp_dir); // Recreate the temp directory for next iteration diff --git a/contrib/libarchive/cpio/cpio.c b/contrib/libarchive/cpio/cpio.c index 6e6c2c3356..ebdace394c 100644 --- a/contrib/libarchive/cpio/cpio.c +++ b/contrib/libarchive/cpio/cpio.c @@ -1002,7 +1002,10 @@ mode_in(struct cpio *cpio) lafe_errc(1, archive_errno(a), "%s", archive_error_string(a)); } - if (archive_match_path_excluded(cpio->matching, entry)) + r = archive_match_path_excluded(cpio->matching, entry); + if (r < 0) + lafe_errc(1, 0, "%s", archive_error_string(cpio->matching)); + if (r) continue; if (cpio->option_rename) cpio_rename(entry); @@ -1117,7 +1120,10 @@ mode_list(struct cpio *cpio) lafe_errc(1, archive_errno(a), "%s", archive_error_string(a)); } - if (archive_match_path_excluded(cpio->matching, entry)) + r = archive_match_path_excluded(cpio->matching, entry); + if (r < 0) + lafe_errc(1, 0, "%s", archive_error_string(cpio->matching)); + if (r) continue; if (cpio->verbose) list_item_verbose(cpio, entry); diff --git a/contrib/libarchive/cpio/test/test_extract_cpio_absolute_paths.c b/contrib/libarchive/cpio/test/test_extract_cpio_absolute_paths.c index 51650bc00f..e3a72f9cca 100644 --- a/contrib/libarchive/cpio/test/test_extract_cpio_absolute_paths.c +++ b/contrib/libarchive/cpio/test/test_extract_cpio_absolute_paths.c @@ -50,4 +50,5 @@ DEFINE_TEST(test_extract_cpio_absolute_paths) r = systemf("%s -i --insecure < archive.cpio 2> stderr3.txt", testprog); assert(r == 0); assertFileExists(temp_absolute_file_name); + free(temp_absolute_file_name); } diff --git a/contrib/libarchive/cpio/test/test_format_newc.c b/contrib/libarchive/cpio/test/test_format_newc.c index 9d4e4e9fb6..7363fc148f 100644 --- a/contrib/libarchive/cpio/test/test_format_newc.c +++ b/contrib/libarchive/cpio/test/test_format_newc.c @@ -198,7 +198,7 @@ DEFINE_TEST(test_format_newc) t = from_hex(e + 46, 8); /* mtime */ failure("t=%#08jx now=%#08jx=%jd", (uintmax_t)t, (uintmax_t)now, (intmax_t)now); - assert(t <= now); /* File wasn't created in future. */ + assert(t <= now + 1); /* Allow 1 sec margin for timing variations. */ failure("t=%#08jx now - 2=%#08jx=%jd", (uintmax_t)t, (uintmax_t)now - 2, (intmax_t)now - 2); assert(t >= now - 2); /* File was created w/in last 2 secs. */ diff --git a/contrib/libarchive/doc/RUNNING_TESTS_LINUX.md b/contrib/libarchive/doc/RUNNING_TESTS_LINUX.md new file mode 100644 index 0000000000..62b6d18553 --- /dev/null +++ b/contrib/libarchive/doc/RUNNING_TESTS_LINUX.md @@ -0,0 +1,70 @@ +--- +name: libarchive-running-tests-linux +description: Explains how to build and run the libarchive test suite on Linux. +--- + +WIP: This is still being developed. +Of course, we'll need other `RUNNING_TESTS_.md`, +as well as `BUILDING_.md` files with more details about various build options and setup. + +# Building and Running Tests on Linux + +The following is a summary of the information in [doc/BUILDING_LINUX.md](BUILDING_LINUX.md). + +### Configuring and Building the Tests + +We recommend using the CMake build system with the Ninja build tool. +A parallel build system based on GNU autoconf is also available. + +To configure with CMake: +```bash +cmake -G Ninja -B _build -S . +``` +(Omit `-G Ninja` to use the platform default build system +-- usually `make` -- instead of Ninja.) + +To build all of libarchive, including the test suites, +using whatever build system you selected during configuration: +```bash +cmake --build _build +``` + +### Testing a component + +There is a single test executable for each major libarchive component. + +To test the libarchive library: +```bash +./_build/bin/libarchive_test +``` + +To test other components: +```bash +./_build/bin/bsdcat_test +./_build/bin/bsdcpio_test +./_build/bin/bsdtar_test +./_build/bin/bsdunzip_test +``` + +Each test executables runs a series of tests on the corresponding component. +Each test runs in its own temporary directory; +if the test fails, the temporary directory is left behind so you can inspect the contents. + +Reference files are loaded from a specific hardcoded path. +This assumes the current working directory is the root of the libarchive source tree. +If you need to run a test executable from a different directory, +use the `-r` option to provide a path to the reference files. + +Use the `-h` (help) option for more details or `-v` (verbose) for more detailed output. + +### Running a single test + +You can run a single test by name +```bash +./_build/bin/libarchive_test test_read_format_zip +``` +or by number +```bash +./_build/bin/libarchive_test 307 +./_build/bin/libarchive_test 446-448 +``` diff --git a/contrib/libarchive/doc/WRITING_TESTS.md b/contrib/libarchive/doc/WRITING_TESTS.md new file mode 100644 index 0000000000..5b179f36d9 --- /dev/null +++ b/contrib/libarchive/doc/WRITING_TESTS.md @@ -0,0 +1,242 @@ +--- +name: libarchive-writing-tests +description: Guide for writing and maintaining libarchive unit tests. +--- + +# Writing Libarchive Unit Tests + +Each libarchive component includes a suite of unit tests. +These are located in the `test` directory underneath the component directory +(`libarchive/test`, `tar/test`, etc). + +The most common reason that we fail to accept patches to libarchive +is because the patch lacks suitable new tests. +Almost all changes should be accompanied with a new or updated test case, +and if the change is non-trivial it will likely require several +tests to verify the full range of new behavior. +A new format or filter may require dozens of new tests. + +The rest of this file explains how to write a new test case and +add it to the existing test suite. +Understanding the structure of tests will also help when updating +or modifying existing tests. +The RUNNING_TESTS documentation corresponding to your platform +describes how to build and run the test suite. + +## Creating a New Test + +A "test" in libarchive is a C function defined with the `DEFINE_TEST(test_name)` macro. +While most test files contain only a single test, it is possible to include multiple tests in a single source file. +Many tests also involve an associated reference or sample input file, which is typically stored in the repository in UUencoded format. + +### 1. Basic Template +```c +#include "test.h" + +/* The test name typically matches the name of the `.c` source file. */ +DEFINE_TEST(test_foo) +{ + /* The file in the repository is named "test_foo.tar.uu". */ + /* The `refname` here omits the `.uu` suffix. */ + /* The base filename should match the test name. */ + const char *refname = "test_foo.tar"; + + struct archive *a; + struct archive_entry *ae; + int r; + + /* Each test runs in a private temporary directory. */ + + /* If you have a binary archive sample, extract it first. */ + extract_reference_file(refname); + + /* Create and configure a suitable archive handle. */ + 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)); + + /* Open the extracted reference file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); + + /* Perform whatever tests are appropriate. */ + + /* For example, when fixing a crash in libarchive, it + * may suffice for a test to simply read all the entries and + * their contents, as shown below. + * If errors are expected, you may need to unroll the following + * in order to perform specific checks for each entry. */ + while ((r = archive_read_next_header(a, &ae)) == ARCHIVE_OK) { + const void *pv; + size_t s; + int64_t o; + + while ((r == archive_read_data_block(a, &pv, &s, &o)) == ARCHIVE_OK) { + /* Verify the data contents if appropriate. */ + } + /* Verify that we exited the loop above on EOF, not on error. */ + assertEqualIntA(a, ARCHIVE_EOF, r); + } + + /* We exited the loop above, verify that it's EOF and not an error. */ + assertEqualIntA(a, ARCHIVE_EOF, r); + + /* Best practice: Close and free separately to get better + * error reporting if close fails. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} +``` + +### 2. Reference Files (Compatibility Tests) +For testing compatibility with existing archives: +1. Place the sample data in the `test` directory alongside the `.c` file. +2. Encode it using `uuencode`: `uuencode test_foo.tar test_foo.tar > test_foo.tar.uu`. +3. Use `extract_reference_file("test_foo.tar")` in your test to decode it into the temporary work directory. + +### 3. File and Function Naming + +The basic naming convention is `test___.c` where: +- **Functionality:** Indicates general functionality (e.g., `read`, `write`, `archive`, `entry`, `compat`). +- **Format/API:** The specific format or API being exercised (e.g., `format_tar`, `filter_gzip`, `next_header`, `acl`). +- **Detail:** Additional context to clarify the purpose (e.g., `empty`, `large`, `mac_metadata`). + +**Example names from the current suite:** +- `test_read_format_zip_mac_metadata.c` +- `test_write_disk_perms.c` +- `test_archive_read_next_header_empty.c` + +### 4. Registering the Test + +The build system searches uses of `DEFINE_TEST` to locate tests +in the relevant sources. +You only need to add the new files to the build system +to have them built +and run with the rest of the suite. +To add them to the build systems, +you need to update two files: + +1. `Makefile.am` in the root: + - Add `.c` files to `libarchive_test_SOURCES`. + - Add `.uu` reference files to `libarchive_test_EXTRA_DIST`. + - **Note:** Please maintain alphabetical order in these lists. +2. `CMakeLists.txt` in the relevant directory (e.g., `libarchive/test/CMakeLists.txt`): + - Add `.c` files to `libarchive_test_SOURCES`. + - **Note:** `.uu` files do NOT need to be listed in `CMakeLists.txt`. + +--- + +## Assertion Macros + +Always use the specialized assertion macros to ensure failures are actionable. +The full list of available macros is defined in `test_utils/test_common.h`. + +| Macro | Description | +|-------|-------------| +| `assert(expr)` | Standard boolean assertion. | +| `assertEqualInt(v1, v2)` | Asserts two integers are equal. Prints both values on failure. | +| `assertEqualString(s1, s2)` | Asserts two strings are equal. Prints both on failure. | +| `assertEqualMem(p1, p2, n)` | Asserts two memory blocks are equal. Provides a hexdump on failure. | +| `assertA(expr)` | Like `assert`, but also prints `archive_error_string(a)` on failure. | +| `assertEqualIntA(a, v1, v2)` | Like `assertEqualInt`, but includes archive error context. | +| `failure(fmt, ...)` | **Critical:** Use before an assertion to provide context. The message is only shown if the following assertion fails. | + +**Example usage:** +```c +/* Read first entry and verify metadata. */ +assertEqualIntA(a, ARCHIVE_OK, r = archive_read_next_header(a, &ae)); +if (r != ARCHIVE_OK) { ... end the test ... } + +assertEqualString("test_file.txt", archive_entry_pathname(ae)); +assertEqualInt(1197179003, archive_entry_mtime(ae)); +assertEqualInt(1000, archive_entry_uid(ae)); +assertEqualString("tim", archive_entry_uname(ae)); +assertEqualInt(0100644, archive_entry_mode(ae)); +``` + +--- + +## Working with Files and Data + +Many libarchive tests perform all operations entirely in memory. +However, when testing archive extraction, you must verify the resulting files on disk. +Similarly, when testing archive creation, you may need to create files on disk to be archived. +The harness provides a variety of file utilities expressed as assertions. + +This includes assertions that create or modify files: +- `assertMakeFile(path, mode, contents)` +- `assertMakeDir(path, mode)` +- `assertChmod(pathname, mode)` + +And assertions that verify particular file properties, such as: +- `assertFileExists(path)` +- `assertFileSize(path, expected_size)` +- `assertTextFileContents(expected_text, path)` + +The full set of assertions is listed in `test_utils/test_common.h`. +You can search the existing tests to find examples of their usage. + +--- + +## Platform and Environment Utilities + +Some checks can only be done if the underlying system has certain +capabilities. + +Utilities to check capabilities of the current system include: +- `canSymlink()` +- `canGzip()` +- `canRunCommand("cmd", NULL)`. + +These can be used to circumvent specific individual checks: + +```c +if (canSymlink()) { + skipping("Symlinks not supported on this platform"); + /* ... verify that symlink entries were correctly restored */ +} +``` + +Or to abort an entire test: +```c +if (!canSymlink()) { + skipping("Symlinks not supported on this platform"); + return; +} +``` + +--- + +## General Best Practices + +Some pointers for making more effective tests: + +- **Use assertions liberally:** + Most lines of code in a test use `assert` macros to + verify the expected result. +- **Always Clean Up:** + Call `archive_read_free()` or `archive_write_free()` on every exit + path, including failures and premature exits. +- **Cross-Platform Portability:** + Do not assume POSIX features like `symlink` or `chown`. + Use the `can...()` helpers to verify system support before + performing platform-specific checks. +- **Verify the Fix:** + Run your new test against the code before and after any + other changes to ensure the test reproduces the issue and that + your fix addresses it. +- **Test, then Fix:** + Pull requests should have one or more commits with + new or updated unit tests, followed by commits that + change functionality. +- **Verify Error Details:** + When an API returns `ARCHIVE_WARN` or `ARCHIVE_FATAL`, + verify the specific error code from `archive_errno()`. + However, you should not always check the result of `archive_error_string()`, + as the specific text can evolve over time. + Generally, there should be one test each time a new error path is added + that verifies the error string. +- **Match the Existing Style:** + Changes to existing files should always match the indentation + and style of that file. + New files should follow the "BSD" formatting convention, + with 8-character hard tabs for indentation. diff --git a/contrib/libarchive/libarchive/archive.h b/contrib/libarchive/libarchive/archive.h index 41a5440cac..159a3d561a 100644 --- a/contrib/libarchive/libarchive/archive.h +++ b/contrib/libarchive/libarchive/archive.h @@ -34,7 +34,7 @@ * assert that ARCHIVE_VERSION_NUMBER >= 2012108. */ /* Note: Compiler will complain if this does not match archive_entry.h! */ -#define ARCHIVE_VERSION_NUMBER 3008007 +#define ARCHIVE_VERSION_NUMBER 3008008 #include #include /* for wchar_t */ @@ -177,7 +177,7 @@ __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_ONLY_STRING "3.8.7" +#define ARCHIVE_VERSION_ONLY_STRING "3.8.8" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); @@ -210,7 +210,9 @@ __LA_DECL const char * archive_openssl_version(void); __LA_DECL const char * archive_libmd_version(void); __LA_DECL const char * archive_commoncrypto_version(void); __LA_DECL const char * archive_cng_version(void); +#if ARCHIVE_VERSION_NUMBER < 4000000 __LA_DECL const char * archive_wincrypt_version(void); +#endif __LA_DECL const char * archive_librichacl_version(void); __LA_DECL const char * archive_libacl_version(void); __LA_DECL const char * archive_libattr_version(void); @@ -653,7 +655,6 @@ __LA_DECL int archive_read_data_block(struct archive *a, /*- * Some convenience functions that are built on archive_read_data: * 'skip': skips entire entry - * 'into_buffer': writes data into memory buffer that you provide * 'into_fd': writes data to specified filedes */ __LA_DECL int archive_read_data_skip(struct archive *); @@ -1234,7 +1235,7 @@ __LA_DECL int archive_match_exclude_entry(struct archive *, int _flag, struct archive_entry *); /* - * Test if a file is excluded by its uid ,gid, uname or gname. + * Test if a file is excluded by its uid, gid, uname or gname. * The conditions are set by following functions. */ __LA_DECL int archive_match_owner_excluded(struct archive *, diff --git a/contrib/libarchive/libarchive/archive_acl.c b/contrib/libarchive/libarchive/archive_acl.c index ab601833de..f8d85b4bfa 100644 --- a/contrib/libarchive/libarchive/archive_acl.c +++ b/contrib/libarchive/libarchive/archive_acl.c @@ -56,9 +56,7 @@ static int archive_acl_add_entry_len_l(struct archive_acl *acl, int type, int permset, int tag, int id, const char *name, size_t len, struct archive_string_conv *sc); static int archive_acl_text_want_type(struct archive_acl *acl, int flags); -static size_t archive_acl_text_len(struct archive_acl *acl, int want_type, - int flags, int wide, struct archive *a, - struct archive_string_conv *sc); +static size_t archive_acl_text_empty(struct archive_acl *acl, int want_type); static int isint_w(const wchar_t *start, const wchar_t *end, int *result); static int ismode_w(const wchar_t *start, const wchar_t *end, int *result); static int is_nfs4_flags_w(const wchar_t *start, const wchar_t *end, @@ -67,9 +65,9 @@ static int is_nfs4_perms_w(const wchar_t *start, const wchar_t *end, int *result); static void next_field_w(const wchar_t **wp, const wchar_t **start, const wchar_t **end, wchar_t *sep); -static void append_entry_w(wchar_t **wp, const wchar_t *prefix, int type, +static void append_entry_w(struct archive_wstring *ws, const wchar_t *prefix, int type, int tag, int flags, const wchar_t *wname, int perm, int id); -static void append_id_w(wchar_t **wp, int id); +static void append_id_w(struct archive_wstring *ws, int id); static int isint(const char *start, const char *end, int *result); static int ismode(const char *start, const char *end, int *result); static int is_nfs4_flags(const char *start, const char *end, @@ -78,9 +76,9 @@ static int is_nfs4_perms(const char *start, const char *end, int *result); static void next_field(const char **p, size_t *l, const char **start, const char **end, char *sep); -static void append_entry(char **p, const char *prefix, int type, +static void append_entry(struct archive_string *s, const char *prefix, int type, int tag, int flags, const char *name, int perm, int id); -static void append_id(char **p, int id); +static void append_id(struct archive_string *s, int id); static const struct { const int perm; @@ -539,20 +537,12 @@ archive_acl_text_want_type(struct archive_acl *acl, int flags) } /* - * Calculate ACL text string length + * Check if ACL text would be empty */ static size_t -archive_acl_text_len(struct archive_acl *acl, int want_type, int flags, - int wide, struct archive *a, struct archive_string_conv *sc) { +archive_acl_text_empty(struct archive_acl *acl, int want_type) { struct archive_acl_entry *ap; - const char *name; - const wchar_t *wname; - int count, idlen, tmp, r; - size_t length; - size_t len; - count = 0; - length = 0; for (ap = acl->acl_head; ap != NULL; ap = ap->next) { if ((ap->type & want_type) == 0) continue; @@ -565,107 +555,11 @@ archive_acl_text_len(struct archive_acl *acl, int want_type, int flags, || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ || ap->tag == ARCHIVE_ENTRY_ACL_OTHER)) continue; - count++; - if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0 - && (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) - length += 8; /* "default:" */ - switch (ap->tag) { - case ARCHIVE_ENTRY_ACL_USER_OBJ: - if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { - length += 6; /* "owner@" */ - break; - } - /* FALLTHROUGH */ - case ARCHIVE_ENTRY_ACL_USER: - case ARCHIVE_ENTRY_ACL_MASK: - length += 4; /* "user", "mask" */ - break; - case ARCHIVE_ENTRY_ACL_GROUP_OBJ: - if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { - length += 6; /* "group@" */ - break; - } - /* FALLTHROUGH */ - case ARCHIVE_ENTRY_ACL_GROUP: - case ARCHIVE_ENTRY_ACL_OTHER: - length += 5; /* "group", "other" */ - break; - case ARCHIVE_ENTRY_ACL_EVERYONE: - length += 9; /* "everyone@" */ - break; - } - length += 1; /* colon after tag */ - if (ap->tag == ARCHIVE_ENTRY_ACL_USER || - ap->tag == ARCHIVE_ENTRY_ACL_GROUP) { - if (wide) { - r = archive_mstring_get_wcs(a, &ap->name, - &wname); - if (r == 0 && wname != NULL) - length += wcslen(wname); - else if (r < 0 && errno == ENOMEM) - return (0); - else - length += sizeof(uid_t) * 3 + 1; - } else { - r = archive_mstring_get_mbs_l(a, &ap->name, &name, - &len, sc); - if (r != 0) - return (0); - if (len > 0 && name != NULL) - length += len; - else - length += sizeof(uid_t) * 3 + 1; - } - length += 1; /* colon after user or group name */ - } else if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) - length += 1; /* 2nd colon empty user,group or other */ - - if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0) - && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) - && (ap->tag == ARCHIVE_ENTRY_ACL_OTHER - || ap->tag == ARCHIVE_ENTRY_ACL_MASK)) { - /* Solaris has no colon after other: and mask: */ - length = length - 1; - } - if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { - /* rwxpdDaARWcCos:fdinSFI:deny */ - length += 27; - if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DENY) == 0) - length += 1; /* allow, alarm, audit */ - } else - length += 3; /* rwx */ - - if ((ap->tag == ARCHIVE_ENTRY_ACL_USER || - ap->tag == ARCHIVE_ENTRY_ACL_GROUP) && - (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0) { - length += 1; /* colon */ - /* ID digit count */ - idlen = 1; - tmp = ap->id; - while (tmp > 9) { - tmp = tmp / 10; - idlen++; - } - length += idlen; - } - length ++; /* entry separator */ - } - - /* Add filemode-mapping access entries to the length */ - if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - if ((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0) { - /* "user::rwx\ngroup::rwx\nother:rwx\n" */ - length += 31; - } else { - /* "user::rwx\ngroup::rwx\nother::rwx\n" */ - length += 32; - } - } else if (count == 0) return (0); + } - /* The terminating character is included in count */ - return (length); + return (1); } /* @@ -676,15 +570,12 @@ wchar_t * archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags, struct archive *a) { - int count; - size_t length; - size_t len; const wchar_t *wname; const wchar_t *prefix; wchar_t separator; struct archive_acl_entry *ap; + struct archive_wstring ws; int id, r, want_type; - wchar_t *wp, *ws; want_type = archive_acl_text_want_type(acl, flags); @@ -695,9 +586,7 @@ archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags, if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT; - length = archive_acl_text_len(acl, want_type, flags, 1, a, NULL); - - if (length == 0) + if (archive_acl_text_empty(acl, want_type)) return (NULL); if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA) @@ -705,28 +594,20 @@ archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags, else separator = L'\n'; - /* Now, allocate the string and actually populate it. */ - wp = ws = malloc(length * sizeof(*wp)); - if (wp == NULL) { - if (errno == ENOMEM) - __archive_errx(1, "No memory"); - return (NULL); - } - count = 0; + archive_string_init(&ws); if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + append_entry_w(&ws, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL, acl->mode & 0700, -1); - *wp++ = separator; - append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + archive_wstrappend_wchar(&ws, separator); + append_entry_w(&ws, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL, acl->mode & 0070, -1); - *wp++ = separator; - append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + archive_wstrappend_wchar(&ws, separator); + append_entry_w(&ws, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_OTHER, flags, NULL, acl->mode & 0007, -1); - count += 3; } for (ap = acl->acl_head; ap != NULL; ap = ap->next) { @@ -748,108 +629,95 @@ archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags, prefix = NULL; r = archive_mstring_get_wcs(a, &ap->name, &wname); if (r == 0) { - if (count > 0) - *wp++ = separator; - if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) + if (ws.length > 0) + archive_wstrappend_wchar(&ws, separator); + if ((flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) || + wname == NULL) id = ap->id; else id = -1; - append_entry_w(&wp, prefix, ap->type, ap->tag, flags, + append_entry_w(&ws, prefix, ap->type, ap->tag, flags, wname, ap->permset, id); - count++; } else if (r < 0 && errno == ENOMEM) { - free(ws); + archive_wstring_free(&ws); return (NULL); } } - /* Add terminating character */ - *wp++ = L'\0'; - - len = wcslen(ws); - - if (len > length - 1) - __archive_errx(1, "Buffer overrun"); - if (text_len != NULL) - *text_len = len; + *text_len = ws.length; - return (ws); + return (ws.s); } static void -append_id_w(wchar_t **wp, int id) +append_id_w(struct archive_wstring *ws, int id) { if (id < 0) id = 0; if (id > 9) - append_id_w(wp, id / 10); - *(*wp)++ = L"0123456789"[id % 10]; + append_id_w(ws, id / 10); + archive_wstrappend_wchar(ws, L"0123456789"[id % 10]); } static void -append_entry_w(wchar_t **wp, const wchar_t *prefix, int type, +append_entry_w(struct archive_wstring *ws, const wchar_t *prefix, int type, int tag, int flags, const wchar_t *wname, int perm, int id) { int i; - if (prefix != NULL) { - wcscpy(*wp, prefix); - *wp += wcslen(*wp); - } + if (prefix != NULL) + archive_wstrcat(ws, prefix); switch (tag) { case ARCHIVE_ENTRY_ACL_USER_OBJ: wname = NULL; id = -1; if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { - wcscpy(*wp, L"owner@"); + archive_wstrcat(ws, L"owner@"); break; } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_USER: - wcscpy(*wp, L"user"); + archive_wstrcat(ws, L"user"); break; case ARCHIVE_ENTRY_ACL_GROUP_OBJ: wname = NULL; id = -1; if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { - wcscpy(*wp, L"group@"); + archive_wstrcat(ws, L"group@"); break; } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_GROUP: - wcscpy(*wp, L"group"); + archive_wstrcat(ws, L"group"); break; case ARCHIVE_ENTRY_ACL_MASK: - wcscpy(*wp, L"mask"); + archive_wstrcat(ws, L"mask"); wname = NULL; id = -1; break; case ARCHIVE_ENTRY_ACL_OTHER: - wcscpy(*wp, L"other"); + archive_wstrcat(ws, L"other"); wname = NULL; id = -1; break; case ARCHIVE_ENTRY_ACL_EVERYONE: - wcscpy(*wp, L"everyone@"); + archive_wstrcat(ws, L"everyone@"); wname = NULL; id = -1; break; default: - **wp = '\0'; break; } - *wp += wcslen(*wp); - *(*wp)++ = L':'; + archive_wstrappend_wchar(ws, L':'); if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) || tag == ARCHIVE_ENTRY_ACL_USER || tag == ARCHIVE_ENTRY_ACL_GROUP) { if (wname != NULL) { - wcscpy(*wp, wname); - *wp += wcslen(*wp); + archive_wstrcat(ws, wname); } else if (tag == ARCHIVE_ENTRY_ACL_USER || tag == ARCHIVE_ENTRY_ACL_GROUP) { - append_id_w(wp, id); + append_id_w(ws, id); if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) id = -1; } @@ -857,51 +725,49 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int type, if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0) || (tag != ARCHIVE_ENTRY_ACL_OTHER && tag != ARCHIVE_ENTRY_ACL_MASK)) - *(*wp)++ = L':'; + archive_wstrappend_wchar(ws, L':'); } if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { /* POSIX.1e ACL perms */ - *(*wp)++ = (perm & 0444) ? L'r' : L'-'; - *(*wp)++ = (perm & 0222) ? L'w' : L'-'; - *(*wp)++ = (perm & 0111) ? L'x' : L'-'; + archive_wstrappend_wchar(ws, (perm & 0444) ? L'r' : L'-'); + archive_wstrappend_wchar(ws, (perm & 0222) ? L'w' : L'-'); + archive_wstrappend_wchar(ws, (perm & 0111) ? L'x' : L'-'); } else { /* NFSv4 ACL perms */ for (i = 0; i < nfsv4_acl_perm_map_size; i++) { if (perm & nfsv4_acl_perm_map[i].perm) - *(*wp)++ = nfsv4_acl_perm_map[i].wc; + archive_wstrappend_wchar(ws, nfsv4_acl_perm_map[i].wc); else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) - *(*wp)++ = L'-'; + archive_wstrappend_wchar(ws, L'-'); } - *(*wp)++ = L':'; + archive_wstrappend_wchar(ws, L':'); for (i = 0; i < nfsv4_acl_flag_map_size; i++) { if (perm & nfsv4_acl_flag_map[i].perm) - *(*wp)++ = nfsv4_acl_flag_map[i].wc; + archive_wstrappend_wchar(ws, nfsv4_acl_flag_map[i].wc); else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) - *(*wp)++ = L'-'; + archive_wstrappend_wchar(ws, L'-'); } - *(*wp)++ = L':'; + archive_wstrappend_wchar(ws, L':'); switch (type) { case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: - wcscpy(*wp, L"allow"); + archive_wstrcat(ws, L"allow"); break; case ARCHIVE_ENTRY_ACL_TYPE_DENY: - wcscpy(*wp, L"deny"); + archive_wstrcat(ws, L"deny"); break; case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: - wcscpy(*wp, L"audit"); + archive_wstrcat(ws, L"audit"); break; case ARCHIVE_ENTRY_ACL_TYPE_ALARM: - wcscpy(*wp, L"alarm"); + archive_wstrcat(ws, L"alarm"); break; default: - *(*wp) = L'\0'; break; } - *wp += wcslen(*wp); } if (id != -1) { - *(*wp)++ = L':'; - append_id_w(wp, id); + archive_wstrappend_wchar(ws, L':'); + append_id_w(ws, id); } } @@ -913,15 +779,13 @@ char * archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags, struct archive_string_conv *sc) { - int count; - size_t length; size_t len; const char *name; const char *prefix; char separator; struct archive_acl_entry *ap; + struct archive_string s; int id, r, want_type; - char *p, *s; want_type = archive_acl_text_want_type(acl, flags); @@ -932,9 +796,7 @@ archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags, if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT; - length = archive_acl_text_len(acl, want_type, flags, 0, NULL, sc); - - if (length == 0) + if (archive_acl_text_empty(acl, want_type)) return (NULL); if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA) @@ -942,28 +804,20 @@ archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags, else separator = '\n'; - /* Now, allocate the string and actually populate it. */ - p = s = malloc(length * sizeof(*p)); - if (p == NULL) { - if (errno == ENOMEM) - __archive_errx(1, "No memory"); - return (NULL); - } - count = 0; + archive_string_init(&s); if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + append_entry(&s, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL, acl->mode & 0700, -1); - *p++ = separator; - append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + archive_strappend_char(&s, separator); + append_entry(&s, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL, acl->mode & 0070, -1); - *p++ = separator; - append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + archive_strappend_char(&s, separator); + append_entry(&s, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_OTHER, flags, NULL, acl->mode & 0007, -1); - count += 3; } for (ap = acl->acl_head; ap != NULL; ap = ap->next) { @@ -986,109 +840,95 @@ archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags, r = archive_mstring_get_mbs_l( NULL, &ap->name, &name, &len, sc); if (r != 0) { - free(s); + archive_string_free(&s); return (NULL); } - if (count > 0) - *p++ = separator; + if (s.length > 0) + archive_strappend_char(&s, separator); if (name == NULL || (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)) { id = ap->id; } else { id = -1; } - append_entry(&p, prefix, ap->type, ap->tag, flags, name, + append_entry(&s, prefix, ap->type, ap->tag, flags, name, ap->permset, id); - count++; } - /* Add terminating character */ - *p++ = '\0'; - - len = strlen(s); - - if (len > length - 1) - __archive_errx(1, "Buffer overrun"); - if (text_len != NULL) - *text_len = len; + *text_len = s.length; - return (s); + return (s.s); } static void -append_id(char **p, int id) +append_id(struct archive_string *s, int id) { if (id < 0) id = 0; if (id > 9) - append_id(p, id / 10); - *(*p)++ = "0123456789"[id % 10]; + append_id(s, id / 10); + archive_strappend_char(s, "0123456789"[id % 10]); } static void -append_entry(char **p, const char *prefix, int type, +append_entry(struct archive_string *s, const char *prefix, int type, int tag, int flags, const char *name, int perm, int id) { int i; - if (prefix != NULL) { - strcpy(*p, prefix); - *p += strlen(*p); - } + if (prefix != NULL) + archive_strcat(s, prefix); switch (tag) { case ARCHIVE_ENTRY_ACL_USER_OBJ: name = NULL; id = -1; if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { - strcpy(*p, "owner@"); + archive_strcat(s, "owner@"); break; } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_USER: - strcpy(*p, "user"); + archive_strcat(s, "user"); break; case ARCHIVE_ENTRY_ACL_GROUP_OBJ: name = NULL; id = -1; if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { - strcpy(*p, "group@"); + archive_strcat(s, "group@"); break; } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_GROUP: - strcpy(*p, "group"); + archive_strcat(s, "group"); break; case ARCHIVE_ENTRY_ACL_MASK: - strcpy(*p, "mask"); + archive_strcat(s, "mask"); name = NULL; id = -1; break; case ARCHIVE_ENTRY_ACL_OTHER: - strcpy(*p, "other"); + archive_strcat(s, "other"); name = NULL; id = -1; break; case ARCHIVE_ENTRY_ACL_EVERYONE: - strcpy(*p, "everyone@"); + archive_strcat(s, "everyone@"); name = NULL; id = -1; break; default: - **p = '\0'; break; } - *p += strlen(*p); - *(*p)++ = ':'; + archive_strappend_char(s, ':'); if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) || tag == ARCHIVE_ENTRY_ACL_USER || tag == ARCHIVE_ENTRY_ACL_GROUP) { if (name != NULL) { - strcpy(*p, name); - *p += strlen(*p); + archive_strcat(s, name); } else if (tag == ARCHIVE_ENTRY_ACL_USER || tag == ARCHIVE_ENTRY_ACL_GROUP) { - append_id(p, id); + append_id(s, id); if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) id = -1; } @@ -1096,51 +936,49 @@ append_entry(char **p, const char *prefix, int type, if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0) || (tag != ARCHIVE_ENTRY_ACL_OTHER && tag != ARCHIVE_ENTRY_ACL_MASK)) - *(*p)++ = ':'; + archive_strappend_char(s, ':'); } if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { /* POSIX.1e ACL perms */ - *(*p)++ = (perm & 0444) ? 'r' : '-'; - *(*p)++ = (perm & 0222) ? 'w' : '-'; - *(*p)++ = (perm & 0111) ? 'x' : '-'; + archive_strappend_char(s, (perm & 0444) ? 'r' : '-'); + archive_strappend_char(s, (perm & 0222) ? 'w' : '-'); + archive_strappend_char(s, (perm & 0111) ? 'x' : '-'); } else { /* NFSv4 ACL perms */ for (i = 0; i < nfsv4_acl_perm_map_size; i++) { if (perm & nfsv4_acl_perm_map[i].perm) - *(*p)++ = nfsv4_acl_perm_map[i].c; + archive_strappend_char(s, nfsv4_acl_perm_map[i].c); else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) - *(*p)++ = '-'; + archive_strappend_char(s, '-'); } - *(*p)++ = ':'; + archive_strappend_char(s, ':'); for (i = 0; i < nfsv4_acl_flag_map_size; i++) { if (perm & nfsv4_acl_flag_map[i].perm) - *(*p)++ = nfsv4_acl_flag_map[i].c; + archive_strappend_char(s, nfsv4_acl_flag_map[i].c); else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) - *(*p)++ = '-'; + archive_strappend_char(s, '-'); } - *(*p)++ = ':'; + archive_strappend_char(s, ':'); switch (type) { case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: - strcpy(*p, "allow"); + archive_strcat(s, "allow"); break; case ARCHIVE_ENTRY_ACL_TYPE_DENY: - strcpy(*p, "deny"); + archive_strcat(s, "deny"); break; case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: - strcpy(*p, "audit"); + archive_strcat(s, "audit"); break; case ARCHIVE_ENTRY_ACL_TYPE_ALARM: - strcpy(*p, "alarm"); + archive_strcat(s, "alarm"); break; default: - *(*p) = '\0'; break; } - *p += strlen(*p); } if (id != -1) { - *(*p)++ = ':'; - append_id(p, id); + archive_strappend_char(s, ':'); + append_id(s, id); } } @@ -1248,11 +1086,18 @@ archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text, type = want_type; /* Check for a numeric ID in field n+1 or n+3. */ - isint_w(field[n + 1].start, field[n + 1].end, &id); + if (isint_w(field[n + 1].start, field[n + 1].end, + &id) < 0) { + ret = ARCHIVE_WARN; + continue; + } /* Field n+3 is optional. */ - if (id == -1 && fields > n+3) - isint_w(field[n + 3].start, field[n + 3].end, - &id); + if (id == -1 && fields > n+3 && + isint_w(field[n + 3].start, field[n + 3].end, + &id) < 0) { + ret = ARCHIVE_WARN; + continue; + } tag = 0; s = field[n].start; @@ -1367,7 +1212,10 @@ archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text, tag == ARCHIVE_ENTRY_ACL_GROUP) { n = 1; name = field[1]; - isint_w(name.start, name.end, &id); + if (isint_w(name.start, name.end, &id) < 0) { + ret = ARCHIVE_WARN; + continue; + } } else n = 0; @@ -1402,7 +1250,11 @@ archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text, ret = ARCHIVE_WARN; continue; } - isint_w(field[4 + n].start, field[4 + n].end, &id); + if (isint_w(field[4 + n].start, field[4 + n].end, + &id) < 0) { + ret = ARCHIVE_WARN; + continue; + } } /* Add entry to the internal list. */ @@ -1436,8 +1288,8 @@ isint_w(const wchar_t *start, const wchar_t *end, int *result) if (*start < L'0' || *start > L'9') return (0); if (n > (INT_MAX / 10) || - (n == INT_MAX / 10 && (*start - L'0') > INT_MAX % 10)) { - n = INT_MAX; + (n == INT_MAX / 10 && (*start - L'0') >= INT_MAX % 10)) { + return (-1); } else { n *= 10; n += *start - L'0'; @@ -1747,15 +1599,21 @@ archive_acl_from_text_nl(struct archive_acl *acl, const char *text, type = want_type; /* Check for a numeric ID in field n+1 or n+3. */ - isint(field[n + 1].start, field[n + 1].end, &id); + if (isint(field[n + 1].start, field[n + 1].end, + &id) < 0) { + ret = ARCHIVE_WARN; + continue; + } /* Field n+3 is optional. */ - if (id == -1 && fields > (n + 3)) - isint(field[n + 3].start, field[n + 3].end, - &id); + if (id == -1 && fields > (n + 3) && + isint(field[n + 3].start, field[n + 3].end, + &id) < 0) { + ret = ARCHIVE_WARN; + continue; + } tag = 0; s = field[n].start; - st = field[n].start + 1; len = field[n].end - field[n].start; if (len == 0) { @@ -1763,6 +1621,8 @@ archive_acl_from_text_nl(struct archive_acl *acl, const char *text, continue; } + st = s + 1; + switch (*s) { case 'u': if (len == 1 || (len == 4 @@ -1868,7 +1728,10 @@ archive_acl_from_text_nl(struct archive_acl *acl, const char *text, tag == ARCHIVE_ENTRY_ACL_GROUP) { n = 1; name = field[1]; - isint(name.start, name.end, &id); + if (isint(name.start, name.end, &id) < 0) { + ret = ARCHIVE_WARN; + continue; + } } else n = 0; @@ -1903,8 +1766,11 @@ archive_acl_from_text_nl(struct archive_acl *acl, const char *text, ret = ARCHIVE_WARN; continue; } - isint(field[4 + n].start, field[4 + n].end, - &id); + if (isint(field[4 + n].start, field[4 + n].end, + &id) < 0) { + ret = ARCHIVE_WARN; + continue; + } } /* Add entry to the internal list. */ @@ -1938,8 +1804,8 @@ isint(const char *start, const char *end, int *result) if (*start < '0' || *start > '9') return (0); if (n > (INT_MAX / 10) || - (n == INT_MAX / 10 && (*start - '0') > INT_MAX % 10)) { - n = INT_MAX; + (n == INT_MAX / 10 && (*start - '0') >= INT_MAX % 10)) { + return (-1); } else { n *= 10; n += *start - '0'; @@ -2121,7 +1987,10 @@ next_field(const char **p, size_t *l, const char **start, (*p)++; (*l)--; } - *sep = **p; + if (*l > 0) + *sep = **p; + else + *sep = '\0'; /* Handle in-field comments */ if (*sep == '#') { @@ -2129,7 +1998,10 @@ next_field(const char **p, size_t *l, const char **start, (*p)++; (*l)--; } - *sep = **p; + if (*l > 0) + *sep = **p; + else + *sep = '\0'; } /* Skip separator. */ diff --git a/contrib/libarchive/libarchive/archive_cmdline.c b/contrib/libarchive/libarchive/archive_cmdline.c index 23bb05d642..ffc4f54749 100644 --- a/contrib/libarchive/libarchive/archive_cmdline.c +++ b/contrib/libarchive/libarchive/archive_cmdline.c @@ -36,7 +36,6 @@ #include "archive_cmdline_private.h" #include "archive_string.h" -static int cmdline_set_path(struct archive_cmdline *, const char *); static int cmdline_add_arg(struct archive_cmdline *, const char *); static ssize_t @@ -98,7 +97,7 @@ get_argument(struct archive_string *as, const char *p) /* * Set up command line arguments. - * Returns ARCHIVE_OK if everything okey. + * Returns ARCHIVE_OK if everything okay. * Returns ARCHIVE_FAILED if there is a lack of the `"' terminator or an * empty command line. * Returns ARCHIVE_FATAL if no memory. @@ -123,9 +122,12 @@ __archive_cmdline_parse(struct archive_cmdline *data, const char *cmd) r = ARCHIVE_FAILED;/* An empty command path. */ goto exit_function; } - r = cmdline_set_path(data, as.s); - if (r != ARCHIVE_OK) + free(data->path); + data->path = strdup(as.s); + if (data->path == NULL) { + r = ARCHIVE_FATAL; goto exit_function; + } p = strrchr(as.s, '/'); if (p == NULL) p = as.s; @@ -158,23 +160,7 @@ __archive_cmdline_parse(struct archive_cmdline *data, const char *cmd) } /* - * Set the program path. - */ -static int -cmdline_set_path(struct archive_cmdline *data, const char *path) -{ - char *newptr; - - newptr = realloc(data->path, strlen(path) + 1); - if (newptr == NULL) - return (ARCHIVE_FATAL); - data->path = newptr; - strcpy(data->path, path); - return (ARCHIVE_OK); -} - -/* - * Add a argument for the program. + * Add an argument for the program. */ static int cmdline_add_arg(struct archive_cmdline *data, const char *arg) diff --git a/contrib/libarchive/libarchive/archive_crc32.h b/contrib/libarchive/libarchive/archive_crc32.h index d86a507ce7..cbd25291a9 100644 --- a/contrib/libarchive/libarchive/archive_crc32.h +++ b/contrib/libarchive/libarchive/archive_crc32.h @@ -43,28 +43,65 @@ static unsigned long crc32(unsigned long crc, const void *_p, size_t len) { - unsigned long crc2, b, i; const unsigned char *p = _p; - static volatile int crc_tbl_inited = 0; - static unsigned long crc_tbl[256]; + static const unsigned long crc_tbl[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d + }; if (_p == NULL) return (0); - if (!crc_tbl_inited) { - for (b = 0; b < 256; ++b) { - crc2 = b; - for (i = 8; i > 0; --i) { - if (crc2 & 1) - crc2 = (crc2 >> 1) ^ 0xedb88320UL; - else - crc2 = (crc2 >> 1); - } - crc_tbl[b] = crc2; - } - crc_tbl_inited = 1; - } - crc = crc ^ 0xffffffffUL; /* A use of this loop is about 20% - 30% faster than * no use version in any optimization option of gcc. */ diff --git a/contrib/libarchive/libarchive/archive_cryptor.c b/contrib/libarchive/libarchive/archive_cryptor.c index b6a02fd1e7..85b20ac9ac 100644 --- a/contrib/libarchive/libarchive/archive_cryptor.c +++ b/contrib/libarchive/libarchive/archive_cryptor.c @@ -57,7 +57,7 @@ pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt, return 0; } -#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA +#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) #ifdef _MSC_VER #pragma comment(lib, "Bcrypt.lib") #endif @@ -197,7 +197,7 @@ aes_ctr_release(archive_crypto_ctx *ctx) return 0; } -#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA +#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) static int aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len) diff --git a/contrib/libarchive/libarchive/archive_cryptor_private.h b/contrib/libarchive/libarchive/archive_cryptor_private.h index 1f9298ffdc..069eccd994 100644 --- a/contrib/libarchive/libarchive/archive_cryptor_private.h +++ b/contrib/libarchive/libarchive/archive_cryptor_private.h @@ -62,7 +62,7 @@ typedef struct { size_t encr_pos; } archive_crypto_ctx; -#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA +#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) #include #define ARCHIVE_CRYPTOR_USE_CNG 1 @@ -148,16 +148,6 @@ typedef struct { #else -#if defined(ARCHIVE_CRYPTO_MD5_WIN) ||\ - defined(ARCHIVE_CRYPTO_SHA1_WIN) ||\ - defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\ - defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\ - defined(ARCHIVE_CRYPTO_SHA512_WIN) -#if defined(_WIN32) && !defined(__CYGWIN__) && !(defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA) -#define ARCHIVE_CRYPTOR_USE_WINCRYPT 1 -#endif -#endif - #define AES_BLOCK_SIZE 16 #define AES_MAX_KEY_SIZE 32 typedef int archive_crypto_ctx; diff --git a/contrib/libarchive/libarchive/archive_digest.c b/contrib/libarchive/libarchive/archive_digest.c index 45fc36af11..ab6db12beb 100644 --- a/contrib/libarchive/libarchive/archive_digest.c +++ b/contrib/libarchive/libarchive/archive_digest.c @@ -44,16 +44,11 @@ /* * Message digest functions for Windows platform. */ -#if defined(ARCHIVE_CRYPTO_MD5_WIN) ||\ - defined(ARCHIVE_CRYPTO_SHA1_WIN) ||\ - defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\ - defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\ - defined(ARCHIVE_CRYPTO_SHA512_WIN) +#if defined(HAVE_BCRYPT_H) /* * Initialize a Message digest. */ -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA static int win_crypto_init(Digest_CTX *ctx, const WCHAR *algo) { @@ -72,30 +67,6 @@ win_crypto_init(Digest_CTX *ctx, const WCHAR *algo) ctx->valid = 1; return (ARCHIVE_OK); } -#else -static int -win_crypto_init(Digest_CTX *ctx, DWORD prov, ALG_ID algId) -{ - - ctx->valid = 0; - if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL, - prov, CRYPT_VERIFYCONTEXT)) { - if (GetLastError() != (DWORD)NTE_BAD_KEYSET) - return (ARCHIVE_FAILED); - if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL, - prov, CRYPT_NEWKEYSET)) - return (ARCHIVE_FAILED); - } - - if (!CryptCreateHash(ctx->cryptProv, algId, 0, 0, &ctx->hash)) { - CryptReleaseContext(ctx->cryptProv, 0); - return (ARCHIVE_FAILED); - } - - ctx->valid = 1; - return (ARCHIVE_OK); -} -#endif /* * Update a Message digest. @@ -107,42 +78,26 @@ win_crypto_Update(Digest_CTX *ctx, const unsigned char *buf, size_t len) if (!ctx->valid) return (ARCHIVE_FAILED); -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA BCryptHashData(ctx->hHash, (PUCHAR)(uintptr_t)buf, (ULONG)len, 0); -#else - CryptHashData(ctx->hash, - (unsigned char *)(uintptr_t)buf, - (DWORD)len, 0); -#endif return (ARCHIVE_OK); } static int win_crypto_Final(unsigned char *buf, size_t bufsize, Digest_CTX *ctx) { -#if !(defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA) - DWORD siglen = (DWORD)bufsize; -#endif - if (!ctx->valid) return (ARCHIVE_FAILED); -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA BCryptFinishHash(ctx->hHash, buf, (ULONG)bufsize, 0); BCryptDestroyHash(ctx->hHash); BCryptCloseAlgorithmProvider(ctx->hAlg, 0); -#else - CryptGetHashParam(ctx->hash, HP_HASHVAL, buf, &siglen, 0); - CryptDestroyHash(ctx->hash); - CryptReleaseContext(ctx->cryptProv, 0); -#endif ctx->valid = 0; return (ARCHIVE_OK); } -#endif /* defined(ARCHIVE_CRYPTO_*_WIN) */ +#endif /* defined(HAVE_BCRYPT_H) */ /* MD5 implementations */ @@ -234,11 +189,7 @@ __archive_md5final(archive_md5_ctx *ctx, void *md) static int __archive_md5init(archive_md5_ctx *ctx) { -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA return (win_crypto_init(ctx, BCRYPT_MD5_ALGORITHM)); -#else - return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_MD5)); -#endif } static int @@ -645,11 +596,7 @@ __archive_sha1final(archive_sha1_ctx *ctx, void *md) static int __archive_sha1init(archive_sha1_ctx *ctx) { -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA return (win_crypto_init(ctx, BCRYPT_SHA1_ALGORITHM)); -#else - return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_SHA1)); -#endif } static int @@ -925,11 +872,7 @@ __archive_sha256final(archive_sha256_ctx *ctx, void *md) static int __archive_sha256init(archive_sha256_ctx *ctx) { -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA return (win_crypto_init(ctx, BCRYPT_SHA256_ALGORITHM)); -#else - return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_256)); -#endif } static int @@ -1177,11 +1120,7 @@ __archive_sha384final(archive_sha384_ctx *ctx, void *md) static int __archive_sha384init(archive_sha384_ctx *ctx) { -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA return (win_crypto_init(ctx, BCRYPT_SHA384_ALGORITHM)); -#else - return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_384)); -#endif } static int @@ -1453,11 +1392,7 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md) static int __archive_sha512init(archive_sha512_ctx *ctx) { -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA return (win_crypto_init(ctx, BCRYPT_SHA512_ALGORITHM)); -#else - return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_512)); -#endif } static int diff --git a/contrib/libarchive/libarchive/archive_digest_private.h b/contrib/libarchive/libarchive/archive_digest_private.h index deb134e4f8..7db999450e 100644 --- a/contrib/libarchive/libarchive/archive_digest_private.h +++ b/contrib/libarchive/libarchive/archive_digest_private.h @@ -165,8 +165,7 @@ defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\ defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\ defined(ARCHIVE_CRYPTO_SHA512_WIN) -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA -/* don't use bcrypt when XP needs to be supported */ +#if defined(HAVE_BCRYPT_H) #include #define ARCHIVE_CRYPTO_CNG 1 typedef struct { @@ -174,15 +173,6 @@ typedef struct { BCRYPT_ALG_HANDLE hAlg; BCRYPT_HASH_HANDLE hHash; } Digest_CTX; -#else -#include -#include -#define ARCHIVE_CRYPTO_WINCRYPT 1 -typedef struct { - int valid; - HCRYPTPROV cryptProv; - HCRYPTHASH hash; -} Digest_CTX; #endif #endif diff --git a/contrib/libarchive/libarchive/archive_endian.h b/contrib/libarchive/libarchive/archive_endian.h index 83b2efa531..939acc6670 100644 --- a/contrib/libarchive/libarchive/archive_endian.h +++ b/contrib/libarchive/libarchive/archive_endian.h @@ -70,6 +70,22 @@ archive_be16dec(const void *pp) return ((p0 << 8) | p1); } +static inline uint32_t +archive_be24dec(const void *pp) +{ + unsigned char const *p = (unsigned char const *)pp; + + /* Store into unsigned temporaries before left shifting, to avoid + promotion to signed int and then left shifting into the sign bit, + which is undefined behaviour. */ + unsigned int p2 = p[2]; + unsigned int p1 = p[1]; + unsigned int p0 = p[0]; + + return ((p0 << 16) | (p1 << 8) | p2); +} + + static inline uint32_t archive_be32dec(const void *pp) { @@ -108,6 +124,21 @@ archive_le16dec(const void *pp) return ((p1 << 8) | p0); } +static inline uint32_t +archive_le24dec(const void *pp) +{ + unsigned char const *p = (unsigned char const *)pp; + + /* Store into unsigned temporaries before left shifting, to avoid + promotion to signed int and then left shifting into the sign bit, + which is undefined behaviour. */ + unsigned int p2 = p[2]; + unsigned int p1 = p[1]; + unsigned int p0 = p[0]; + + return ((p2 << 16) | (p1 << 8) | p0); +} + static inline uint32_t archive_le32dec(const void *pp) { @@ -170,6 +201,16 @@ archive_le16enc(void *pp, uint16_t u) p[1] = (u >> 8) & 0xff; } +static inline void +archive_le24enc(void *pp, uint32_t u) +{ + unsigned char *p = (unsigned char *)pp; + + p[0] = u & 0xff; + p[1] = (u >> 8) & 0xff; + p[2] = (u >> 16) & 0xff; +} + static inline void archive_le32enc(void *pp, uint32_t u) { diff --git a/contrib/libarchive/libarchive/archive_entry.c b/contrib/libarchive/libarchive/archive_entry.c index 4ba361ebe2..2ac5507d7c 100644 --- a/contrib/libarchive/libarchive/archive_entry.c +++ b/contrib/libarchive/libarchive/archive_entry.c @@ -1239,7 +1239,7 @@ _archive_entry_copy_link_l(struct archive_entry *entry, } void -archive_entry_set_mode(struct archive_entry *entry, mode_t m) +archive_entry_set_mode(struct archive_entry *entry, __LA_MODE_T m) { entry->stat_valid = 0; entry->acl.mode = m; @@ -1314,7 +1314,7 @@ _archive_entry_copy_pathname_l(struct archive_entry *entry, } void -archive_entry_set_perm(struct archive_entry *entry, mode_t p) +archive_entry_set_perm(struct archive_entry *entry, __LA_MODE_T p) { entry->stat_valid = 0; entry->acl.mode &= AE_IFMT; diff --git a/contrib/libarchive/libarchive/archive_entry.h b/contrib/libarchive/libarchive/archive_entry.h index 7122a74ed0..aa4f4dfb36 100644 --- a/contrib/libarchive/libarchive/archive_entry.h +++ b/contrib/libarchive/libarchive/archive_entry.h @@ -28,7 +28,7 @@ #define ARCHIVE_ENTRY_H_INCLUDED /* Note: Compiler will complain if this does not match archive.h! */ -#define ARCHIVE_VERSION_NUMBER 3008007 +#define ARCHIVE_VERSION_NUMBER 3008008 /* * Note: archive_entry.h is for use outside of libarchive; the diff --git a/contrib/libarchive/libarchive/archive_entry_link_resolver.c b/contrib/libarchive/libarchive/archive_entry_link_resolver.c index 77fcad61fd..233c46aa89 100644 --- a/contrib/libarchive/libarchive/archive_entry_link_resolver.c +++ b/contrib/libarchive/libarchive/archive_entry_link_resolver.c @@ -78,7 +78,7 @@ struct links_entry { struct archive_entry_linkresolver { struct links_entry **buckets; struct links_entry *spare; - unsigned long number_entries; + size_t number_entries; size_t number_buckets; int strategy; }; @@ -158,13 +158,12 @@ archive_entry_linkresolver_set_strategy(struct archive_entry_linkresolver *res, void archive_entry_linkresolver_free(struct archive_entry_linkresolver *res) { - struct links_entry *le; - if (res == NULL) return; - while ((le = next_entry(res, NEXT_ENTRY_ALL)) != NULL) - archive_entry_free(le->entry); + while (next_entry(res, NEXT_ENTRY_ALL) != NULL) { + /* Actual freeing done by next_entry() */ + } free(res->buckets); free(res); } @@ -382,6 +381,10 @@ insert_entry(struct archive_entry_linkresolver *res, if (le == NULL) return (NULL); le->canonical = archive_entry_clone(entry); + if (le->canonical == NULL) { + free(le); + return (NULL); + } /* If the links cache is getting too full, enlarge the hash table. */ if (res->number_entries > res->number_buckets * 2) diff --git a/contrib/libarchive/libarchive/archive_entry_sparse.c b/contrib/libarchive/libarchive/archive_entry_sparse.c index c430896119..1e84ff7f85 100644 --- a/contrib/libarchive/libarchive/archive_entry_sparse.c +++ b/contrib/libarchive/libarchive/archive_entry_sparse.c @@ -127,9 +127,10 @@ archive_entry_sparse_count(struct archive_entry *entry) int archive_entry_sparse_reset(struct archive_entry * entry) { + /* Counting can change sparse_head, so do it first */ + int count = archive_entry_sparse_count(entry); entry->sparse_p = entry->sparse_head; - - return archive_entry_sparse_count(entry); + return (count); } int diff --git a/contrib/libarchive/libarchive/archive_entry_strmode.c b/contrib/libarchive/libarchive/archive_entry_strmode.c index 5faa2faeef..22171992dd 100644 --- a/contrib/libarchive/libarchive/archive_entry_strmode.c +++ b/contrib/libarchive/libarchive/archive_entry_strmode.c @@ -28,9 +28,6 @@ #ifdef HAVE_SYS_STAT_H #include #endif -#ifdef HAVE_STRING_H -#include -#endif #include "archive_entry.h" #include "archive_entry_private.h" @@ -38,16 +35,10 @@ const char * archive_entry_strmode(struct archive_entry *entry) { - static const mode_t permbits[] = - { 0400, 0200, 0100, 0040, 0020, 0010, 0004, 0002, 0001 }; char *bp = entry->strmode; - mode_t mode; + mode_t mask, mode; int i; - /* Fill in a default string, then selectively override. */ - strcpy(bp, "?rwxrwxrwx "); - - mode = archive_entry_mode(entry); switch (archive_entry_filetype(entry)) { case AE_IFREG: bp[0] = '-'; break; case AE_IFBLK: bp[0] = 'b'; break; @@ -57,30 +48,22 @@ archive_entry_strmode(struct archive_entry *entry) case AE_IFSOCK: bp[0] = 's'; break; case AE_IFIFO: bp[0] = 'p'; break; default: - if (archive_entry_hardlink(entry) != NULL) { - bp[0] = 'h'; - break; - } + bp[0] = (archive_entry_hardlink(entry) != NULL) ? 'h' : '?'; + break; } - for (i = 0; i < 9; i++) - if (!(mode & permbits[i])) - bp[i+1] = '-'; + mode = archive_entry_mode(entry); + for (i = 0, mask = 0400; i < 9; i++, mask >>= 1) + bp[i + 1] = (mode & mask) ? "rwx"[i % 3] : '-'; - if (mode & S_ISUID) { - if (mode & 0100) bp[3] = 's'; - else bp[3] = 'S'; - } - if (mode & S_ISGID) { - if (mode & 0010) bp[6] = 's'; - else bp[6] = 'S'; - } - if (mode & S_ISVTX) { - if (mode & 0001) bp[9] = 't'; - else bp[9] = 'T'; - } - if (archive_entry_acl_types(entry) != 0) - bp[10] = '+'; + if (mode & S_ISUID) + bp[3] = (mode & 0100) ? 's' : 'S'; + if (mode & S_ISGID) + bp[6] = (mode & 0010) ? 's' : 'S'; + if (mode & S_ISVTX) + bp[9] = (mode & 0001) ? 't' : 'T'; + bp[10] = (archive_entry_acl_types(entry) != 0) ? '+' : ' '; + bp[11] = '\0'; return (bp); } diff --git a/contrib/libarchive/libarchive/archive_hmac.c b/contrib/libarchive/libarchive/archive_hmac.c index 458092f41b..e1e8f05ff0 100644 --- a/contrib/libarchive/libarchive/archive_hmac.c +++ b/contrib/libarchive/libarchive/archive_hmac.c @@ -74,7 +74,7 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) memset(ctx, 0, sizeof(*ctx)); } -#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA +#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) #ifndef BCRYPT_HASH_REUSABLE_FLAG # define BCRYPT_HASH_REUSABLE_FLAG 0x00000020 diff --git a/contrib/libarchive/libarchive/archive_hmac_private.h b/contrib/libarchive/libarchive/archive_hmac_private.h index 36b8e3320e..af00beadb5 100644 --- a/contrib/libarchive/libarchive/archive_hmac_private.h +++ b/contrib/libarchive/libarchive/archive_hmac_private.h @@ -52,7 +52,7 @@ int __libarchive_hmac_build_hack(void); typedef CCHmacContext archive_hmac_sha1_ctx; -#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA +#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) #include typedef struct { diff --git a/contrib/libarchive/libarchive/archive_integer.h b/contrib/libarchive/libarchive/archive_integer.h new file mode 100644 index 0000000000..6427c622cd --- /dev/null +++ b/contrib/libarchive/libarchive/archive_integer.h @@ -0,0 +1,247 @@ +/*- + * Copyright (c) 2026 Tobias Stoeckmann + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + */ + +#ifndef ARCHIVE_INTEGER_H_INCLUDED +#define ARCHIVE_INTEGER_H_INCLUDED + +#include "archive_platform.h" + +/* Note: This is a purely internal header! */ +/* Do not use this outside of libarchive internal code! */ + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +#ifdef HAVE_INTSAFE_H +#define ENABLE_INTSAFE_SIGNED_FUNCTIONS +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_STDCKDINT_H +#include +#endif +#ifdef HAVE_STDINT_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +#ifdef HAVE_STDCKDINT_H +#define USE_STDCKDINT 1 +#elif (__GNUC__ >= 5 && !defined(__INTEL_COMPILER)) +#define USE_BUILTIN 1 +#elif __has_builtin(__builtin_add_overflow) +#define USE_BUILTIN 1 +#elif defined HAVE_INTSAFE_H +#define USE_INTSAFE 1 +#endif + +/* + * Disabling inline keyword for compilers known to choke on it: + * - Watcom C++ in C code. (For any version?) + * - SGI MIPSpro + * - Microsoft Visual C++ 6.0 (supposedly newer versions too) + * - IBM VisualAge 6 (XL v6) + * - Sun WorkShop C (SunPro) before 5.9 + */ +#if defined(__WATCOMC__) || defined(__sgi) || defined(__hpux) || defined(__BORLANDC__) +#define inline +#elif defined(__IBMC__) && __IBMC__ < 700 +#define inline +#elif defined(__SUNPRO_C) && __SUNPRO_C < 0x590 +#define inline +#elif defined(_MSC_VER) || defined(__osf__) +#define inline __inline +#endif + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_add_i64(int64_t *result, int64_t a, int64_t b) +{ +#if USE_STDCKDINT + return ckd_add(result, a, b); +#elif USE_BUILTIN + return __builtin_add_overflow(a, b, result); +#elif USE_INTSAFE + LONGLONG res; + int ret; + + ret = LongLongAdd(a, b, &res); + *result = (int64_t)res; + return ret; +#else + if ((b > 0 && a > INT64_MAX - b) || + (b < 0 && a < INT64_MIN - b)) + return 1; + + *result = a + b; + return 0; +#endif +} + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_add_size(size_t *result, size_t a, size_t b) +{ +#if USE_STDCKDINT + return ckd_add(result, a, b); +#elif USE_BUILTIN + return __builtin_add_overflow(a, b, result); +#elif USE_INTSAFE + return SizeTAdd(a, b, result); +#else + if (a > SIZE_MAX - b) + return 1; + *result = a + b; + return 0; +#endif +} + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_add_u64(uint64_t *result, uint64_t a, uint64_t b) +{ +#if USE_STDCKDINT + return ckd_add(result, a, b); +#elif USE_BUILTIN + return __builtin_add_overflow(a, b, result); +#elif USE_INTSAFE + ULONGLONG res; + int ret; + + ret = ULongLongAdd(a, b, &res); + *result = (uint64_t)res; + return ret; +#else + if (a > UINT64_MAX - b) + return 1; + *result = a + b; + return 0; +#endif +} + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_mul_i64(int64_t *result, int64_t a, int64_t b) +{ +#if USE_STDCKDINT + return ckd_mul(result, a, b); +#elif USE_BUILTIN + return __builtin_mul_overflow(a, b, result); +#elif USE_INTSAFE + LONGLONG res; + int ret; + + ret = LongLongMult(a, b, &res); + *result = (int64_t)res; + return ret; +#else + if ((a > 0 && b > 0 && a > INT64_MAX / b) || + (a < 0 && b > 0 && a < INT64_MIN / b) || + (a > 0 && b < 0 && b < INT64_MIN / a) || + (a < 0 && b < 0 && a < INT64_MAX / b)) + return 1; + + *result = a * b; + return 0; +#endif +} + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_mul_size(size_t *result, size_t a, size_t b) +{ +#if USE_STDCKDINT + return ckd_mul(result, a, b); +#elif USE_BUILTIN + return __builtin_mul_overflow(a, b, result); +#elif USE_INTSAFE + return SizeTMult(a, b, result); +#else + if (b != 0 && a > SIZE_MAX / b) + return 1; + *result = a * b; + return 0; +#endif +} + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_mul_u64(uint64_t *result, uint64_t a, uint64_t b) +{ +#if USE_STDCKDINT + return ckd_mul(result, a, b); +#elif USE_BUILTIN + return __builtin_mul_overflow(a, b, result); +#elif USE_INTSAFE + ULONGLONG res; + int ret; + + ret = ULongLongMult(a, b, &res); + *result = (uint64_t)res; + return ret; +#else + if (b != 0 && a > UINT64_MAX / b) + return 1; + *result = a * b; + return 0; +#endif +} + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_sub_i64(int64_t *result, int64_t a, int64_t b) +{ +#if USE_STDCKDINT + return ckd_sub(result, a, b); +#elif USE_BUILTIN + return __builtin_sub_overflow(a, b, result); +#elif USE_INTSAFE + LONGLONG res; + int ret; + + ret = LongLongSub(a, b, &res); + *result = (int64_t)res; + return ret; +#else + if ((b > 0 && a < INT64_MIN + b) || + (b < 0 && a > INT64_MAX + b)) + return 1; + + *result = a - b; + return 0; +#endif +} + +#endif diff --git a/contrib/libarchive/libarchive/archive_match.c b/contrib/libarchive/libarchive/archive_match.c index 51a0e3fd57..ecd470bd15 100644 --- a/contrib/libarchive/libarchive/archive_match.c +++ b/contrib/libarchive/libarchive/archive_match.c @@ -40,6 +40,7 @@ #endif #include "archive.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_entry.h" #include "archive_pathmatch.h" @@ -216,6 +217,14 @@ error_nomem(struct archive_match *a) return (ARCHIVE_FATAL); } +static int +error_pattern(struct archive_match *a) +{ + archive_set_error(&(a->archive), EINVAL, "Failed to apply pattern"); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); +} + /* * Create an ARCHIVE_MATCH object. */ @@ -269,7 +278,7 @@ archive_match_free(struct archive *_a) * * Returns 1 if archive entry is excluded. * Returns 0 if archive entry is not excluded. - * Returns <0 if something error happened. + * Returns <0 if some error happened. */ int archive_match_excluded(struct archive *_a, struct archive_entry *entry) @@ -293,6 +302,8 @@ archive_match_excluded(struct archive *_a, struct archive_entry *entry) #else r = path_excluded(a, 1, archive_entry_pathname(entry)); #endif + if (r < 0) + return (error_pattern(a)); if (r != 0) return (r); } @@ -449,13 +460,14 @@ archive_match_include_pattern_from_file_w(struct archive *_a, * * Returns 1 if archive entry is excluded. * Returns 0 if archive entry is not excluded. - * Returns <0 if something error happened. + * Returns <0 if some error happened. */ int archive_match_path_excluded(struct archive *_a, struct archive_entry *entry) { struct archive_match *a; + int r; archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, ARCHIVE_STATE_NEW, "archive_match_path_excluded"); @@ -471,10 +483,13 @@ archive_match_path_excluded(struct archive *_a, if ((a->setflag & PATTERN_IS_SET) == 0) return (0); #if defined(_WIN32) && !defined(__CYGWIN__) - return (path_excluded(a, 0, archive_entry_pathname_w(entry))); + r = path_excluded(a, 0, archive_entry_pathname_w(entry)); #else - return (path_excluded(a, 1, archive_entry_pathname(entry))); + r = path_excluded(a, 1, archive_entry_pathname(entry)); #endif + if (r < 0) + return (error_pattern(a)); + return (r); } /* @@ -629,11 +644,12 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist, } r = archive_read_next_header(ar, &ae); if (r != ARCHIVE_OK) { - archive_read_free(ar); if (r == ARCHIVE_EOF) { + archive_read_free(ar); return (ARCHIVE_OK); } else { archive_copy_error(&(a->archive), ar); + archive_read_free(ar); return (r); } } @@ -1007,7 +1023,7 @@ archive_match_exclude_entry(struct archive *_a, int flag, * * Returns 1 if archive entry is excluded. * Returns 0 if archive entry is not excluded. - * Returns <0 if something error happened. + * Returns <0 if some error happened. */ int archive_match_time_excluded(struct archive *_a, @@ -1653,7 +1669,7 @@ archive_match_include_gname_w(struct archive *_a, const wchar_t *gname) * * Returns 1 if archive entry is excluded. * Returns 0 if archive entry is not excluded. - * Returns <0 if something error happened. + * Returns <0 if some error happened. */ int archive_match_owner_excluded(struct archive *_a, @@ -1684,15 +1700,22 @@ add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id) if (ids->count + 1 >= ids->size) { void *p; + size_t alloc_size, new_size; if (ids->size == 0) - ids->size = 8; - else - ids->size *= 2; - p = realloc(ids->ids, sizeof(*ids->ids) * ids->size); + new_size = 8; + else { + if (archive_ckd_mul_size(&new_size, ids->size, 2)) + return (error_nomem(a)); + } + if (archive_ckd_mul_size(&alloc_size, + new_size, sizeof(*ids->ids))) + return (error_nomem(a)); + p = realloc(ids->ids, alloc_size); if (p == NULL) return (error_nomem(a)); ids->ids = (int64_t *)p; + ids->size = new_size; } /* Find an insert point. */ diff --git a/contrib/libarchive/libarchive/archive_options.c b/contrib/libarchive/libarchive/archive_options.c index 66491bd418..24480b97e2 100644 --- a/contrib/libarchive/libarchive/archive_options.c +++ b/contrib/libarchive/libarchive/archive_options.c @@ -31,8 +31,8 @@ #include "archive_options_private.h" -static const char * -parse_option(const char **str, +static char * +parse_option(char **str, const char **mod, const char **opt, const char **val); int @@ -102,8 +102,8 @@ _archive_set_options(struct archive *a, const char *options, unsigned int magic, const char *fn, option_handler use_option) { int allok = 1, anyok = 0, ignore_mod_err = 0, r; - char *data; - const char *s, *mod, *opt, *val; + char *data, *s; + const char *mod, *opt, *val; archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn); @@ -115,7 +115,7 @@ _archive_set_options(struct archive *a, const char *options, ENOMEM, "Out of memory adding file to list"); return (ARCHIVE_FATAL); } - s = (const char *)data; + s = data; do { mod = opt = val = NULL; @@ -167,11 +167,11 @@ _archive_set_options(struct archive *a, const char *options, return allok ? ARCHIVE_OK : anyok ? ARCHIVE_WARN : ARCHIVE_FAILED; } -static const char * -parse_option(const char **s, const char **m, const char **o, const char **v) +static char * +parse_option(char **s, const char **m, const char **o, const char **v) { - const char *end, *mod, *opt, *val; - char *p; + const char *mod, *val; + char *end, *opt, *p; end = NULL; mod = NULL; @@ -182,7 +182,7 @@ parse_option(const char **s, const char **m, const char **o, const char **v) if (p != NULL) { *p = '\0'; - end = ((const char *)p) + 1; + end = p + 1; } if (0 == strlen(opt)) { diff --git a/contrib/libarchive/libarchive/archive_pack_dev.c b/contrib/libarchive/libarchive/archive_pack_dev.c index 3c6209b984..e293512928 100644 --- a/contrib/libarchive/libarchive/archive_pack_dev.c +++ b/contrib/libarchive/libarchive/archive_pack_dev.c @@ -319,7 +319,7 @@ compare_format(const void *key, const void *element) pack_t * pack_find(const char *name) { - struct format *format; + const struct format *format; format = bsearch(name, formats, sizeof(formats)/sizeof(formats[0]), diff --git a/contrib/libarchive/libarchive/archive_parse_date.c b/contrib/libarchive/libarchive/archive_parse_date.c index d9e968387d..c1b0f18311 100644 --- a/contrib/libarchive/libarchive/archive_parse_date.c +++ b/contrib/libarchive/libarchive/archive_parse_date.c @@ -36,6 +36,7 @@ #include #include "archive.h" +#include "archive_integer.h" /* Basic time units. */ #define EPOCH 1970 @@ -49,7 +50,7 @@ enum DSTMODE { DSTon, DSToff, DSTmaybe }; enum { tAM, tPM }; /* Token types returned by nexttoken() */ enum { tAGO = 260, tDAY, tDAYZONE, tAMPM, tMONTH, tMONTH_UNIT, tSEC_UNIT, - tUNUMBER, tZONE, tDST }; + tUNUMBER, tZONE, tDST, tERROR }; struct token { int token; time_t value; }; /* @@ -818,20 +819,33 @@ RelativeMonth(time_t Start, time_t Timezone, time_t RelMonth) } /* - * Parses and consumes an unsigned number. - * Returns 1 if any number is parsed. Otherwise, *value is unchanged. + * Parses and consumes an unsigned 64-bit number. + * Returns UINT64_MAX if the number overflows. */ -static char -consume_unsigned_number(const char **in, time_t *value) -{ - char c; - if (isdigit((unsigned char)(c = **in))) { - for (*value = 0; isdigit((unsigned char)(c = *(*in)++)); ) - *value = 10 * *value + c - '0'; - (*in)--; - return 1; +static uint64_t +consume_unsigned_number(const char **in) { + uint64_t value = 0; + unsigned char c; + + /* Get the first character, abort if it's not a digit */ + c = (unsigned char)(**in); + if (c < '0' || c > '9') { + return UINT64_MAX; } - return 0; + + /* Fold digits into the value, abort on overflow */ + while (c >= '0' && c <= '9') { + unsigned char digit = c - '0'; + + /* Return error if the result would overflow UINT64_MAX */ + if (archive_ckd_mul_u64(&value, value, 10) || + archive_ckd_add_u64(&value, value, digit)) { + return UINT64_MAX; + } + (*in)++; + c = (unsigned char)(**in); + } + return value; } /* @@ -906,12 +920,19 @@ nexttoken(const char **in, time_t *value) } /* - * Not in the word table, maybe it's a number. Note: - * Because '-' and '+' have other special meanings, I - * don't deal with signed numbers here. + * Not in the word table. If it starts with a digit, + * it must be a number. Note: Because '-' and '+' have + * other special meanings, I don't deal with signed + * numbers here. */ - if (consume_unsigned_number(in, value)) { - return (tUNUMBER); + if (isdigit((unsigned char)(**in))) { + uint64_t val = consume_unsigned_number(in); + if (val > 9999) { + return (tERROR); + } else { + *value = val; + return (tUNUMBER); + } } return *(*in)++; @@ -949,6 +970,7 @@ difftm (struct tm *a, struct tm *b) static time_t parse_unix_epoch(const char *p) { + uint64_t val; time_t epoch; /* may begin with + */ @@ -957,12 +979,18 @@ parse_unix_epoch(const char *p) } /* followed by some number */ - if (!consume_unsigned_number(&p, &epoch)) + val = consume_unsigned_number(&p); + /* Truncate to time_t */ + epoch = (time_t)val; + /* If truncated value is different, then + * the value is too large for `time_t`. */ + if (epoch < 0 || (uint64_t)epoch != val) { return (time_t)-1; - - /* ...and nothing else */ - if (*p != '\0') + } + /* If there's any more characters, fail. */ + if (*p != '\0') { return (time_t)-1; + } return epoch; } diff --git a/contrib/libarchive/libarchive/archive_pathmatch.c b/contrib/libarchive/libarchive/archive_pathmatch.c index db0d2b791a..4b69ae1e4a 100644 --- a/contrib/libarchive/libarchive/archive_pathmatch.c +++ b/contrib/libarchive/libarchive/archive_pathmatch.c @@ -35,6 +35,8 @@ #include "archive_pathmatch.h" +#define MAX_RECURSION 100 + /* * Check whether a character 'c' is matched by a list specification [...]: * * Leading '!' or '^' negates the class. @@ -167,9 +169,13 @@ pm_slashskip_w(const wchar_t *s) { } static int -pm(const char *p, const char *s, int flags) +pm(const char *p, const char *s, int flags, int depth) { const char *end; + int r; + + if (depth > MAX_RECURSION) + return (-1); /* * Ignore leading './', './/', '././', etc. @@ -202,8 +208,9 @@ pm(const char *p, const char *s, int flags) if (*p == '\0') return (1); while (*s) { - if (pm(p, s, flags)) - return (1); + r = pm(p, s, flags, depth + 1); + if (r) + return (r); ++s; } return (0); @@ -220,7 +227,7 @@ pm(const char *p, const char *s, int flags) } if (*end == ']') { /* We found [...], try to match it. */ - if (!pm_list(p + 1, end, *s, flags)) + if (*s == '\0' || !pm_list(p + 1, end, *s, flags)) return (0); p = end; /* Jump to trailing ']' char. */ break; @@ -272,9 +279,13 @@ pm(const char *p, const char *s, int flags) } static int -pm_w(const wchar_t *p, const wchar_t *s, int flags) +pm_w(const wchar_t *p, const wchar_t *s, int flags, int depth) { const wchar_t *end; + int r; + + if (depth > MAX_RECURSION) + return (-1); /* * Ignore leading './', './/', '././', etc. @@ -307,8 +318,9 @@ pm_w(const wchar_t *p, const wchar_t *s, int flags) if (*p == L'\0') return (1); while (*s) { - if (pm_w(p, s, flags)) - return (1); + r = pm_w(p, s, flags, depth + 1); + if (r) + return (r); ++s; } return (0); @@ -387,7 +399,7 @@ __archive_pathmatch(const char *p, const char *s, int flags) return (0); /* Leading '^' anchors the start of the pattern. */ - if (*p == '^') { + if ((flags & PATHMATCH_NO_ANCHOR_START) && *p == '^') { ++p; flags &= ~PATHMATCH_NO_ANCHOR_START; } @@ -401,22 +413,25 @@ __archive_pathmatch(const char *p, const char *s, int flags) ++p; while (*s == '/') ++s; - return (pm(p, s, flags)); + return (pm(p, s, flags, 0)); } /* If start is unanchored, try to match start of each path element. */ if (flags & PATHMATCH_NO_ANCHOR_START) { for ( ; s != NULL; s = strchr(s, '/')) { + int r; + if (*s == '/') s++; - if (pm(p, s, flags)) - return (1); + r = pm(p, s, flags, 0); + if (r) + return (r); } return (0); } /* Default: Match from beginning. */ - return (pm(p, s, flags)); + return (pm(p, s, flags, 0)); } int @@ -429,7 +444,7 @@ __archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags) return (0); /* Leading '^' anchors the start of the pattern. */ - if (*p == L'^') { + if ((flags & PATHMATCH_NO_ANCHOR_START) && *p == L'^') { ++p; flags &= ~PATHMATCH_NO_ANCHOR_START; } @@ -443,20 +458,23 @@ __archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags) ++p; while (*s == L'/') ++s; - return (pm_w(p, s, flags)); + return (pm_w(p, s, flags, 0)); } /* If start is unanchored, try to match start of each path element. */ if (flags & PATHMATCH_NO_ANCHOR_START) { for ( ; s != NULL; s = wcschr(s, L'/')) { + int r; + if (*s == L'/') s++; - if (pm_w(p, s, flags)) - return (1); + r = pm_w(p, s, flags, 0); + if (r) + return (r); } return (0); } /* Default: Match from beginning. */ - return (pm_w(p, s, flags)); + return (pm_w(p, s, flags, 0)); } diff --git a/contrib/libarchive/libarchive/archive_random.c b/contrib/libarchive/libarchive/archive_random.c index 8c48d2d3b5..28cba00bd3 100644 --- a/contrib/libarchive/libarchive/archive_random.c +++ b/contrib/libarchive/libarchive/archive_random.c @@ -58,18 +58,12 @@ static void la_arc4random_buf(void *, size_t); #include "archive_random_private.h" #if defined(_WIN32) && !defined(__CYGWIN__) -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA -/* don't use bcrypt when XP needs to be supported */ #include /* Common in other bcrypt implementations, but missing from VS2008. */ #ifndef BCRYPT_SUCCESS #define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS) #endif - -#elif defined(HAVE_WINCRYPT_H) -#include -#endif #endif #ifndef O_CLOEXEC @@ -85,7 +79,6 @@ int archive_random(void *buf, size_t nbytes) { #if defined(_WIN32) && !defined(__CYGWIN__) -# if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA NTSTATUS status; BCRYPT_ALG_HANDLE hAlg; @@ -98,25 +91,6 @@ archive_random(void *buf, size_t nbytes) return ARCHIVE_FAILED; return ARCHIVE_OK; -# else - HCRYPTPROV hProv; - BOOL success; - - success = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT); - if (!success && GetLastError() == (DWORD)NTE_BAD_KEYSET) { - success = CryptAcquireContext(&hProv, NULL, NULL, - PROV_RSA_FULL, CRYPT_NEWKEYSET); - } - if (success) { - success = CryptGenRandom(hProv, (DWORD)nbytes, (BYTE*)buf); - CryptReleaseContext(hProv, 0); - if (success) - return ARCHIVE_OK; - } - /* TODO: Does this case really happen? */ - return ARCHIVE_FAILED; -# endif #elif !defined(HAVE_ARC4RANDOM_BUF) && (!defined(_WIN32) || defined(__CYGWIN__)) la_arc4random_buf(buf, nbytes); return ARCHIVE_OK; diff --git a/contrib/libarchive/libarchive/archive_read.c b/contrib/libarchive/libarchive/archive_read.c index e5f89bdc87..b23d99dd7b 100644 --- a/contrib/libarchive/libarchive/archive_read.c +++ b/contrib/libarchive/libarchive/archive_read.c @@ -36,6 +36,9 @@ #ifdef HAVE_ERRNO_H #include #endif +#ifdef HAVE_LIMITS_H +#include +#endif #include #ifdef HAVE_STDLIB_H #include @@ -49,6 +52,7 @@ #include "archive.h" #include "archive_entry.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_read_private.h" @@ -252,42 +256,39 @@ client_close_proxy(struct archive_read_filter *self) return read_client_close_proxy(self->archive); } -static int -client_open_proxy(struct archive_read_filter *self) -{ - int r = ARCHIVE_OK; - if (self->archive->client.opener != NULL) - r = (self->archive->client.opener)( - (struct archive *)self->archive, self->data); - return (r); -} - static int client_switch_proxy(struct archive_read_filter *self, unsigned int iindex) { - int r1 = ARCHIVE_OK, r2 = ARCHIVE_OK; - void *data2 = NULL; + struct archive_read *a; + int r1 = ARCHIVE_OK, r2 = ARCHIVE_OK; + void *data2; + + while (self->upstream != NULL) + self = self->upstream; + a = self->archive; /* Don't do anything if already in the specified data node */ - if (self->archive->client.cursor == iindex) + if (a->client.cursor == iindex) return (ARCHIVE_OK); - self->archive->client.cursor = iindex; - data2 = self->archive->client.dataset[self->archive->client.cursor].data; - if (self->archive->client.switcher != NULL) + a->client.cursor = iindex; + data2 = a->client.dataset[a->client.cursor].data; + if (a->client.switcher != NULL) { - r1 = r2 = (self->archive->client.switcher) - ((struct archive *)self->archive, self->data, data2); + r1 = r2 = (a->client.switcher) + ((struct archive *)a, self->data, data2); self->data = data2; } else { /* Attempt to call close and open instead */ - if (self->archive->client.closer != NULL) - r1 = (self->archive->client.closer) - ((struct archive *)self->archive, self->data); + if (a->client.closer != NULL) + r1 = (a->client.closer) + ((struct archive *)a, self->data); self->data = data2; - r2 = client_open_proxy(self); + if (a->client.opener != NULL) + r2 = (a->client.opener) + ((struct archive *)a, self->data); } return (r1 < r2) ? r1 : r2; } @@ -403,7 +404,9 @@ archive_read_add_callback_data(struct archive *_a, void *client_data, { struct archive_read *a = (struct archive_read *)_a; void *p; + size_t alloc_size; unsigned int i; + unsigned int nodes; archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_add_callback_data"); @@ -412,14 +415,26 @@ archive_read_add_callback_data(struct archive *_a, void *client_data, "Invalid index specified"); return ARCHIVE_FATAL; } - p = realloc(a->client.dataset, sizeof(*a->client.dataset) - * (++(a->client.nodes))); + + if (a->client.nodes == UINT_MAX || + archive_ckd_mul_size(&alloc_size, + (size_t)a->client.nodes + 1, sizeof(*a->client.dataset))) { + archive_set_error(&a->archive, ENOMEM, + "No memory"); + return ARCHIVE_FATAL; + } + + nodes = a->client.nodes + 1; + p = realloc(a->client.dataset, alloc_size); if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "No memory"); return ARCHIVE_FATAL; } + a->client.dataset = (struct archive_read_data_node *)p; + a->client.nodes = nodes; + for (i = a->client.nodes - 1; i > iindex; i--) { a->client.dataset[i].data = a->client.dataset[i-1].data; a->client.dataset[i].begin_position = -1; @@ -934,7 +949,10 @@ archive_read_data_skip(struct archive *_a) if (r == ARCHIVE_EOF) r = ARCHIVE_OK; - a->archive.state = ARCHIVE_STATE_HEADER; + if (r == ARCHIVE_FATAL) + a->archive.state = ARCHIVE_STATE_FATAL; + else + a->archive.state = ARCHIVE_STATE_HEADER; return (r); } @@ -942,6 +960,8 @@ la_int64_t archive_seek_data(struct archive *_a, int64_t offset, int whence) { struct archive_read *a = (struct archive_read *)_a; + la_int64_t r; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, "archive_seek_data_block"); @@ -949,10 +969,14 @@ archive_seek_data(struct archive *_a, int64_t offset, int whence) archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, "Internal error: " "No format_seek_data_block function registered"); + a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); } - return (a->format->seek_data)(a, offset, whence); + r = (a->format->seek_data)(a, offset, whence); + if (r == ARCHIVE_FATAL) + a->archive.state = ARCHIVE_STATE_FATAL; + return (r); } /* @@ -968,6 +992,8 @@ _archive_read_data_block(struct archive *_a, const void **buff, size_t *size, int64_t *offset) { struct archive_read *a = (struct archive_read *)_a; + int r; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, "archive_read_data_block"); @@ -975,10 +1001,14 @@ _archive_read_data_block(struct archive *_a, archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, "Internal error: " "No format->read_data function registered"); + a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); } - return (a->format->read_data)(a, buff, size, offset); + r = (a->format->read_data)(a, buff, size, offset); + if (r == ARCHIVE_FATAL) + a->archive.state = ARCHIVE_STATE_FATAL; + return (r); } static int @@ -1366,7 +1396,7 @@ __archive_read_filter_ahead(struct archive_read_filter *filter, /* Move data forward in copy buffer if necessary. */ if (filter->next > filter->buffer && - filter->next + min > filter->buffer + filter->buffer_size) { + min > filter->buffer_size - (filter->next - filter->buffer)) { if (filter->avail > 0) memmove(filter->buffer, filter->next, filter->avail); diff --git a/contrib/libarchive/libarchive/archive_read_append_filter.c b/contrib/libarchive/libarchive/archive_read_append_filter.c index d578b06fe7..04c3627413 100644 --- a/contrib/libarchive/libarchive/archive_read_append_filter.c +++ b/contrib/libarchive/libarchive/archive_read_append_filter.c @@ -37,7 +37,7 @@ int archive_read_append_filter(struct archive *_a, int code) { int r1, r2, number_bidders, i; - char str[20]; + const char *str; struct archive_read_filter_bidder *bidder; struct archive_read_filter *filter; struct archive_read *a = (struct archive_read *)_a; @@ -53,15 +53,15 @@ archive_read_append_filter(struct archive *_a, int code) r1 = (ARCHIVE_OK); break; case ARCHIVE_FILTER_GZIP: - strcpy(str, "gzip"); + str = "gzip"; r1 = archive_read_support_filter_gzip(_a); break; case ARCHIVE_FILTER_BZIP2: - strcpy(str, "bzip2"); + str = "bzip2"; r1 = archive_read_support_filter_bzip2(_a); break; case ARCHIVE_FILTER_COMPRESS: - strcpy(str, "compress (.Z)"); + str = "compress (.Z)"; r1 = archive_read_support_filter_compress(_a); break; case ARCHIVE_FILTER_PROGRAM: @@ -69,43 +69,43 @@ archive_read_append_filter(struct archive *_a, int code) "Cannot append program filter using archive_read_append_filter"); return (ARCHIVE_FATAL); case ARCHIVE_FILTER_LZMA: - strcpy(str, "lzma"); + str = "lzma"; r1 = archive_read_support_filter_lzma(_a); break; case ARCHIVE_FILTER_XZ: - strcpy(str, "xz"); + str = "xz"; r1 = archive_read_support_filter_xz(_a); break; case ARCHIVE_FILTER_UU: - strcpy(str, "uu"); + str = "uu"; r1 = archive_read_support_filter_uu(_a); break; case ARCHIVE_FILTER_RPM: - strcpy(str, "rpm"); + str = "rpm"; r1 = archive_read_support_filter_rpm(_a); break; case ARCHIVE_FILTER_LZ4: - strcpy(str, "lz4"); + str = "lz4"; r1 = archive_read_support_filter_lz4(_a); break; case ARCHIVE_FILTER_ZSTD: - strcpy(str, "zstd"); + str = "zstd"; r1 = archive_read_support_filter_zstd(_a); break; case ARCHIVE_FILTER_LZIP: - strcpy(str, "lzip"); + str = "lzip"; r1 = archive_read_support_filter_lzip(_a); break; case ARCHIVE_FILTER_LZOP: - strcpy(str, "lzop"); + str = "lzop"; r1 = archive_read_support_filter_lzop(_a); break; case ARCHIVE_FILTER_LRZIP: - strcpy(str, "lrzip"); + str = "lrzip"; r1 = archive_read_support_filter_lrzip(_a); break; case ARCHIVE_FILTER_GRZIP: - strcpy(str, "grzip"); + str = "grzip"; r1 = archive_read_support_filter_grzip(_a); break; default: diff --git a/contrib/libarchive/libarchive/archive_read_data_into_fd.c b/contrib/libarchive/libarchive/archive_read_data_into_fd.c index 8fd5e12442..38de5b4b4d 100644 --- a/contrib/libarchive/libarchive/archive_read_data_into_fd.c +++ b/contrib/libarchive/libarchive/archive_read_data_into_fd.c @@ -46,9 +46,9 @@ */ static int pad_to(struct archive *a, int fd, int can_lseek, - size_t nulls_size, const char *nulls, - int64_t target_offset, int64_t actual_offset) + char **nulls, int64_t target_offset, int64_t actual_offset) { + const size_t nulls_size = 16384; size_t to_write; ssize_t bytes_written; @@ -56,16 +56,26 @@ pad_to(struct archive *a, int fd, int can_lseek, actual_offset = lseek(fd, target_offset - actual_offset, SEEK_CUR); if (actual_offset != target_offset) { - archive_set_error(a, errno, "Seek error"); + archive_set_error(a, + actual_offset == -1 ? errno : ARCHIVE_ERRNO_MISC, + "Seek error"); return (ARCHIVE_FATAL); } return (ARCHIVE_OK); } + if (*nulls == NULL) { + *nulls = calloc(1, nulls_size); + if (*nulls == NULL) { + archive_set_error(a, errno, "Out of memory"); + return (ARCHIVE_FATAL); + } + } + while (target_offset > actual_offset) { to_write = nulls_size; if (target_offset < actual_offset + (int64_t)nulls_size) to_write = (size_t)(target_offset - actual_offset); - bytes_written = write(fd, nulls, to_write); + bytes_written = write(fd, *nulls, to_write); if (bytes_written < 0) { archive_set_error(a, errno, "Write error"); return (ARCHIVE_FATAL); @@ -84,29 +94,27 @@ archive_read_data_into_fd(struct archive *a, int fd) const void *buff; size_t size, bytes_to_write; ssize_t bytes_written; + int64_t fd_offset; int64_t target_offset; int64_t actual_offset = 0; int can_lseek; char *nulls = NULL; - size_t nulls_size = 16384; archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, "archive_read_data_into_fd"); can_lseek = (fstat(fd, &st) == 0) && S_ISREG(st.st_mode); - if (!can_lseek) { - nulls = calloc(1, nulls_size); - if (!nulls) { - r = ARCHIVE_FATAL; - goto cleanup; - } + if (can_lseek) { + fd_offset = lseek(fd, 0, SEEK_CUR); + if (fd_offset == -1) + can_lseek = 0; } while ((r = archive_read_data_block(a, &buff, &size, &target_offset)) == ARCHIVE_OK) { const char *p = buff; if (target_offset > actual_offset) { - r = pad_to(a, fd, can_lseek, nulls_size, nulls, + r = pad_to(a, fd, can_lseek, &nulls, target_offset, actual_offset); if (r != ARCHIVE_OK) break; @@ -129,7 +137,7 @@ archive_read_data_into_fd(struct archive *a, int fd) } if (r == ARCHIVE_EOF && target_offset > actual_offset) { - r2 = pad_to(a, fd, can_lseek, nulls_size, nulls, + r2 = pad_to(a, fd, can_lseek, &nulls, target_offset, actual_offset); if (r2 != ARCHIVE_OK) r = r2; @@ -139,5 +147,15 @@ archive_read_data_into_fd(struct archive *a, int fd) free(nulls); if (r != ARCHIVE_EOF) return (r); - return (ARCHIVE_OK); + r = ARCHIVE_OK; + if (can_lseek) { + int64_t offset = lseek(fd, 0, SEEK_CUR); + if (offset - fd_offset != actual_offset) { + archive_set_error(a, + offset == -1 ? errno : ARCHIVE_ERRNO_MISC, + "Seek error"); + r = ARCHIVE_FATAL; + } + } + return (r); } diff --git a/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c b/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c index 6e6bae6a4e..c4ad595fa4 100644 --- a/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c +++ b/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c @@ -256,6 +256,11 @@ archive_read_disk_entry_from_file(struct archive *_a, char *linkbuffer; ssize_t lnklen; + if (st->st_size >= SSIZE_MAX) { + archive_set_error(&a->archive, ENOMEM, + "Couldn't read link data"); + return (ARCHIVE_FAILED); + } linkbuffer = malloc(linkbuffer_len + 1); if (linkbuffer == NULL) { archive_set_error(&a->archive, ENOMEM, @@ -894,7 +899,7 @@ setup_sparse_fiemap(struct archive_read_disk *a, r = ioctl(*fd, FS_IOC_FIEMAP, fm); if (r < 0) { - /* When something error happens, it is better we + /* When some error happens, it is better we * should return ARCHIVE_OK because an earlier * version(<2.6.28) cannot perform FS_IOC_FIEMAP. */ goto exit_setup_sparse_fiemap; diff --git a/contrib/libarchive/libarchive/archive_read_disk_posix.c b/contrib/libarchive/libarchive/archive_read_disk_posix.c index a7176bdd93..47c1d33436 100644 --- a/contrib/libarchive/libarchive/archive_read_disk_posix.c +++ b/contrib/libarchive/libarchive/archive_read_disk_posix.c @@ -920,7 +920,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, if (a->matching) { r = archive_match_path_excluded(a->matching, entry); if (r < 0) { - archive_set_error(&(a->archive), errno, + archive_set_error(&(a->archive), archive_errno(a->matching), "%s", archive_error_string(a->matching)); return (r); } @@ -1034,7 +1034,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, if (a->matching) { r = archive_match_time_excluded(a->matching, entry); if (r < 0) { - archive_set_error(&(a->archive), errno, + archive_set_error(&(a->archive), archive_errno(a->matching), "%s", archive_error_string(a->matching)); return (r); } @@ -1060,7 +1060,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, if (a->matching) { r = archive_match_owner_excluded(a->matching, entry); if (r < 0) { - archive_set_error(&(a->archive), errno, + archive_set_error(&(a->archive), archive_errno(a->matching), "%s", archive_error_string(a->matching)); return (r); } @@ -1413,18 +1413,18 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) /* * This is the new filesystem which we have to generate a new ID for. */ - fid = t->max_filesystem_id++; - if (fid > MAX_FILESYSTEM_ID) { + fid = t->max_filesystem_id; + if (fid >= MAX_FILESYSTEM_ID) { archive_set_error(&a->archive, ENOMEM, "Too many filesystems"); return (ARCHIVE_FATAL); } - if (t->max_filesystem_id > t->allocated_filesystem) { + if (fid + 1 > t->allocated_filesystem) { int s; void *p; - s = t->max_filesystem_id * 2; + s = (fid + 1) * 2; p = realloc(t->filesystem_table, - s * sizeof(*t->filesystem_table)); + s * sizeof(*t->filesystem_table)); if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate tar data"); @@ -1433,6 +1433,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) t->filesystem_table = (struct filesystem *)p; t->allocated_filesystem = s; } + t->max_filesystem_id = fid + 1; t->current_filesystem_id = fid; t->current_filesystem = &(t->filesystem_table[fid]); t->current_filesystem->dev = dev; diff --git a/contrib/libarchive/libarchive/archive_read_filter.3 b/contrib/libarchive/libarchive/archive_read_filter.3 index 72ff240fd3..05513ececd 100644 --- a/contrib/libarchive/libarchive/archive_read_filter.3 +++ b/contrib/libarchive/libarchive/archive_read_filter.3 @@ -142,7 +142,9 @@ These functions return .Cm ARCHIVE_OK if the compression is fully supported, .Cm ARCHIVE_WARN -if the compression is supported only through an external program. +if the compression is supported only through an external program, or +.Cm ARCHIVE_FATAL +on error. .Pp .Fn archive_read_support_filter_none always succeeds. @@ -158,5 +160,4 @@ functions. .Xr archive_read 3 , .Xr archive_read_data 3 , .Xr archive_read_format 3 , -.Xr archive_read_format 3 , .Xr libarchive 3 diff --git a/contrib/libarchive/libarchive/archive_read_open.3 b/contrib/libarchive/libarchive/archive_read_open.3 index 081b7114be..0e85d16f0d 100644 --- a/contrib/libarchive/libarchive/archive_read_open.3 +++ b/contrib/libarchive/libarchive/archive_read_open.3 @@ -31,6 +31,7 @@ .Nm archive_read_open_fd , .Nm archive_read_open_FILE , .Nm archive_read_open_filename , +.Nm archive_read_open_filenames , .Nm archive_read_open_memory .Nd functions for reading streaming archives .Sh LIBRARY @@ -65,6 +66,12 @@ Streaming Archive Library (libarchive, -larchive) .Fa "size_t block_size" .Fc .Ft int +.Fo archive_read_open_filenames +.Fa "struct archive *" +.Fa "const char **filenames" +.Fa "size_t block_size" +.Fc +.Ft int .Fn archive_read_open_memory "struct archive *" "const void *buff" "size_t size" .Sh DESCRIPTION .Bl -tag -compact -width indent @@ -111,6 +118,15 @@ Like except that it accepts a simple filename and a block size. A NULL filename represents standard input. This function is safe for use with tape drives or other blocked devices. +.It Fn archive_read_open_filenames +Like +.Fn archive_read_open , +except that it accepts a NULL-terminated array of filenames to open in +sequence (as would be created by the +.Xr split 1 +command) and a block size. +A NULL filename at the beginning of the array represents standard input. +This function is safe for use with tape drives or other blocked devices. .It Fn archive_read_open_memory Like .Fn archive_read_open , diff --git a/contrib/libarchive/libarchive/archive_read_open_filename.c b/contrib/libarchive/libarchive/archive_read_open_filename.c index 9ec1e6c0e8..91f64b694a 100644 --- a/contrib/libarchive/libarchive/archive_read_open_filename.c +++ b/contrib/libarchive/libarchive/archive_read_open_filename.c @@ -40,6 +40,9 @@ #ifdef HAVE_IO_H #include #endif +#ifdef HAVE_LIMITS_H +#include +#endif #ifdef HAVE_STDLIB_H #include #endif @@ -181,7 +184,7 @@ archive_read_open_filenames_w(struct archive *a, const wchar_t **wfilenames, if (wfilename == NULL) wfilename = L""; mine = calloc(1, - sizeof(*mine) + wcslen(wfilename) * sizeof(wchar_t)); + sizeof(*mine) + wcslen(wfilename) * MB_LEN_MAX); if (mine == NULL) goto no_memory; mine->block_size = block_size; @@ -315,7 +318,7 @@ file_open(struct archive *a, void *client_data) } #else archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Unexpedted operation in archive_read_open_filename"); + "Unexpected operation in archive_read_open_filename"); goto fail; #endif } diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_all.c b/contrib/libarchive/libarchive/archive_read_support_filter_all.c index cb46d120d1..f08677301f 100644 --- a/contrib/libarchive/libarchive/archive_read_support_filter_all.c +++ b/contrib/libarchive/libarchive/archive_read_support_filter_all.c @@ -43,34 +43,34 @@ archive_read_support_filter_all(struct archive *a) archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_support_filter_all"); - /* Bzip falls back to "bunzip2" command-line */ + /* Bzip falls back to "bzip2 -d" command-line */ archive_read_support_filter_bzip2(a); /* The decompress code doesn't use an outside library. */ archive_read_support_filter_compress(a); /* Gzip decompress falls back to "gzip -d" command-line. */ archive_read_support_filter_gzip(a); - /* Lzip falls back to "unlzip" command-line program. */ + /* Lzip falls back to "lzip -d -q" command-line. */ archive_read_support_filter_lzip(a); /* The LZMA file format has a very weak signature, so it * may not be feasible to keep this here, but we'll try. * This will come back out if there are problems. */ - /* Lzma falls back to "unlzma" command-line program. */ + /* Lzma falls back to "lzma -d -qq" command-line. */ archive_read_support_filter_lzma(a); - /* Xz falls back to "unxz" command-line program. */ + /* Xz falls back to "xz -d -qq" command-line. */ archive_read_support_filter_xz(a); /* The decode code doesn't use an outside library. */ archive_read_support_filter_uu(a); /* The decode code doesn't use an outside library. */ archive_read_support_filter_rpm(a); - /* The decode code always uses "lrzip -q -d" command-line. */ + /* The decode code always uses "lrzip -d -q" command-line. */ archive_read_support_filter_lrzip(a); /* Lzop decompress falls back to "lzop -d" command-line. */ archive_read_support_filter_lzop(a); /* The decode code always uses "grzip -d" command-line. */ archive_read_support_filter_grzip(a); - /* Lz4 falls back to "lz4 -d" command-line program. */ + /* Lz4 falls back to "lz4 -d -q" command-line. */ archive_read_support_filter_lz4(a); - /* Zstd falls back to "zstd -d" command-line program. */ + /* Zstd falls back to "zstd -d -qq" command-line. */ archive_read_support_filter_zstd(a); /* Note: We always return ARCHIVE_OK here, even if some of the diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_bzip2.c b/contrib/libarchive/libarchive/archive_read_support_filter_bzip2.c index 479237c277..26d550e2c4 100644 --- a/contrib/libarchive/libarchive/archive_read_support_filter_bzip2.c +++ b/contrib/libarchive/libarchive/archive_read_support_filter_bzip2.c @@ -28,6 +28,9 @@ #ifdef HAVE_ERRNO_H #include #endif +#ifdef HAVE_LIMITS_H +#include +#endif #include #ifdef HAVE_STDLIB_H #include @@ -63,8 +66,7 @@ static int bzip2_filter_close(struct archive_read_filter *); /* * Note that we can detect bzip2 archives even if we can't decompress * them. (In fact, we like detecting them because we can give better - * error messages.) So the bid framework here gets compiled even - * if bzlib is unavailable. + * error messages.) */ static int bzip2_reader_bid(struct archive_read_filter_bidder *, struct archive_read_filter *); static int bzip2_reader_init(struct archive_read_filter *); @@ -113,13 +115,12 @@ static int bzip2_reader_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) { const unsigned char *buffer; - ssize_t avail; int bits_checked; (void)self; /* UNUSED */ /* Minimal bzip2 archive is 14 bytes. */ - buffer = __archive_read_filter_ahead(filter, 14, &avail); + buffer = __archive_read_filter_ahead(filter, 14, NULL); if (buffer == NULL) return (0); @@ -150,9 +151,9 @@ bzip2_reader_bid(struct archive_read_filter_bidder *self, struct archive_read_fi #if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) /* - * If we don't have the library on this system, we can't actually do the - * decompression. We can, however, still detect compressed archives - * and emit a useful message. + * If we don't have the library on this system, we can't do the + * decompression directly. We can, however, try to run "bzip2 -d" + * in case that's available. */ static int bzip2_reader_init(struct archive_read_filter *self) @@ -232,6 +233,8 @@ bzip2_filter_read(struct archive_read_filter *self, const void **p) /* Try to fill the output buffer. */ for (;;) { + ssize_t max_in; + if (!state->valid) { if (bzip2_reader_bid(self->bidder, self->upstream) == 0) { state->eof = 1; @@ -286,15 +289,13 @@ bzip2_filter_read(struct archive_read_filter *self, const void **p) return (ARCHIVE_FATAL); } state->stream.next_in = (char *)(uintptr_t)read_buf; + if (UINT_MAX >= SSIZE_MAX) + max_in = SSIZE_MAX; + else + max_in = UINT_MAX; + if (ret > max_in) + ret = max_in; state->stream.avail_in = (uint32_t)ret; - /* There is no more data, return whatever we have. */ - if (ret == 0) { - state->eof = 1; - *p = state->out_block; - decompressed = state->stream.next_out - - state->out_block; - return (decompressed); - } /* Decompress as much as we can in one pass. */ ret = BZ2_bzDecompress(&(state->stream)); diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_compress.c b/contrib/libarchive/libarchive/archive_read_support_filter_compress.c index d03013b361..5ca07ae6a6 100644 --- a/contrib/libarchive/libarchive/archive_read_support_filter_compress.c +++ b/contrib/libarchive/libarchive/archive_read_support_filter_compress.c @@ -104,6 +104,7 @@ struct private_data { void *out_block; /* Decompression status variables. */ + int initialized; int use_reset_code; int end_of_stream; /* EOF status. */ int maxcode; /* Largest code. */ @@ -172,13 +173,12 @@ compress_bidder_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) { const unsigned char *buffer; - ssize_t avail; int bits_checked; (void)self; /* UNUSED */ /* Shortest valid compress file is 3 bytes. */ - buffer = __archive_read_filter_ahead(filter, 3, &avail); + buffer = __archive_read_filter_ahead(filter, 3, NULL); if (buffer == NULL) return (0); @@ -212,7 +212,6 @@ compress_bidder_init(struct archive_read_filter *self) struct private_data *state; static const size_t out_block_size = 64 * 1024; void *out_block; - int code; self->code = ARCHIVE_FILTER_COMPRESS; self->name = "compress (.Z)"; @@ -233,14 +232,23 @@ compress_bidder_init(struct archive_read_filter *self) state->out_block = out_block; self->vtable = &compress_reader_vtable; - /* XXX MOVE THE FOLLOWING OUT OF INIT() XXX */ + return (ARCHIVE_OK); +} + +static int +compress_filter_init(struct archive_read_filter *self) +{ + struct private_data *state = (struct private_data *)self->data; + int code; + + state->initialized = 1; (void)getbits(self, 8); /* Skip first signature byte. */ (void)getbits(self, 8); /* Skip second signature byte. */ /* Get compression parameters. */ code = getbits(self, 8); - if ((code & 0x1f) > 16) { + if (code < 0 || (code & 0x1f) > 16) { archive_set_error(&self->archive->archive, -1, "Invalid compressed data"); return (ARCHIVE_FATAL); @@ -278,6 +286,11 @@ compress_filter_read(struct archive_read_filter *self, const void **pblock) int ret; state = (struct private_data *)self->data; + if (!state->initialized) { + ret = compress_filter_init(self); + if (ret != ARCHIVE_OK) + return (ret); + } if (state->end_of_stream) { *pblock = NULL; return (0); @@ -325,18 +338,11 @@ next_code(struct archive_read_filter *self) struct private_data *state = (struct private_data *)self->data; int code, newcode; - static int debug_buff[1024]; - static unsigned debug_index; - again: code = newcode = getbits(self, state->bits); if (code < 0) return (code); - debug_buff[debug_index++] = code; - if (debug_index >= sizeof(debug_buff)/sizeof(debug_buff[0])) - debug_index = 0; - /* If it's a reset code, reset the dictionary. */ if ((code == 256) && state->use_reset_code) { /* @@ -434,7 +440,7 @@ getbits(struct archive_read_filter *self, int n) 1, &ret); if (ret == 0) return (-1); - if (ret < 0 || state->next_in == NULL) + if (state->next_in == NULL) return (ARCHIVE_FATAL); state->consume_unnotified = state->avail_in = ret; } diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_grzip.c b/contrib/libarchive/libarchive/archive_read_support_filter_grzip.c index 8ec5d1f855..2bbb2e016e 100644 --- a/contrib/libarchive/libarchive/archive_read_support_filter_grzip.c +++ b/contrib/libarchive/libarchive/archive_read_support_filter_grzip.c @@ -80,12 +80,11 @@ grzip_bidder_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) { const unsigned char *p; - ssize_t avail; (void)self; /* UNUSED */ - p = __archive_read_filter_ahead(filter, sizeof(grzip_magic), &avail); - if (p == NULL || avail == 0) + p = __archive_read_filter_ahead(filter, sizeof(grzip_magic), NULL); + if (p == NULL) return (0); if (memcmp(p, grzip_magic, sizeof(grzip_magic))) diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_gzip.c b/contrib/libarchive/libarchive/archive_read_support_filter_gzip.c index 726385e328..a312065c63 100644 --- a/contrib/libarchive/libarchive/archive_read_support_filter_gzip.c +++ b/contrib/libarchive/libarchive/archive_read_support_filter_gzip.c @@ -56,7 +56,6 @@ struct private_data { char in_stream; unsigned char *out_block; size_t out_block_size; - int64_t total_out; unsigned long crc; uint32_t mtime; char *name; @@ -71,12 +70,7 @@ static int gzip_filter_close(struct archive_read_filter *); /* * Note that we can detect gzip archives even if we can't decompress * them. (In fact, we like detecting them because we can give better - * error messages.) So the bid framework here gets compiled even - * if zlib is unavailable. - * - * TODO: If zlib is unavailable, gzip_bidder_init() should - * use the compress_program framework to try to fire up an external - * gzip program. + * error messages.) */ static int gzip_bidder_bid(struct archive_read_filter_bidder *, struct archive_read_filter *); @@ -146,7 +140,7 @@ peek_at_header(struct archive_read_filter *filter, int *pbits, * is all fixed layout. */ len = 10; p = __archive_read_filter_ahead(filter, len, &avail); - if (p == NULL || avail == 0) + if (p == NULL) return (0); /* We only support deflation- third byte must be 0x08. */ if (memcmp(p, "\x1F\x8B\x08", 3) != 0) @@ -171,7 +165,7 @@ peek_at_header(struct archive_read_filter *filter, int *pbits, p = __archive_read_filter_ahead(filter, len + 2, &avail); if (p == NULL) return (0); - len += ((int)p[len + 1] << 8) | (int)p[len]; + len += archive_le16dec(p + len); len += 2; } @@ -284,7 +278,7 @@ gzip_read_header(struct archive_read_filter *self, struct archive_entry *entry) state = (struct private_data *)self->data; - /* A mtime of 0 is considered invalid/missing. */ + /* An mtime of 0 is considered invalid/missing. */ if (state->mtime != 0) archive_entry_set_mtime(entry, state->mtime, 0); @@ -341,7 +335,7 @@ static int consume_header(struct archive_read_filter *self) { struct private_data *state; - ssize_t avail; + ssize_t avail, max_in; size_t len; int ret; @@ -359,6 +353,18 @@ consume_header(struct archive_read_filter *self) /* Initialize compression library. */ state->stream.next_in = (unsigned char *)(uintptr_t) __archive_read_filter_ahead(self->upstream, 1, &avail); + if (avail < 0) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Failed to read gzip input"); + return (ARCHIVE_FATAL); + } + if (UINT_MAX >= SSIZE_MAX) + max_in = SSIZE_MAX; + else + max_in = UINT_MAX; + if (avail > max_in) + avail = max_in; state->stream.avail_in = (uInt)avail; ret = inflateInit2(&(state->stream), -15 /* Don't check for zlib header */); @@ -400,7 +406,6 @@ consume_trailer(struct archive_read_filter *self) { struct private_data *state; const unsigned char *p; - ssize_t avail; state = (struct private_data *)self->data; @@ -416,8 +421,8 @@ consume_trailer(struct archive_read_filter *self) } /* GZip trailer is a fixed 8 byte structure. */ - p = __archive_read_filter_ahead(self->upstream, 8, &avail); - if (p == NULL || avail == 0) + p = __archive_read_filter_ahead(self->upstream, 8, NULL); + if (p == NULL) return (ARCHIVE_FATAL); /* XXX TODO: Verify the length and CRC. */ @@ -502,7 +507,6 @@ gzip_filter_read(struct archive_read_filter *self, const void **p) /* We've read as much as we can. */ decompressed = state->stream.next_out - state->out_block; - state->total_out += decompressed; if (decompressed == 0) *p = NULL; else diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_lrzip.c b/contrib/libarchive/libarchive/archive_read_support_filter_lrzip.c index a562d538ed..9d51837753 100644 --- a/contrib/libarchive/libarchive/archive_read_support_filter_lrzip.c +++ b/contrib/libarchive/libarchive/archive_read_support_filter_lrzip.c @@ -79,15 +79,15 @@ lrzip_bidder_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) { const unsigned char *p; - ssize_t avail, len; + ssize_t len; int i; (void)self; /* UNUSED */ /* Start by looking at the first six bytes of the header, which * is all fixed layout. */ len = 6; - p = __archive_read_filter_ahead(filter, len, &avail); - if (p == NULL || avail == 0) + p = __archive_read_filter_ahead(filter, len, NULL); + if (p == NULL) return (0); if (memcmp(p, LRZIP_HEADER_MAGIC, LRZIP_HEADER_MAGIC_LEN)) diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_lz4.c b/contrib/libarchive/libarchive/archive_read_support_filter_lz4.c index acd7f51579..2e5f634b1a 100644 --- a/contrib/libarchive/libarchive/archive_read_support_filter_lz4.c +++ b/contrib/libarchive/libarchive/archive_read_support_filter_lz4.c @@ -44,6 +44,7 @@ #include "archive.h" #include "archive_endian.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_read_private.h" #include "archive_xxhash.h" @@ -95,8 +96,7 @@ static int lz4_filter_close(struct archive_read_filter *); /* * Note that we can detect lz4 archives even if we can't decompress * them. (In fact, we like detecting them because we can give better - * error messages.) So the bid framework here gets compiled even - * if liblz4 is unavailable. + * error messages.) */ static int lz4_reader_bid(struct archive_read_filter_bidder *, struct archive_read_filter *); static int lz4_reader_init(struct archive_read_filter *); @@ -145,52 +145,75 @@ lz4_reader_bid(struct archive_read_filter_bidder *self, const unsigned char *buffer; ssize_t avail; int bits_checked = 0; - ssize_t min_lz4_archive_size = 11; + const size_t min_lz4_archive_size = 11; - // LZ4 skippable frames contain a 4 byte magic number followed by - // a 4 byte frame data size, then that number of bytes of data. Regular - // frames contain a 4 byte magic number followed by a 2-14 byte frame - // header, some data, and a 3 byte end marker. - ssize_t min_lz4_frame_size = 8; + /* + * LZ4 skippable frames contain a 4 byte magic number followed by + * a 4 byte frame data size, then that number of bytes of data. + * Regular frames contain a 4 byte magic number followed by a 2-14 + * byte frame header, some data, and a 3 byte end marker. + */ + const size_t min_lz4_frame_size = 8; - ssize_t offset_in_buffer = 0; - ssize_t max_lookahead = 64 * 1024; + size_t offset_in_buffer = 0; + const size_t max_lookahead = 64 * 1024; + uint32_t magic_number; - (void)self; // UNUSED + (void)self; /* UNUSED */ - // Zstd and LZ4 skippable frame magic numbers are identical. To - // differentiate these two, we need to look for a non-skippable - // frame. + /* + * Zstd and LZ4 skippable frame magic numbers are identical. To + * differentiate these two, we need to look for a non-skippable + * frame. + */ - // Minimal lz4 archive is 11 bytes. - buffer = __archive_read_filter_ahead(filter, min_lz4_archive_size, &avail); + /* Minimal lz4 archive is 11 bytes. */ + buffer = __archive_read_filter_ahead(filter, min_lz4_archive_size, + &avail); if (buffer == NULL) return (0); - uint32_t magic_number = archive_le32dec(buffer); + magic_number = archive_le32dec(buffer); while ((magic_number & LZ4_SKIPPABLE_MASK) == LZ4_SKIPPABLE_START) { + size_t min; + uint32_t frame_data_size; - offset_in_buffer += 4; // Skip over the magic number + /* Skip over the magic number */ + offset_in_buffer += 4; - // Ensure that we can read another 4 bytes. - if (offset_in_buffer + 4 > avail) { - buffer = __archive_read_filter_ahead(filter, offset_in_buffer + 4, &avail); + /* Ensure that we can read another 4 bytes. */ + if (offset_in_buffer + 4 > (size_t)avail) { + buffer = __archive_read_filter_ahead(filter, + offset_in_buffer + 4, &avail); if (buffer == NULL) return (0); } - uint32_t frame_data_size = archive_le32dec(buffer + offset_in_buffer); + frame_data_size = archive_le32dec(buffer + offset_in_buffer); - // Skip over the 4 frame data size bytes, plus the value stored there. - offset_in_buffer += 4 + frame_data_size; + /* Skip over the 4 frame data size bytes */ + offset_in_buffer += 4; - // There should be at least one more frame if this is LZ4 data. - if (offset_in_buffer + min_lz4_frame_size > avail) { // TODO: should this be >= ? - if (offset_in_buffer + min_lz4_frame_size > max_lookahead) + /* Skip over the value stored there. */ + if (archive_ckd_add_size(&offset_in_buffer, + offset_in_buffer, frame_data_size)) + return (0); + + /* + * There should be at least one more frame + * if this is LZ4 data. + */ + if (archive_ckd_add_size(&min, + offset_in_buffer, min_lz4_frame_size)) + return (0); + /* TODO: should this be >= ? */ + if (min > (size_t)avail) { + if (min > max_lookahead) return (0); - buffer = __archive_read_filter_ahead(filter, offset_in_buffer + min_lz4_frame_size, &avail); + buffer = __archive_read_filter_ahead(filter, + min, &avail); if (buffer == NULL) return (0); } @@ -198,8 +221,10 @@ lz4_reader_bid(struct archive_read_filter_bidder *self, magic_number = archive_le32dec(buffer + offset_in_buffer); } - // We have skipped over any skippable frames. Either a regular LZ4 frame - // follows, or this isn't LZ4 data. + /* + * We have skipped over any skippable frames. Either a regular LZ4 frame + * follows, or this isn't LZ4 data. + */ bits_checked = offset_in_buffer; buffer = buffer + offset_in_buffer; @@ -241,9 +266,9 @@ lz4_reader_bid(struct archive_read_filter_bidder *self, #if !defined(HAVE_LIBLZ4) /* - * If we don't have the library on this system, we can't actually do the - * decompression. We can, however, still detect compressed archives - * and emit a useful message. + * If we don't have the library on this system, we can't do the + * decompression directly. We can, however, try to run "lz4 -d -q" + * in case that's available. */ static int lz4_reader_init(struct archive_read_filter *self) @@ -304,13 +329,15 @@ lz4_allocate_out_block(struct archive_read_filter *self) out_block_size += 64 * 1024; if (state->out_block_size < out_block_size) { free(state->out_block); + state->out_block = NULL; out_block = malloc(out_block_size); - state->out_block_size = out_block_size; if (out_block == NULL) { + state->out_block_size = 0; archive_set_error(&self->archive->archive, ENOMEM, "Can't allocate data for lz4 decompression"); return (ARCHIVE_FATAL); } + state->out_block_size = out_block_size; state->out_block = out_block; } if (!state->flags.block_independence) @@ -327,13 +354,15 @@ lz4_allocate_out_block_for_legacy(struct archive_read_filter *self) if (state->out_block_size < out_block_size) { free(state->out_block); + state->out_block = NULL; out_block = malloc(out_block_size); - state->out_block_size = out_block_size; if (out_block == NULL) { + state->out_block_size = 0; archive_set_error(&self->archive->archive, ENOMEM, "Can't allocate data for lz4 decompression"); return (ARCHIVE_FATAL); } + state->out_block_size = out_block_size; state->out_block = out_block; } return (ARCHIVE_OK); @@ -361,7 +390,7 @@ lz4_filter_read(struct archive_read_filter *self, const void **p) break; case READ_DEFAULT_STREAM: case READ_LEGACY_STREAM: - /* Reading a lz4 stream already failed. */ + /* Reading an lz4 stream already failed. */ archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, "Invalid sequence"); return (ARCHIVE_FATAL); @@ -408,9 +437,15 @@ lz4_filter_read(struct archive_read_filter *self, const void **p) "Malformed lz4 data"); return (ARCHIVE_FATAL); } - uint32_t skip_bytes = archive_le32dec(read_buf); - __archive_read_filter_consume(self->upstream, - 4 + skip_bytes); + int64_t skip_bytes = archive_le32dec(read_buf); + if (__archive_read_filter_consume(self->upstream, + 4 + skip_bytes) < 0) { + archive_set_error( + &self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Malformed lz4 data"); + return (ARCHIVE_FATAL); + } } else { /* Ignore following unrecognized data. */ state->eof = 1; @@ -512,8 +547,11 @@ lz4_filter_read_descriptor(struct archive_read_filter *self) /* Make sure we have a large enough buffer for uncompressed data. */ if (lz4_allocate_out_block(self) != ARCHIVE_OK) return (ARCHIVE_FATAL); - if (state->flags.stream_checksum) + if (state->flags.stream_checksum) { state->xxh32_state = __archive_xxhash.XXH32_init(0); + if (state->xxh32_state == NULL) + return (ARCHIVE_FATAL); + } state->decoded_size = 0; /* Success */ @@ -530,7 +568,6 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p) struct private_data *state = (struct private_data *)self->data; ssize_t compressed_size; const char *read_buf; - ssize_t bytes_remaining; int checksum_size; ssize_t uncompressed_size; size_t prefix64k; @@ -538,8 +575,7 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p) *p = NULL; /* Make sure we have 4 bytes for a block size. */ - read_buf = __archive_read_filter_ahead(self->upstream, 4, - &bytes_remaining); + read_buf = __archive_read_filter_ahead(self->upstream, 4, NULL); if (read_buf == NULL) goto truncated_error; compressed_size = archive_le32dec(read_buf); @@ -565,7 +601,7 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p) a huge buffer used for decoded data. */ read_buf = __archive_read_filter_ahead(self->upstream, - 4 + compressed_size + checksum_size, &bytes_remaining); + 4 + compressed_size + checksum_size, NULL); if (read_buf == NULL) goto truncated_error; @@ -673,7 +709,6 @@ lz4_filter_read_default_stream(struct archive_read_filter *self, const void **p) { struct private_data *state = (struct private_data *)self->data; const char *read_buf; - ssize_t bytes_remaining; ssize_t ret; if (state->stage == SELECT_STREAM) { @@ -697,7 +732,7 @@ lz4_filter_read_default_stream(struct archive_read_filter *self, const void **p) unsigned int checksum; unsigned int checksum_stream; read_buf = __archive_read_filter_ahead(self->upstream, - 4, &bytes_remaining); + 4, NULL); if (read_buf == NULL) { archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, "truncated lz4 input"); diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_lzop.c b/contrib/libarchive/libarchive/archive_read_support_filter_lzop.c index 12ed78c578..40c4575882 100644 --- a/contrib/libarchive/libarchive/archive_read_support_filter_lzop.c +++ b/contrib/libarchive/libarchive/archive_read_support_filter_lzop.c @@ -71,7 +71,6 @@ struct read_lzop { unsigned char *out_block; size_t out_block_size; - int64_t total_out; int flags; uint32_t compressed_cksum; uint32_t uncompressed_cksum; @@ -118,7 +117,6 @@ archive_read_support_filter_lzop(struct archive *_a) #if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) return (ARCHIVE_OK); #else - /* Return ARCHIVE_WARN since this always uses an external program. */ archive_set_error(_a, ARCHIVE_ERRNO_MISC, "Using external lzop program for lzop decompression"); return (ARCHIVE_WARN); @@ -133,12 +131,11 @@ lzop_bidder_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) { const unsigned char *p; - ssize_t avail; (void)self; /* UNUSED */ - p = __archive_read_filter_ahead(filter, LZOP_HEADER_MAGIC_LEN, &avail); - if (p == NULL || avail == 0) + p = __archive_read_filter_ahead(filter, LZOP_HEADER_MAGIC_LEN, NULL); + if (p == NULL) return (0); if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN)) @@ -429,12 +426,11 @@ lzop_filter_read(struct archive_read_filter *self, const void **p) } /* - * If the both uncompressed size and compressed size are the same, + * If both uncompressed size and compressed size are the same, * we do not decompress this block. */ if (state->uncompressed_size == state->compressed_size) { *p = b; - state->total_out += state->compressed_size; state->unconsumed_bytes = state->compressed_size; return ((ssize_t)state->uncompressed_size); } @@ -478,7 +474,6 @@ lzop_filter_read(struct archive_read_filter *self, const void **p) __archive_read_filter_consume(self->upstream, state->compressed_size); *p = state->out_block; - state->total_out += out_size; return ((ssize_t)out_size); } diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_rpm.c b/contrib/libarchive/libarchive/archive_read_support_filter_rpm.c index 25ace4a25b..1213df6c9b 100644 --- a/contrib/libarchive/libarchive/archive_read_support_filter_rpm.c +++ b/contrib/libarchive/libarchive/archive_read_support_filter_rpm.c @@ -38,20 +38,7 @@ #include "archive_read_private.h" struct rpm { - int64_t total_in; - uint64_t hpos; - uint64_t hlen; - unsigned char header[16]; - enum { - ST_LEAD, /* Skipping 'Lead' section. */ - ST_HEADER, /* Reading 'Header' section; - * first 16 bytes. */ - ST_HEADER_DATA, /* Skipping 'Header' section. */ - ST_PADDING, /* Skipping padding data after the - * 'Header' section. */ - ST_ARCHIVE /* Reading 'Archive' section. */ - } state; - int first_header; + int data_reached; }; #define RPM_LEAD_SIZE 96 /* Size of 'Lead' section. */ #define RPM_MIN_HEAD_SIZE 16 /* Minimum size of 'Head'. */ @@ -64,8 +51,6 @@ static ssize_t rpm_filter_read(struct archive_read_filter *, const void **); static int rpm_filter_close(struct archive_read_filter *); -static inline size_t rpm_limit_bytes(uint64_t, size_t); - #if ARCHIVE_VERSION_NUMBER < 4000000 /* Deprecated; remove in libarchive 4.0 */ int @@ -95,12 +80,11 @@ rpm_bidder_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) { const unsigned char *b; - ssize_t avail; int bits_checked; (void)self; /* UNUSED */ - b = __archive_read_filter_ahead(filter, 8, &avail); + b = __archive_read_filter_ahead(filter, 8, NULL); if (b == NULL) return (0); @@ -152,133 +136,107 @@ rpm_bidder_init(struct archive_read_filter *self) } self->data = rpm; - rpm->state = ST_LEAD; + rpm->data_reached = 0; self->vtable = &rpm_reader_vtable; return (ARCHIVE_OK); } -static inline size_t -rpm_limit_bytes(uint64_t bytes, size_t max) +static ssize_t +skip_padding(struct archive_read_filter *self) { - return (bytes > max ? max : (size_t)bytes); + const unsigned char *h; + ssize_t avail, count, r; + + do { + h = __archive_read_filter_ahead(self->upstream, 1, &avail); + if (h == NULL) + return (ARCHIVE_FATAL); + for (count = 0; count < avail && *h++ == '\0'; count++) + ; + r = __archive_read_filter_consume(self->upstream, count); + if (r < 0) + return (r); + } while (count == avail); + + return (ARCHIVE_OK); } static ssize_t -rpm_filter_read(struct archive_read_filter *self, const void **buff) +skip_prologue(struct archive_read_filter *self) { - struct rpm *rpm; - const unsigned char *b; - ssize_t avail_in, total, used; - size_t n; - uint64_t section; - uint64_t bytes; + const unsigned char *h; + ssize_t r; + int header, seen_header = 0; + + /* Skip lead size. */ + r = __archive_read_filter_consume(self->upstream, RPM_LEAD_SIZE); + if (r < 0) + return (r); - rpm = (struct rpm *)self->data; - *buff = NULL; - total = avail_in = 0; - b = NULL; - used = 0; do { - if (b == NULL) { - b = __archive_read_filter_ahead(self->upstream, 1, - &avail_in); - if (b == NULL) { - if (avail_in < 0) - return (ARCHIVE_FATAL); - else - break; - } + /* Read header intro. */ + h = __archive_read_filter_ahead(self->upstream, + RPM_MIN_HEAD_SIZE, NULL); + if (h == NULL) + return (ARCHIVE_FATAL); + + header = (memcmp(h, "\x8E\xAD\xE8\x01", 4) == 0); + if (header) { + int64_t bytes, length, section; + + seen_header = 1; + + /* Calculate header length. */ + section = archive_be32dec(h + 8); + bytes = archive_be32dec(h + 12); + length = RPM_MIN_HEAD_SIZE + section * 16 + bytes; + + /* Skip header. */ + r = __archive_read_filter_consume(self->upstream, + length); + if (r < 0) + return (r); + + /* Skip padding. */ + r = skip_padding(self); + if (r != ARCHIVE_OK) + return (r); } + } while (header); + + /* At least one header must have been encountered. */ + if (!seen_header) { + archive_set_error( + &self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unrecognized rpm header"); + return (ARCHIVE_FATAL); + } - switch (rpm->state) { - case ST_LEAD: - if (rpm->total_in + avail_in < RPM_LEAD_SIZE) - used += avail_in; - else { - n = (size_t)(RPM_LEAD_SIZE - rpm->total_in); - used += n; - b += n; - rpm->state = ST_HEADER; - rpm->hpos = 0; - rpm->hlen = 0; - rpm->first_header = 1; - } - break; - case ST_HEADER: - n = rpm_limit_bytes(RPM_MIN_HEAD_SIZE - rpm->hpos, - avail_in - used); - memcpy(rpm->header+rpm->hpos, b, n); - b += n; - used += n; - rpm->hpos += n; - - if (rpm->hpos == RPM_MIN_HEAD_SIZE) { - if (rpm->header[0] != 0x8e || - rpm->header[1] != 0xad || - rpm->header[2] != 0xe8 || - rpm->header[3] != 0x01) { - if (rpm->first_header) { - archive_set_error( - &self->archive->archive, - ARCHIVE_ERRNO_FILE_FORMAT, - "Unrecognized rpm header"); - return (ARCHIVE_FATAL); - } - rpm->state = ST_ARCHIVE; - *buff = rpm->header; - total = RPM_MIN_HEAD_SIZE; - break; - } - /* Calculate 'Header' length. */ - section = archive_be32dec(rpm->header+8); - bytes = archive_be32dec(rpm->header+12); - rpm->hlen = rpm->hpos + section * 16 + bytes; - rpm->state = ST_HEADER_DATA; - rpm->first_header = 0; - } - break; - case ST_HEADER_DATA: - n = rpm_limit_bytes(rpm->hlen - rpm->hpos, - avail_in - used); - b += n; - used += n; - rpm->hpos += n; - if (rpm->hpos == rpm->hlen) - rpm->state = ST_PADDING; - break; - case ST_PADDING: - while (used < avail_in) { - if (*b != 0) { - /* Read next header. */ - rpm->state = ST_HEADER; - rpm->hpos = 0; - rpm->hlen = 0; - break; - } - b++; - used++; - } - break; - case ST_ARCHIVE: - *buff = b; - total = avail_in; - used = avail_in; - break; - } - if (used == avail_in) { - rpm->total_in += used; - __archive_read_filter_consume(self->upstream, used); - b = NULL; - used = 0; - } - } while (total == 0 && avail_in > 0); + return (ARCHIVE_OK); +} - if (used > 0 && b != NULL) { - rpm->total_in += used; - __archive_read_filter_consume(self->upstream, used); +static ssize_t +rpm_filter_read(struct archive_read_filter *self, const void **buff) +{ + struct rpm *rpm; + ssize_t r; + + rpm = (struct rpm *)self->data; + + if (!rpm->data_reached) { + r = skip_prologue(self); + if (r != ARCHIVE_OK) + return (r); + rpm->data_reached = 1; } - return (total); + + *buff = __archive_read_filter_ahead(self->upstream, 1, &r); + if (r > 0) + __archive_read_filter_consume(self->upstream, r); + + return r; } static int diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_uu.c b/contrib/libarchive/libarchive/archive_read_support_filter_uu.c index acb8feb79b..714c7e8361 100644 --- a/contrib/libarchive/libarchive/archive_read_support_filter_uu.c +++ b/contrib/libarchive/libarchive/archive_read_support_filter_uu.c @@ -43,8 +43,6 @@ /* Maximum lookahead during bid phase */ #define UUENCODE_BID_MAX_READ 128*1024 /* in bytes */ -#define UUENCODE_MAX_LINE_LENGTH 34*1024 /* in bytes */ - struct uudecode { int64_t total; unsigned char *in_buff; @@ -224,7 +222,7 @@ bid_get_line(struct archive_read_filter *filter, len = get_line(*b, *avail, nl); /* - * Read bytes more while it does not reach the end of line. + * Read more bytes while it does not reach the end of line. */ while (*nl == 0 && len == *avail && !quit && *nbytes_read < UUENCODE_BID_MAX_READ) { @@ -423,7 +421,6 @@ ensure_in_buff_size(struct archive_read_filter *self, /* Allocate the new buffer. */ ptr = malloc(newsize); if (ptr == NULL) { - free(ptr); archive_set_error(&self->archive->archive, ENOMEM, "Can't allocate data for uudecode"); @@ -480,13 +477,15 @@ uudecode_filter_read(struct archive_read_filter *self, const void **buff) used = 0; total = 0; out = uudecode->out_buff; + if (avail_in > 2 * UUENCODE_BID_MAX_READ) + avail_in = 2 * UUENCODE_BID_MAX_READ; ravail = avail_in; if (uudecode->state == ST_IGNORE) { used = avail_in; goto finish; } if (uudecode->in_cnt) { - if (uudecode->in_cnt > UUENCODE_MAX_LINE_LENGTH) { + if (uudecode->in_cnt > UUENCODE_BID_MAX_READ) { archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid format data"); @@ -523,6 +522,12 @@ uudecode_filter_read(struct archive_read_filter *self, const void **buff) "Insufficient compressed data"); return (ARCHIVE_FATAL); } + if (len > UUENCODE_BID_MAX_READ) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid format data"); + return (ARCHIVE_FATAL); + } llen = len; if ((nl == 0) && (uudecode->state != ST_UUEND)) { if (total == 0 && ravail <= 0) { @@ -544,7 +549,7 @@ uudecode_filter_read(struct archive_read_filter *self, const void **buff) uudecode->in_cnt = len; if (total == 0) { /* Do not return 0; it means end-of-file. - * We should try to read bytes more. */ + * We should try to read more bytes. */ __archive_read_filter_consume( self->upstream, ravail); goto read_more; @@ -586,11 +591,11 @@ uudecode_filter_read(struct archive_read_filter *self, const void **buff) if (uudecode->name != NULL) free(uudecode->name); uudecode->name = malloc(namelen + 1); - if (uudecode->name == NULL) { - archive_set_error( - &self->archive->archive, - ENOMEM, - "Can't allocate data for uudecode"); + if (uudecode->name == NULL) { + archive_set_error( + &self->archive->archive, + ENOMEM, + "Can't allocate data for uudecode"); return (ARCHIVE_FATAL); } strncpy(uudecode->name, diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_xz.c b/contrib/libarchive/libarchive/archive_read_support_filter_xz.c index dcbf734eca..22cbb26cd0 100644 --- a/contrib/libarchive/libarchive/archive_read_support_filter_xz.c +++ b/contrib/libarchive/libarchive/archive_read_support_filter_xz.c @@ -54,7 +54,6 @@ struct private_data { lzma_stream stream; unsigned char *out_block; size_t out_block_size; - int64_t total_out; char eof; /* True = found end of compressed data. */ char in_stream; @@ -83,8 +82,7 @@ static int xz_lzma_bidder_init(struct archive_read_filter *); /* * Note that we can detect xz and lzma compressed files even if we * can't decompress them. (In fact, we like detecting them because we - * can give better error messages.) So the bid framework here gets - * compiled even if no lzma library is available. + * can give better error messages.) */ static int xz_bidder_bid(struct archive_read_filter_bidder *, struct archive_read_filter *); @@ -203,11 +201,10 @@ xz_bidder_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) { const unsigned char *buffer; - ssize_t avail; (void)self; /* UNUSED */ - buffer = __archive_read_filter_ahead(filter, 6, &avail); + buffer = __archive_read_filter_ahead(filter, 6, NULL); if (buffer == NULL) return (0); @@ -237,14 +234,13 @@ lzma_bidder_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) { const unsigned char *buffer; - ssize_t avail; uint32_t dicsize; uint64_t uncompressed_size; int bits_checked; (void)self; /* UNUSED */ - buffer = __archive_read_filter_ahead(filter, 14, &avail); + buffer = __archive_read_filter_ahead(filter, 14, NULL); if (buffer == NULL) return (0); @@ -343,11 +339,10 @@ static int lzip_has_member(struct archive_read_filter *filter) { const unsigned char *buffer; - ssize_t avail; int bits_checked; int log2dic; - buffer = __archive_read_filter_ahead(filter, 6, &avail); + buffer = __archive_read_filter_ahead(filter, 6, NULL); if (buffer == NULL) return (0); @@ -526,6 +521,7 @@ xz_lzma_bidder_init(struct archive_read_filter *self) free(state->out_block); free(state); self->data = NULL; + self->vtable = NULL; return (ARCHIVE_FATAL); } @@ -536,12 +532,11 @@ lzip_init(struct archive_read_filter *self) const unsigned char *h; lzma_filter filters[2]; unsigned char props[5]; - ssize_t avail_in; uint32_t dicsize; int log2dic, ret; state = (struct private_data *)self->data; - h = __archive_read_filter_ahead(self->upstream, 6, &avail_in); + h = __archive_read_filter_ahead(self->upstream, 6, NULL); if (h == NULL) return (ARCHIVE_FATAL); @@ -706,7 +701,6 @@ xz_filter_read(struct archive_read_filter *self, const void **p) } decompressed = state->stream.next_out - state->out_block; - state->total_out += decompressed; state->member_out += decompressed; if (decompressed == 0) { if (member_in != state->member_in && diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_zstd.c b/contrib/libarchive/libarchive/archive_read_support_filter_zstd.c index da7c540dbc..100c2c10dd 100644 --- a/contrib/libarchive/libarchive/archive_read_support_filter_zstd.c +++ b/contrib/libarchive/libarchive/archive_read_support_filter_zstd.c @@ -48,6 +48,7 @@ #include "archive.h" #include "archive_endian.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_read_private.h" @@ -57,7 +58,6 @@ struct private_data { ZSTD_DStream *dstream; unsigned char *out_block; size_t out_block_size; - int64_t total_out; char in_frame; /* True = in the middle of a zstd frame. */ char eof; /* True = found end of compressed data. */ }; @@ -70,8 +70,7 @@ static int zstd_filter_close(struct archive_read_filter *); /* * Note that we can detect zstd compressed files even if we can't decompress * them. (In fact, we like detecting them because we can give better error - * messages.) So the bid framework here gets compiled even if no zstd library - * is available. + * messages.) */ static int zstd_bidder_bid(struct archive_read_filter_bidder *, struct archive_read_filter *); @@ -110,55 +109,77 @@ zstd_bidder_bid(struct archive_read_filter_bidder *self, { const unsigned char *buffer; ssize_t avail; - - // Zstandard skippable frames contain a 4 byte magic number followed by - // a 4 byte frame data size, then that number of bytes of data. Regular - // frames contain a 4 byte magic number followed by a 2-14 byte frame - // header, some data, and a 3 byte end marker. - ssize_t min_zstd_frame_size = 8; - - ssize_t offset_in_buffer = 0; - ssize_t max_lookahead = 64 * 1024; - - // Zstd regular frame magic number. - uint32_t zstd_magic = 0xFD2FB528U; - - // Note: Zstd and LZ4 skippable frame magic numbers are identical. - // To differentiate these two, we need to look for a non-skippable - // frame. - uint32_t zstd_magic_skippable_start = 0x184D2A50; - uint32_t zstd_magic_skippable_mask = 0xFFFFFFF0; - - (void) self; // UNUSED - - buffer = __archive_read_filter_ahead(filter, min_zstd_frame_size, &avail); + /* + * Zstandard skippable frames contain a 4 byte magic number followed + * by a 4 byte frame data size, then that number of bytes of data. + * Regular frames contain a 4 byte magic number followed by a 2-14 + * byte frame header, some data, and a 3 byte end marker. + */ + const size_t min_zstd_frame_size = 8; + + size_t offset_in_buffer = 0; + const size_t max_lookahead = 64 * 1024; + uint32_t magic_number; + + /* Zstd regular frame magic number. */ + const uint32_t zstd_magic = 0xFD2FB528U; + + /* + * Note: Zstd and LZ4 skippable frame magic numbers are identical. + * To differentiate these two, we need to look for a non-skippable + * frame. + */ + const uint32_t zstd_magic_skippable_start = 0x184D2A50; + const uint32_t zstd_magic_skippable_mask = 0xFFFFFFF0; + + (void) self; /* UNUSED */ + + buffer = __archive_read_filter_ahead(filter, min_zstd_frame_size, + &avail); if (buffer == NULL) return (0); - uint32_t magic_number = archive_le32dec(buffer); + magic_number = archive_le32dec(buffer); - while ((magic_number & zstd_magic_skippable_mask) == zstd_magic_skippable_start) { + while ((magic_number & zstd_magic_skippable_mask) == + zstd_magic_skippable_start) { + size_t min; + uint32_t frame_data_size; - offset_in_buffer += 4; // Skip over the magic number + /* Skip over the magic number */ + offset_in_buffer += 4; - // Ensure that we can read another 4 bytes. - if (offset_in_buffer + 4 > avail) { - buffer = __archive_read_filter_ahead(filter, offset_in_buffer + 4, &avail); + /* Ensure that we can read another 4 bytes. */ + if (offset_in_buffer + 4 > (size_t)avail) { + buffer = __archive_read_filter_ahead(filter, + offset_in_buffer + 4, &avail); if (buffer == NULL) return (0); } - uint32_t frame_data_size = archive_le32dec(buffer + offset_in_buffer); - - // Skip over the 4 frame data size bytes, plus the value stored there. - offset_in_buffer += 4 + frame_data_size; - - // There should be at least one more frame if this is zstd data. - if (offset_in_buffer + min_zstd_frame_size > avail) { - if (offset_in_buffer + min_zstd_frame_size > max_lookahead) + frame_data_size = archive_le32dec(buffer + offset_in_buffer); + + /* Skip over the 4 frame data size bytes */ + offset_in_buffer += 4; + + /* Skip over the value stored there. */ + if (archive_ckd_add_size(&offset_in_buffer, + offset_in_buffer, frame_data_size)) + return (0); + + /* + * There should be at least one more frame + * if this is zstd data. + */ + if (archive_ckd_add_size(&min, + offset_in_buffer, min_zstd_frame_size)) + return (0); + if (min > (size_t)avail) { + if (min > max_lookahead) return (0); - buffer = __archive_read_filter_ahead(filter, offset_in_buffer + min_zstd_frame_size, &avail); + buffer = __archive_read_filter_ahead(filter, + min, &avail); if (buffer == NULL) return (0); } @@ -166,8 +187,10 @@ zstd_bidder_bid(struct archive_read_filter_bidder *self, magic_number = archive_le32dec(buffer + offset_in_buffer); } - // We have skipped over any skippable frames. Either a regular zstd frame - // follows, or this isn't zstd data. + /* + * We have skipped over any skippable frames. Either a regular zstd + * frame follows, or this isn't zstd data. + */ if (magic_number == zstd_magic) return (offset_in_buffer + 4); @@ -179,7 +202,7 @@ zstd_bidder_bid(struct archive_read_filter_bidder *self, /* * If we don't have the library on this system, we can't do the - * decompression directly. We can, however, try to run "zstd -d" + * decompression directly. We can, however, try to run "zstd -d -qq" * in case that's available. */ static int @@ -310,7 +333,6 @@ zstd_filter_read(struct archive_read_filter *self, const void **p) } decompressed = out.pos; - state->total_out += decompressed; if (decompressed == 0) *p = NULL; else diff --git a/contrib/libarchive/libarchive/archive_read_support_format_7zip.c b/contrib/libarchive/libarchive/archive_read_support_format_7zip.c index 8926ac50a1..9f49ac3092 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_7zip.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_7zip.c @@ -67,6 +67,7 @@ #define SFX_MIN_ADDR 0x27000 #define SFX_MAX_ADDR 0x60000 #define SFX_MAX_OFFSET (SFX_MAX_ADDR - SFX_MIN_ADDR) +#define SFX_MAX_SEEK 0x800000 /* * PE format @@ -174,7 +175,7 @@ struct _7z_digests { struct _7z_folder { uint64_t numCoders; struct _7z_coder { - unsigned long codec; + uint64_t codec; uint64_t numInStreams; uint64_t numOutStreams; uint64_t propertiesSize; @@ -334,7 +335,7 @@ struct _7zip { int stream_valid; #endif /* Decoding Zstandard data. */ -#if HAVE_ZSTD_H +#if HAVE_ZSTD_H && HAVE_LIBZSTD ZSTD_DStream *zstd_dstream; int zstdstream_valid; #endif @@ -345,12 +346,10 @@ struct _7zip { IByteIn bytein; struct { const unsigned char *next_in; - int64_t avail_in; - int64_t total_in; - int64_t stream_in; + size_t avail_in; + size_t stream_in; unsigned char *next_out; - int64_t avail_out; - int64_t total_out; + size_t avail_out; int overconsumed; } ppstream; int ppmd7_valid; @@ -398,6 +397,27 @@ struct _7zip { * the files. */ #define UMAX_ENTRY ARCHIVE_LITERAL_ULL(100000000) +/* + * Files without unpack streams must be described by the EmptyStream bitmap, + * which consumes one bit for every file entry in FilesInfo. + */ +static int +files_info_numfiles_is_sane(const struct _7zip *zip) +{ + uint64_t empty_stream_map_bytes; + + if (zip->numFiles > UMAX_ENTRY) + return (0); + if (zip->numFiles > SIZE_MAX / sizeof(*zip->entries)) + return (0); + + if (zip->numFiles <= zip->si.ss.unpack_streams) + return (1); + + empty_stream_map_bytes = (zip->numFiles + 7) / 8; + return (empty_stream_map_bytes <= zip->header_bytes_remaining); +} + static int archive_read_format_7zip_has_encrypted_entries(struct archive_read *); static int archive_read_support_format_7zip_capabilities(struct archive_read *a); static int archive_read_format_7zip_bid(struct archive_read *, int); @@ -407,8 +427,8 @@ static int archive_read_format_7zip_read_data(struct archive_read *, static int archive_read_format_7zip_read_data_skip(struct archive_read *); static int archive_read_format_7zip_read_header(struct archive_read *, struct archive_entry *); -static int check_7zip_header_in_sfx(const char *); -static unsigned long decode_codec_id(const unsigned char *, size_t); +static int check_7zip_header_in_sfx(const unsigned char *); +static int decode_codec_id(const unsigned char *, size_t, uint64_t *); static int decode_encoded_header_info(struct archive_read *, struct _7z_stream_info *); static int decompress(struct archive_read *, struct _7zip *, @@ -449,9 +469,9 @@ static ssize_t read_stream(struct archive_read *, const void **, size_t, size_t); static int seek_pack(struct archive_read *); static int64_t skip_stream(struct archive_read *, size_t); -static int skip_sfx(struct archive_read *, const ssize_t); -static ssize_t find_pe_overlay(struct archive_read *); -static ssize_t find_elf_data_sec(struct archive_read *); +static int get_data_offset(struct archive_read *, int64_t *, int); +static int get_pe_sfx_offset(struct archive_read *, int64_t *); +static int get_elf_sfx_offset(struct archive_read *, int64_t *, int); static int slurp_central_directory(struct archive_read *, struct _7zip *, struct _7z_header_info *); static int setup_decode_folder(struct archive_read *, struct _7z_folder *, @@ -464,6 +484,7 @@ static size_t arm64_Convert(struct _7zip *, uint8_t *, size_t); static ssize_t Bcj2_Decode(struct _7zip *, uint8_t *, size_t); static size_t sparc_Convert(struct _7zip *, uint8_t *, size_t); static size_t powerpc_Convert(struct _7zip *, uint8_t *, size_t); +static int64_t seek_compat(struct archive_read *, int64_t, int, int); int @@ -530,64 +551,92 @@ archive_read_format_7zip_has_encrypted_entries(struct archive_read *_a) } static int -archive_read_format_7zip_bid(struct archive_read *a, int best_bid) +get_data_offset(struct archive_read *a, int64_t *data_offset, int compat) { - const char *p; - - /* If someone has already bid more than 32, then avoid - trashing the look-ahead buffers with a seek. */ - if (best_bid > 32) - return (-1); + const unsigned char *p; + int64_t offset, sfx_offset; + int r, window; - if ((p = __archive_read_ahead(a, 6, NULL)) == NULL) - return (0); + if ((p = __archive_read_ahead(a, 6, NULL)) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file body"); + return (ARCHIVE_FATAL); + } /* If first six bytes are the 7-Zip signature, - * return the bid right now. */ - if (memcmp(p, _7ZIP_SIGNATURE, 6) == 0) - return (48); + * return the offset right now. */ + if (memcmp(p, _7ZIP_SIGNATURE, 6) == 0) { + *data_offset = 0; + return (ARCHIVE_OK); + } /* - * It may a 7-Zip SFX archive file. If first two bytes are - * 'M' and 'Z' available on Windows or first four bytes are - * "\x7F\x45LF" available on posix like system, seek the 7-Zip - * signature. While find_pe_overlay can be performed without - * performing a seek, find_elf_data_sec requires one, + * It may be a 7-Zip SFX archive file. If first two bytes are + * 'M' and 'Z' (PE, Windows) or first four bytes are + * "\x7F\x45LF" (ELF, Posix-like systems), seek the 7-Zip + * signature. While get_pe_sfx_offset can be performed without + * performing a seek, get_elf_sfx_offset requires one, * thus a performance difference between the two is expected. */ - if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) { - const ssize_t min_addr = p[0] == 'M' ? find_pe_overlay(a) : - find_elf_data_sec(a); - ssize_t offset = min_addr; - ssize_t window = 4096; + if ((p[0] == 'M' && p[1] == 'Z')) + r = get_pe_sfx_offset(a, &sfx_offset); + else if (memcmp(p, "\x7F\x45LF", 4) == 0) + r = get_elf_sfx_offset(a, &sfx_offset, compat); + else + r = ARCHIVE_FATAL; + if (r < ARCHIVE_WARN || sfx_offset > SFX_MAX_SEEK) + goto fail; + + offset = sfx_offset; + window = 4096; + while (offset + window <= (sfx_offset + SFX_MAX_OFFSET)) { ssize_t bytes_avail; - while (offset + window <= (min_addr + SFX_MAX_OFFSET)) { - const char *buff = __archive_read_ahead(a, - offset + window, &bytes_avail); - if (buff == NULL) { - /* Remaining bytes are less than window. */ - window >>= 1; - if (window < 0x40) - return (0); - continue; - } - p = buff + offset; - while (p + 32 < buff + bytes_avail) { - int step = check_7zip_header_in_sfx(p); - if (step == 0) - return (48); - p += step; + const unsigned char *buff = __archive_read_ahead(a, + offset + window, &bytes_avail); + if (buff == NULL) { + /* Remaining bytes are less than window. */ + window >>= 1; + if (window < 0x40) + goto fail; + continue; + } + p = buff + offset; + while (p + 32 < buff + bytes_avail) { + int step = check_7zip_header_in_sfx(p); + if (step == 0) { + *data_offset = p - buff; + return (ARCHIVE_OK); } - offset = p - buff; + p += step; } + offset = p - buff; } - return (0); +fail: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Couldn't find out 7-Zip header"); + return (ARCHIVE_FATAL); +} + +static int +archive_read_format_7zip_bid(struct archive_read *a, int best_bid) +{ + int64_t data_offset; + + /* If someone has already bid more than 32, then avoid + trashing the look-ahead buffers with a seek. */ + if (best_bid > 32) + return (-1); + + if (get_data_offset(a, &data_offset, 0) < 0) + return (0); + + return (48); } static int -check_7zip_header_in_sfx(const char *p) +check_7zip_header_in_sfx(const unsigned char *p) { - switch ((unsigned char)p[5]) { + switch (p[5]) { case 0x1C: if (memcmp(p, _7ZIP_SIGNATURE, 6) != 0) return (6); @@ -596,8 +645,7 @@ check_7zip_header_in_sfx(const char *p) * Magic Code, so we should do this in order not to * make a mis-detection. */ - if (crc32(0, (const unsigned char *)p + 12, 20) - != archive_le32dec(p + 8)) + if (crc32(0, p + 12, 20) != archive_le32dec(p + 8)) return (6); /* Hit the header! */ return (0); @@ -611,79 +659,33 @@ check_7zip_header_in_sfx(const char *p) } static int -skip_sfx(struct archive_read *a, const ssize_t min_addr) -{ - const void *h; - const char *p, *q; - size_t skip, offset; - ssize_t bytes, window; - - if (__archive_read_seek(a, min_addr, SEEK_SET) < 0) - return (ARCHIVE_FATAL); - - offset = 0; - window = 1; - while (offset + window <= SFX_MAX_ADDR - SFX_MIN_ADDR) { - h = __archive_read_ahead(a, window, &bytes); - if (h == NULL) { - /* Remaining bytes are less than window. */ - window >>= 1; - if (window < 0x40) - goto fatal; - continue; - } - if (bytes < 6) { - /* This case might happen when window == 1. */ - window = 4096; - continue; - } - p = (const char *)h; - q = p + bytes; - - /* - * Scan ahead until we find something that looks - * like the 7-Zip header. - */ - while (p + 32 < q) { - int step = check_7zip_header_in_sfx(p); - if (step == 0) { - struct _7zip *zip = - (struct _7zip *)a->format->data; - skip = p - (const char *)h; - __archive_read_consume(a, skip); - zip->seek_base = min_addr + offset + skip; - return (ARCHIVE_OK); - } - p += step; - } - skip = p - (const char *)h; - __archive_read_consume(a, skip); - offset += skip; - if (window == 1) - window = 4096; - } -fatal: - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Couldn't find out 7-Zip header"); - return (ARCHIVE_FATAL); -} - -static ssize_t -find_pe_overlay(struct archive_read *a) +get_pe_sfx_offset(struct archive_read *a, int64_t *sfx_offset) { const char *h; - ssize_t bytes, max_offset, offset, sec_end; - ssize_t opt_hdr_sz, sec_cnt; + int64_t max_offset, offset; + ssize_t bytes; + uint16_t opt_hdr_sz, sec_cnt; + + /* + * If encounter any weirdness, revert to old brute-force style search + */ + *sfx_offset = SFX_MIN_ADDR; for (;;) { /* * Read Dos header to find e_lfanew */ h = __archive_read_ahead(a, PE_DOS_HDR_LEN, &bytes); - if (h == NULL || h[0] != 'M' || h[1] != 'Z') { + if (h == NULL) { + return (ARCHIVE_FATAL); + } + if (h[0] != 'M' || h[1] != 'Z') { break; } offset = archive_le32dec(h + PE_DOS_HDR_ELFANEW_OFFSET); + if (offset > SFX_MAX_SEEK) { + return (ARCHIVE_FATAL); + } /* * Read COFF header to find opt header size and sec cnt @@ -691,8 +693,10 @@ find_pe_overlay(struct archive_read *a) if (bytes < offset + PE_COFF_HDR_LEN) { h = __archive_read_ahead(a, offset + PE_COFF_HDR_LEN, &bytes); - if (h == NULL || h[offset] != 'P' || - h[offset + 1] != 'E') { + if (h == NULL) { + return (ARCHIVE_FATAL); + } + if (h[offset] != 'P' || h[offset + 1] != 'E') { break; } } @@ -710,6 +714,10 @@ find_pe_overlay(struct archive_read *a) break; } + if (offset + sec_cnt * PE_SEC_HDR_LEN > SFX_MAX_SEEK) { + return (ARCHIVE_FATAL); + } + /* * Traverse sec table to find max raw offset (i.e., overlay) */ @@ -717,12 +725,14 @@ find_pe_overlay(struct archive_read *a) h = __archive_read_ahead(a, offset + sec_cnt * PE_SEC_HDR_LEN, NULL); if (h == NULL) { - break; + return (ARCHIVE_FATAL); } } max_offset = offset; while (sec_cnt > 0) { - sec_end = archive_le32dec( + int64_t sec_end; + + sec_end = (int64_t)archive_le32dec( h + offset + PE_SEC_HDR_RAW_SZ_OFFSET) + archive_le32dec( h + offset + PE_SEC_HDR_RAW_ADDR_OFFSET); @@ -732,34 +742,40 @@ find_pe_overlay(struct archive_read *a) offset += PE_SEC_HDR_LEN; sec_cnt--; } - return (max_offset); + *sfx_offset = max_offset; + break; } - /* - * If encounter any weirdness, revert to old brute-force style search - */ - return (SFX_MIN_ADDR); + return (ARCHIVE_OK); } -static ssize_t -find_elf_data_sec(struct archive_read *a) +static int +get_elf_sfx_offset(struct archive_read *a, int64_t *sfx_offset, int compat) { + int64_t r; const char *h; char big_endian, format_64; - ssize_t bytes, min_addr = SFX_MIN_ADDR; - ssize_t request; + size_t request; uint64_t e_shoff, strtab_offset, strtab_size; uint16_t e_shentsize, e_shnum, e_shstrndx; uint16_t (*dec16)(const void *); uint32_t (*dec32)(const void *); uint64_t (*dec64)(const void *); + /* + * If encounter any weirdness, revert to old brute-force style search + */ + *sfx_offset = SFX_MIN_ADDR; + for (;;) { /* * Read Elf header to find bitness & endianness */ - h = __archive_read_ahead(a, ELF_HDR_MIN_LEN, &bytes); - if (h == NULL || memcmp(h, "\x7F\x45LF", 4) != 0) { + h = __archive_read_ahead(a, ELF_HDR_MIN_LEN, NULL); + if (h == NULL) { + return (ARCHIVE_FATAL); + } + if (memcmp(h, "\x7F\x45LF", 4) != 0) { break; } format_64 = h[ELF_HDR_EI_CLASS_OFFSET] == 0x2; @@ -794,20 +810,28 @@ find_elf_data_sec(struct archive_read *a) break; } + if ((int64_t)e_shoff < 0) { + return (ARCHIVE_FATAL); + } + /* * Reading the section table to find strtab section */ - if (__archive_read_seek(a, e_shoff, SEEK_SET) < 0) { - break; + if (seek_compat(a, e_shoff, SEEK_SET, compat) < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Seek error"); + return (ARCHIVE_FATAL); } if (format_64) { - request = (size_t)e_shnum * (size_t)e_shentsize + 0x28; + request = (size_t)e_shnum * e_shentsize + 0x28; } else { - request = (size_t)e_shnum * (size_t)e_shentsize + 0x18; + request = (size_t)e_shnum * e_shentsize + 0x18; } - h = __archive_read_ahead(a, request, &bytes); + if (request > SFX_MAX_SEEK) { + return (ARCHIVE_FATAL); + } + h = __archive_read_ahead(a, request, NULL); if (h == NULL) { - break; + return (ARCHIVE_FATAL); } if (format_64) { strtab_offset = (*dec64)( @@ -820,45 +844,50 @@ find_elf_data_sec(struct archive_read *a) strtab_size = (*dec32)( h + e_shstrndx * e_shentsize + 0x14); } - if (strtab_size < 6 || strtab_size > SIZE_MAX) - break; + if ((int64_t)strtab_offset < 0 || strtab_size < 6 || + strtab_size > SFX_MAX_SEEK) + return (ARCHIVE_FATAL); /* * Read the STRTAB section to find the .data offset */ - if (__archive_read_seek(a, strtab_offset, SEEK_SET) < 0) { - break; + if (seek_compat(a, strtab_offset, SEEK_SET, compat) < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Seek error"); + return (ARCHIVE_FATAL); } h = __archive_read_ahead(a, strtab_size, NULL); if (h == NULL) { - break; + return (ARCHIVE_FATAL); } - ssize_t data_sym_offset = -1; + size_t data_sym_offset = strtab_size; for (size_t offset = 0; offset < strtab_size - 6; offset++) { if (memcmp(h + offset, ".data\00", 6) == 0) { data_sym_offset = offset; break; } } - if (data_sym_offset == -1) { + if (data_sym_offset == strtab_size) { break; } /* * Find the section with the .data name */ - if (__archive_read_seek(a, e_shoff, SEEK_SET) < 0) { - break; + if (seek_compat(a, e_shoff, SEEK_SET, compat) < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Seek error"); + return (ARCHIVE_FATAL); } - h = __archive_read_ahead(a, (size_t)e_shnum * (size_t)e_shentsize, NULL); + h = __archive_read_ahead(a, (size_t)e_shnum * e_shentsize, NULL); if (h == NULL) { - break; + return (ARCHIVE_FATAL); } - ssize_t sec_tbl_offset = 0, name_offset; + size_t sec_tbl_offset = 0; while (e_shnum > 0) { + uint32_t name_offset; + name_offset = (*dec32)(h + sec_tbl_offset); if (name_offset == data_sym_offset) { - uint64_t sel_offset; + int64_t sel_offset; if (format_64) { sel_offset = (*dec64)( @@ -867,9 +896,8 @@ find_elf_data_sec(struct archive_read *a) sel_offset = (*dec32)( h + sec_tbl_offset + 0x10); } - if (sel_offset > SSIZE_MAX) - break; - min_addr = (ssize_t)sel_offset; + if (sel_offset >= 0) + *sfx_offset = sel_offset; break; } sec_tbl_offset += e_shentsize; @@ -878,8 +906,10 @@ find_elf_data_sec(struct archive_read *a) break; } - __archive_read_seek(a, 0, SEEK_SET); - return (min_addr); + r = seek_compat(a, 0, SEEK_SET, compat); + if (r < 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Seek error"); + return (int)r; } static int @@ -1004,29 +1034,19 @@ archive_read_format_7zip_read_header(struct archive_read *a, const int supported_attrs = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM; if (zip_entry->attr & supported_attrs) { - char *fflags_text, *ptr; - /* allocate for ",rdonly,hidden,system" */ - fflags_text = malloc(22 * sizeof(*fflags_text)); - if (fflags_text != NULL) { - ptr = fflags_text; - if (zip_entry->attr & FILE_ATTRIBUTE_READONLY) { - strcpy(ptr, ",rdonly"); - ptr = ptr + 7; - } - if (zip_entry->attr & FILE_ATTRIBUTE_HIDDEN) { - strcpy(ptr, ",hidden"); - ptr = ptr + 7; - } - if (zip_entry->attr & FILE_ATTRIBUTE_SYSTEM) { - strcpy(ptr, ",system"); - ptr = ptr + 7; - } - if (ptr > fflags_text) { - archive_entry_copy_fflags_text(entry, - fflags_text + 1); - } - free(fflags_text); - } + char buf[sizeof(",rdonly,hidden,system")]; + const char *fflags[3] = { "", "", "" }; + const char **flag = fflags; + + if (zip_entry->attr & FILE_ATTRIBUTE_READONLY) + *flag++ = ",rdonly"; + if (zip_entry->attr & FILE_ATTRIBUTE_HIDDEN) + *flag++ = ",hidden"; + if (zip_entry->attr & FILE_ATTRIBUTE_SYSTEM) + *flag++ = ",system"; + + snprintf(buf, sizeof(buf), "%s%s%s", fflags[0], fflags[1], fflags[2]); + archive_entry_copy_fflags_text(entry, buf + 1); } /* If there's no body, force read_data() to return EOF immediately. */ @@ -1037,6 +1057,13 @@ archive_read_format_7zip_read_header(struct archive_read *a, unsigned char *symname = NULL; size_t symsize = 0; + if (zip->entry_bytes_remaining > 1024 * 1024) { + archive_set_error(&a->archive, ENOMEM, + "Rejecting malformed 7zip archive: " + "symlink contents exceed 1 megabyte"); + return (ARCHIVE_FATAL); + } + /* * Symbolic-name is recorded as its contents. We have to * read the contents at this time. @@ -1189,7 +1216,7 @@ archive_read_format_7zip_read_data_skip(struct archive_read *a) */ bytes_skipped = skip_stream(a, (size_t)zip->entry_bytes_remaining); if (bytes_skipped < 0) - return (ARCHIVE_FATAL); + return ((int)bytes_skipped); zip->entry_bytes_remaining = 0; /* This entry is finished and done. */ @@ -1281,17 +1308,20 @@ set_error(struct archive_read *a, int ret) #endif -static unsigned long -decode_codec_id(const unsigned char *codecId, size_t id_size) +static int +decode_codec_id(const unsigned char *codecId, size_t id_size, uint64_t *id) { unsigned i; - unsigned long id = 0; + uint64_t v = 0; for (i = 0; i < id_size; i++) { - id <<= 8; - id += codecId[i]; + if (v > (uint64_t)INT64_MAX / 256) + return (-1); + v <<= 8; + v += codecId[i]; } - return (id); + *id = v; + return (0); } static Byte @@ -1301,29 +1331,26 @@ ppmd_read(void *p) struct _7zip *zip = (struct _7zip *)(a->format->data); Byte b; - if (zip->ppstream.avail_in <= 0) { + if (zip->ppstream.avail_in == 0) { /* * Ppmd7_DecodeSymbol might require reading multiple bytes * and we are on boundary; * last resort to read using __archive_read_ahead. */ - ssize_t bytes_avail = 0; const uint8_t* data = __archive_read_ahead(a, - (size_t)zip->ppstream.stream_in+1, &bytes_avail); - if(data == NULL || bytes_avail < zip->ppstream.stream_in+1) { + zip->ppstream.stream_in + 1, NULL); + if (data == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated 7z file data"); zip->ppstream.overconsumed = 1; return (0); } - zip->ppstream.next_in++; b = data[zip->ppstream.stream_in]; } else { b = *zip->ppstream.next_in++; + zip->ppstream.avail_in--; } - zip->ppstream.avail_in--; - zip->ppstream.total_in++; zip->ppstream.stream_in++; return (b); } @@ -1352,8 +1379,9 @@ init_decompression(struct archive_read *a, struct _7zip *zip, coder2->codec != _7Z_SPARC) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Unsupported filter %lx for %lx", - coder2->codec, coder1->codec); + "Unsupported filter %jx for %jx", + (uintmax_t)coder2->codec, + (uintmax_t)coder1->codec); return (ARCHIVE_FAILED); } zip->codec2 = coder2->codec; @@ -1558,7 +1586,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip, #endif case _7Z_ZSTD: { -#if defined(HAVE_ZSTD_H) +#if HAVE_ZSTD_H && HAVE_LIBZSTD if (zip->zstdstream_valid) { ZSTD_freeDStream(zip->zstd_dstream); zip->zstdstream_valid = 0; @@ -1632,8 +1660,6 @@ init_decompression(struct archive_read *a, struct _7zip *zip, zip->ppmd7_valid = 1; zip->ppmd7_stat = 0; zip->ppstream.overconsumed = 0; - zip->ppstream.total_in = 0; - zip->ppstream.total_out = 0; break; } case _7Z_X86: @@ -1840,7 +1866,7 @@ decompress(struct archive_read *a, struct _7zip *zip, t_avail_out = zip->stream.avail_out; break; #endif -#ifdef HAVE_ZSTD_H +#if HAVE_ZSTD_H && HAVE_LIBZSTD case _7Z_ZSTD: { ZSTD_inBuffer input = { t_next_in, t_avail_in, 0 }; // src, size, pos @@ -1916,14 +1942,13 @@ decompress(struct archive_read *a, struct _7zip *zip, } *zip->ppstream.next_out++ = (unsigned char)sym; zip->ppstream.avail_out--; - zip->ppstream.total_out++; if (flush_bytes) flush_bytes--; } while (zip->ppstream.avail_out && (zip->ppstream.avail_in || flush_bytes)); - t_avail_in = (size_t)zip->ppstream.avail_in; - t_avail_out = (size_t)zip->ppstream.avail_out; + t_avail_in = zip->ppstream.avail_in; + t_avail_out = zip->ppstream.avail_out; break; } default: @@ -2027,7 +2052,7 @@ free_decompression(struct archive_read *a, struct _7zip *zip) zip->stream_valid = 0; } #endif -#ifdef HAVE_ZSTD_H +#if HAVE_ZSTD_H && HAVE_LIBZSTD if (zip->zstdstream_valid) ZSTD_freeDStream(zip->zstd_dstream); #endif @@ -2279,7 +2304,8 @@ read_Folder(struct archive_read *a, struct _7z_folder *f) if ((p = header_bytes(a, codec_size)) == NULL) return (-1); - f->coders[i].codec = decode_codec_id(p, codec_size); + if (decode_codec_id(p, codec_size, &f->coders[i].codec) < 0) + return (-1); if (simple) { f->coders[i].numInStreams = 1; @@ -2543,9 +2569,8 @@ read_SubStreamsInfo(struct archive_read *a, struct _7z_substream_info *ss, for (i = 0; i < numFolders; i++) { if (parse_7zip_uint64(a, &(f[i].numUnpackStreams)) < 0) return (-1); - if (UMAX_ENTRY < f[i].numUnpackStreams) - return (-1); - if (unpack_streams > SIZE_MAX - UMAX_ENTRY) { + if (f[i].numUnpackStreams > + UMAX_ENTRY - unpack_streams) { return (-1); } unpack_streams += (size_t)f[i].numUnpackStreams; @@ -2556,6 +2581,13 @@ read_SubStreamsInfo(struct archive_read *a, struct _7z_substream_info *ss, } else unpack_streams = numFolders; + if (type != kSize) { + for (i = 0; i < numFolders; i++) { + if (f[i].numUnpackStreams > 1) + return (-1); + } + } + ss->unpack_streams = unpack_streams; if (unpack_streams) { ss->unpackSizes = calloc(unpack_streams, @@ -2599,11 +2631,6 @@ read_SubStreamsInfo(struct archive_read *a, struct _7z_substream_info *ss, type = *p; } - for (i = 0; i < unpack_streams; i++) { - ss->digestsDefined[i] = 0; - ss->digests[i] = 0; - } - numDigests = 0; for (i = 0; i < numFolders; i++) { if (f[i].numUnpackStreams != 1 || !f[i].digest_defined) @@ -2806,7 +2833,7 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, if (parse_7zip_uint64(a, &(zip->numFiles)) < 0) return (-1); - if (UMAX_ENTRY < zip->numFiles) + if (!files_info_numfiles_is_sane(zip)) return (-1); zip->entries = calloc((size_t)zip->numFiles, sizeof(*zip->entries)); @@ -2828,7 +2855,7 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, if (parse_7zip_uint64(a, &size) < 0) return (-1); - if (zip->header_bytes_remaining < size) + if (zip->header_bytes_remaining < size || size > SIZE_MAX / 4) return (-1); ll = (size_t)size; @@ -3235,22 +3262,22 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip, uint64_t next_header_size; uint32_t next_header_crc; ssize_t bytes_avail; + int64_t data_offset; int check_header_crc, r; - if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL) + if (get_data_offset(a, &data_offset, 1) < 0) + return (ARCHIVE_FATAL); + if (__archive_read_consume(a, data_offset) < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Seek error"); return (ARCHIVE_FATAL); - - if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) { - /* This is an executable ? Must be self-extracting... */ - const ssize_t min_addr = p[0] == 'M' ? find_pe_overlay(a) : - find_elf_data_sec(a); - r = skip_sfx(a, min_addr); - if (r < ARCHIVE_WARN) - return (r); - if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL) - return (ARCHIVE_FATAL); } - zip->seek_base += 32; + if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file header"); + return (ARCHIVE_FATAL); + } + + zip->seek_base = (uint64_t)data_offset + 32; if (memcmp(p, _7ZIP_SIGNATURE, 6) != 0) { archive_set_error(&a->archive, -1, "Not 7-Zip archive file"); @@ -3258,7 +3285,7 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip, } /* CRC check. */ - if (crc32(0, (const unsigned char *)p + 12, 20) + if (crc32(0, p + 12, 20) != archive_le32dec(p + 8)) { #ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&a->archive, -1, "Header CRC error"); @@ -3282,9 +3309,11 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip, if (next_header_offset != 0) { if (bytes_avail >= (ssize_t)next_header_offset) __archive_read_consume(a, next_header_offset); - else if (__archive_read_seek(a, - next_header_offset + zip->seek_base, SEEK_SET) < 0) + else if (seek_compat(a, + next_header_offset + zip->seek_base, SEEK_SET, 1) < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Seek error"); return (ARCHIVE_FATAL); + } } zip->stream_offset = next_header_offset; zip->header_offset = next_header_offset; @@ -3620,9 +3649,11 @@ seek_pack(struct archive_read *a) zip->si.pi.sizes[zip->pack_stream_index]; pack_offset = zip->si.pi.positions[zip->pack_stream_index]; if (zip->stream_offset != pack_offset) { - if (0 > __archive_read_seek(a, pack_offset + zip->seek_base, - SEEK_SET)) + if (0 > seek_compat(a, pack_offset + zip->seek_base, + SEEK_SET, 1)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Seek error"); return (ARCHIVE_FATAL); + } zip->stream_offset = pack_offset; } zip->pack_stream_index++; @@ -3688,7 +3719,7 @@ read_stream(struct archive_read *a, const void **buff, size_t size, r = setup_decode_folder(a, &(zip->si.ci.folders[zip->folder_index]), 0); if (r != ARCHIVE_OK) - return (ARCHIVE_FATAL); + return (r); zip->folder_index++; } @@ -3763,15 +3794,9 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, } /* - * Initialize a stream reader. - */ - zip->pack_stream_remaining = (unsigned)folder->numPackedStreams; - zip->pack_stream_index = (unsigned)folder->packIndex; - zip->folder_outbytes_remaining = folder_uncompressed_size(folder); - zip->uncompressed_buffer_bytes_remaining = 0; - - /* - * Check coder types. + * Check coder types before modifying any stream-reader state, so that + * an early return leaves zip unchanged (avoids partially-initialized + * state that callers would have to reason about). */ for (i = 0; i < folder->numCoders; i++) { switch(folder->coders[i].codec) { @@ -3789,7 +3814,7 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, ARCHIVE_ERRNO_MISC, "The %s is encrypted, " "but currently not supported", cname); - return (ARCHIVE_FATAL); + return (header ? ARCHIVE_FATAL : ARCHIVE_FAILED); } case _7Z_X86_BCJ2: { found_bcj2++; @@ -3809,8 +3834,16 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, ARCHIVE_ERRNO_MISC, "The %s is encoded with many filters, " "but currently not supported", cname); - return (ARCHIVE_FATAL); + return (header ? ARCHIVE_FATAL : ARCHIVE_FAILED); } + + /* + * Initialize a stream reader. + */ + zip->pack_stream_remaining = (unsigned)folder->numPackedStreams; + zip->pack_stream_index = (unsigned)folder->packIndex; + zip->folder_outbytes_remaining = folder_uncompressed_size(folder); + zip->uncompressed_buffer_bytes_remaining = 0; coder1 = &(folder->coders[0]); if (folder->numCoders == 2) coder2 = &(folder->coders[1]); @@ -3831,6 +3864,7 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, ssize_t bytes; unsigned char *b[3] = {NULL, NULL, NULL}; uint64_t sunpack[3] ={-1, -1, -1}; + uint64_t remaining; size_t s[3] = {0, 0, 0}; int idx[3] = {0, 1, 2}; @@ -3885,12 +3919,14 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, coder2 = &(fc[3]); zip->main_stream_bytes_remaining = (size_t)folder->unPackSize[2]; + remaining = folder->unPackSize[2]; } else if (coder2 != NULL && coder2->codec == _7Z_X86_BCJ2 && zip->pack_stream_remaining == 4 && folder->numInStreams == 5 && folder->numOutStreams == 2) { /* Source type 0 made by 7z */ zip->main_stream_bytes_remaining = (size_t)folder->unPackSize[0]; + remaining = folder->unPackSize[0]; } else { /* We got an unexpected form. */ archive_set_error(&(a->archive), @@ -3898,6 +3934,15 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, "Unsupported form of BCJ2 streams"); return (ARCHIVE_FATAL); } + if (remaining > SIZE_MAX) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "7-Zip sub-stream size exceeds " + "platform maximum"); + return (ARCHIVE_FATAL); + } + zip->main_stream_bytes_remaining = remaining; + /* Skip the main stream at this time. */ if ((r = seek_pack(a)) < 0) @@ -3929,6 +3974,14 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, /* Allocate memory for the decoded data of a sub * stream. */ + if (zip->folder_outbytes_remaining > SIZE_MAX) { + free(b[0]); free(b[1]); free(b[2]); + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "7-Zip sub-stream size exceeds " + "platform maximum"); + return (ARCHIVE_FATAL); + } b[i] = malloc((size_t)zip->folder_outbytes_remaining); if (b[i] == NULL) { free(b[0]); free(b[1]); free(b[2]); @@ -4101,9 +4154,7 @@ x86_Convert(struct _7zip *zip, uint8_t *data, size_t size) prevPosT = bufferPos; if (Test86MSByte(p[4])) { - uint32_t src = ((uint32_t)p[4] << 24) | - ((uint32_t)p[3] << 16) | ((uint32_t)p[2] << 8) | - ((uint32_t)p[1]); + uint32_t src = archive_le32dec(p + 1); uint32_t dest; for (;;) { uint8_t b; @@ -4163,16 +4214,13 @@ arm_Convert(struct _7zip *zip, uint8_t *buf, size_t size) for (i = 0; i + 4 <= size; i += 4) { if (buf[i + 3] == 0xEB) { // Calculate the transformed addr. - addr = (uint32_t)buf[i] | ((uint32_t)buf[i + 1] << 8) - | ((uint32_t)buf[i + 2] << 16); + addr = archive_le24dec(buf + i); addr <<= 2; addr -= zip->bcj_ip + (uint32_t)i; addr >>= 2; // Store the transformed addr in buf. - buf[i] = (uint8_t)addr; - buf[i + 1] = (uint8_t)(addr >> 8); - buf[i + 2] = (uint8_t)(addr >> 16); + archive_le24enc(buf + i, addr); } } @@ -4203,20 +4251,14 @@ arm64_Convert(struct _7zip *zip, uint8_t *buf, size_t size) uint32_t addr; for (i = 0; i + 4 <= size; i += 4) { - instr = (uint32_t)buf[i] - | ((uint32_t)buf[i+1] << 8) - | ((uint32_t)buf[i+2] << 16) - | ((uint32_t)buf[i+3] << 24); + instr = archive_le32dec(buf + i); if ((instr >> 26) == 0x25) { /* BL instruction */ addr = instr - ((zip->bcj_ip + (uint32_t)i) >> 2); instr = 0x94000000 | (addr & 0x03FFFFFF); - buf[i] = (uint8_t)instr; - buf[i+1] = (uint8_t)(instr >> 8); - buf[i+2] = (uint8_t)(instr >> 16); - buf[i+3] = (uint8_t)(instr >> 24); + archive_le32enc(buf + i, instr); } else if ((instr & 0x9F000000) == 0x90000000) { /* ADRP instruction */ addr = ((instr >> 29) & 3) | ((instr >> 3) & 0x1FFFFC); @@ -4232,10 +4274,7 @@ arm64_Convert(struct _7zip *zip, uint8_t *buf, size_t size) instr |= (addr & 0x03FFFC) << 3; instr |= (0U - (addr & 0x020000)) & 0xE00000; - buf[i] = (uint8_t)instr; - buf[i+1] = (uint8_t)(instr >> 8); - buf[i+2] = (uint8_t)(instr >> 16); - buf[i+3] = (uint8_t)(instr >> 24); + archive_le32enc(buf + i, instr); } } @@ -4278,10 +4317,7 @@ sparc_Convert(struct _7zip *zip, uint8_t *buf, size_t size) size &= ~(size_t)3; for (i = 0; i < size; i += 4) { - instr = (uint32_t)(buf[i] << 24) - | ((uint32_t)buf[i+1] << 16) - | ((uint32_t)buf[i+2] << 8) - | (uint32_t)buf[i+3]; + instr = archive_be32dec(buf + i); if ((instr >> 22) == 0x100 || (instr >> 22) == 0x1FF) { instr <<= 2; @@ -4290,10 +4326,7 @@ sparc_Convert(struct _7zip *zip, uint8_t *buf, size_t size) instr = ((uint32_t)0x40000000 - (instr & 0x400000)) | 0x40000000 | (instr & 0x3FFFFF); - buf[i] = (uint8_t)(instr >> 24); - buf[i+1] = (uint8_t)(instr >> 16); - buf[i+2] = (uint8_t)(instr >> 8); - buf[i+3] = (uint8_t)instr; + archive_be32enc(buf + i, instr); } } @@ -4504,15 +4537,10 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize) buf2 += 4; size2 -= 4; } - dest = (((uint32_t)v[0] << 24) | - ((uint32_t)v[1] << 16) | - ((uint32_t)v[2] << 8) | - ((uint32_t)v[3])) - + dest = archive_be32dec(v) - ((uint32_t)zip->bcj2_outPos + (uint32_t)outPos + 4); - out[0] = (uint8_t)dest; - out[1] = (uint8_t)(dest >> 8); - out[2] = (uint8_t)(dest >> 16); - out[3] = zip->bcj2_prevByte = (uint8_t)(dest >> 24); + archive_le32enc(out, dest); + zip->bcj2_prevByte = out[3]; for (i = 0; i < 4 && outPos < outSize; i++) outBuf[outPos++] = out[i]; @@ -4538,3 +4566,34 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize) return ((ssize_t)outPos); } + +/* + * Perform a seek to given position. If seeking is not supported, + * target position is in front of current position, and compat is requested, + * try to consume bytes until position is reached. + */ +int64_t +seek_compat(struct archive_read *a, int64_t offset, int whence, int compat) +{ + int64_t ret = ARCHIVE_FAILED; + + if (a->filter->can_seek) + ret = __archive_read_seek(a, offset, whence); + else if (compat) { + switch (whence) { + case SEEK_CUR: + ret = __archive_read_consume(a, offset); + break; + case SEEK_SET: + if (a->filter->position > offset) + break; + ret = __archive_read_consume(a, + offset - a->filter->position); + break; + default: + break; + } + } + + return (ret); +} diff --git a/contrib/libarchive/libarchive/archive_read_support_format_ar.c b/contrib/libarchive/libarchive/archive_read_support_format_ar.c index 6dfe2939d0..5633594405 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_ar.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_ar.c @@ -45,6 +45,7 @@ #include "archive.h" #include "archive_entry.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_read_private.h" @@ -588,24 +589,22 @@ ar_parse_gnu_filename_table(struct archive_read *a) static uint64_t ar_atol8(const char *p, unsigned char_cnt) { - uint64_t l, limit, last_digit_limit; + uint64_t l; unsigned int digit, base; base = 8; - limit = UINT64_MAX / base; - last_digit_limit = UINT64_MAX % base; while ((*p == ' ' || *p == '\t') && char_cnt-- > 0) p++; l = 0; digit = *p - '0'; - while (*p >= '0' && digit < base && char_cnt-- > 0) { - if (l>limit || (l == limit && digit > last_digit_limit)) { + while (*p >= '0' && digit < base && char_cnt-- > 0) { + if (archive_ckd_mul_u64(&l, l, base) || + archive_ckd_add_u64(&l, l, digit)) { l = UINT64_MAX; /* Truncate on overflow. */ break; } - l = (l * base) + digit; digit = *++p - '0'; } return (l); @@ -614,23 +613,21 @@ ar_atol8(const char *p, unsigned char_cnt) static uint64_t ar_atol10(const char *p, unsigned char_cnt) { - uint64_t l, limit, last_digit_limit; + uint64_t l; unsigned int base, digit; base = 10; - limit = UINT64_MAX / base; - last_digit_limit = UINT64_MAX % base; while ((*p == ' ' || *p == '\t') && char_cnt-- > 0) p++; l = 0; digit = *p - '0'; while (*p >= '0' && digit < base && char_cnt-- > 0) { - if (l > limit || (l == limit && digit > last_digit_limit)) { + if (archive_ckd_mul_u64(&l, l, base) || + archive_ckd_add_u64(&l, l, digit)) { l = UINT64_MAX; /* Truncate on overflow. */ break; } - l = (l * base) + digit; digit = *++p - '0'; } return (l); diff --git a/contrib/libarchive/libarchive/archive_read_support_format_cab.c b/contrib/libarchive/libarchive/archive_read_support_format_cab.c index bf8ac6b1ca..bd82b44acc 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_cab.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_cab.c @@ -112,8 +112,8 @@ struct lzx_dec { unsigned char *bitlen; /* - * Use a index table. It's faster than searching a huffman - * coding tree, which is a binary tree. But a use of a large + * Use an index table. It's faster than searching a huffman + * coding tree, which is a binary tree. But usage of a large * index table causes L1 cache read miss many times. */ int max_bits; @@ -264,7 +264,7 @@ struct cfheader { }; struct cab { - /* entry_bytes_remaining is the number of bytes we expect. */ + /* entry_bytes_remaining is the number of bytes we expect. */ int64_t entry_offset; int64_t entry_bytes_remaining; int64_t entry_unconsumed; @@ -279,7 +279,7 @@ struct cab { struct cfheader cfheader; struct archive_wstring ws; - /* Flag to mark progress that an archive was read their first header.*/ + /* Flag to mark progress that first header of an archive was read.*/ char found_header; char end_of_archive; char end_of_entry; @@ -433,7 +433,7 @@ archive_read_format_cab_bid(struct archive_read *a, int best_bid) /* * Attempt to handle self-extracting archives * by noting a PE header and searching forward - * up to 128k for a 'MSCF' marker. + * up to 128k for an 'MSCF' marker. */ if (p[0] == 'M' && p[1] == 'Z') { offset = 0; @@ -501,7 +501,7 @@ cab_skip_sfx(struct archive_read *a) for (;;) { const char *h = __archive_read_ahead(a, window, &bytes); if (h == NULL) { - /* Remaining size are less than window. */ + /* Remaining size is less than window. */ window >>= 1; if (window < 128) { archive_set_error(&a->archive, @@ -554,19 +554,18 @@ cab_strnlen(const unsigned char *p, size_t maxlen) return ((ssize_t)i); } -/* Read bytes as much as remaining. */ +/* Read up to max remaining bytes. */ static const void * -cab_read_ahead_remaining(struct archive_read *a, size_t min, ssize_t *avail) +cab_read_ahead_remaining(struct archive_read *a, size_t max, ssize_t *avail) { - const void *p; + const void *p = __archive_read_ahead(a, max, avail); - while (min > 0) { - p = __archive_read_ahead(a, min, avail); - if (p != NULL) - return (p); - min--; - } - return (NULL); + if (p == NULL && *avail > 0) + p = __archive_read_ahead(a, *avail, avail); + if (p != NULL && (size_t)*avail > max) + *avail = max; + + return (p); } /* Convert a path separator '\' -> '/' */ @@ -627,7 +626,7 @@ cab_read_header(struct archive_read *a) struct cab *cab; struct cfheader *hd; size_t bytes, used; - ssize_t len; + ssize_t avail, len; int64_t skip; int err, i; int cur_folder, prev_folder; @@ -691,29 +690,34 @@ cab_read_header(struct archive_read *a) hd->cffolder = 0;/* Avoid compiling warning. */ if (hd->flags & PREV_CABINET) { /* How many bytes are used for szCabinetPrev. */ - if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) + if ((p = cab_read_ahead_remaining(a, used + 256, + &avail)) == NULL || (size_t)avail <= used) return (truncated_error(a)); - if ((len = cab_strnlen(p + used, 255)) <= 0) + if ((len = cab_strnlen(p + used, avail - used - 1)) <= 0) { goto invalid; + } used += len + 1; /* How many bytes are used for szDiskPrev. */ - if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) + if ((p = cab_read_ahead_remaining(a, used + 256, + &avail)) == NULL || (size_t)avail <= used) return (truncated_error(a)); - if ((len = cab_strnlen(p + used, 255)) <= 0) + if ((len = cab_strnlen(p + used, avail - used - 1)) < 0) goto invalid; used += len + 1; } if (hd->flags & NEXT_CABINET) { /* How many bytes are used for szCabinetNext. */ - if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) + if ((p = cab_read_ahead_remaining(a, used + 256, + &avail)) == NULL || (size_t)avail <= used) return (truncated_error(a)); - if ((len = cab_strnlen(p + used, 255)) <= 0) + if ((len = cab_strnlen(p + used, avail - used - 1)) <= 0) goto invalid; used += len + 1; /* How many bytes are used for szDiskNext. */ - if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) + if ((p = cab_read_ahead_remaining(a, used + 256, + &avail)) == NULL || (size_t)avail <= used) return (truncated_error(a)); - if ((len = cab_strnlen(p + used, 255)) <= 0) + if ((len = cab_strnlen(p + used, avail - used - 1)) < 0) goto invalid; used += len + 1; } @@ -776,7 +780,7 @@ cab_read_header(struct archive_read *a) */ /* Seek read pointer to the offset of CFFILE if needed. */ skip = (int64_t)hd->files_offset - cab->cab_offset; - if (skip < 0) { + if (skip < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid offset of CFFILE %jd < %jd", (intmax_t)hd->files_offset, (intmax_t)cab->cab_offset); @@ -795,7 +799,6 @@ cab_read_header(struct archive_read *a) prev_folder = -1; for (i = 0; i < hd->file_count; i++) { struct cffile *file = &(hd->file_array[i]); - ssize_t avail; if ((p = __archive_read_ahead(a, 16, NULL)) == NULL) return (truncated_error(a)); @@ -1336,6 +1339,10 @@ cab_next_cfdata(struct archive_read *a) } return (ARCHIVE_OK); invalid: + cfdata->compressed_size = 0; + cfdata->compressed_bytes_remaining = 0; + cfdata->uncompressed_size = 0; + cfdata->uncompressed_bytes_remaining = 0; archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid CFDATA"); return (ARCHIVE_FATAL); @@ -1478,6 +1485,14 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail) cab->uncompressed_buffer + cab->stream.total_out; cab->stream.avail_out = cfdata->uncompressed_size - cab->stream.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 (bytes_avail <= 0) { @@ -1565,11 +1580,9 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail) * correctly compute the sum of CFDATA accordingly. */ if (cfdata->compressed_bytes_remaining > 0) { - ssize_t bytes_avail; - d = __archive_read_ahead(a, cfdata->compressed_bytes_remaining, - &bytes_avail); - if (bytes_avail <= 0) { + NULL); + if (d == NULL) { *avail = truncated_error(a); return (NULL); } @@ -1737,11 +1750,9 @@ cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail) * Make sure a read pointer advances to next CFDATA. */ if (cfdata->compressed_bytes_remaining > 0) { - ssize_t bytes_avail; - d = __archive_read_ahead(a, cfdata->compressed_bytes_remaining, - &bytes_avail); - if (bytes_avail <= 0) { + NULL); + if (d == NULL) { *avail = truncated_error(a); return (NULL); } @@ -3211,6 +3222,10 @@ lzx_make_huffman_table(struct huffman *hf) bitlen = hf->bitlen; len_avail = hf->len_size; hf->tree_used = 0; + /* Initialize table to invalid values */ + for (i = 0; i < tbl_size; i++) { + tbl[i] = (uint16_t)hf->len_size; + } for (i = 0; i < len_avail; i++) { uint16_t *p; int len, cnt; diff --git a/contrib/libarchive/libarchive/archive_read_support_format_cpio.c b/contrib/libarchive/libarchive/archive_read_support_format_cpio.c index 43169f6180..86d2bc95d5 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_cpio.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_cpio.c @@ -38,6 +38,7 @@ #endif #include "archive.h" +#include "archive_endian.h" #include "archive_entry.h" #include "archive_entry_locale.h" #include "archive_private.h" @@ -160,6 +161,8 @@ #define afiol_filesize_c_offset 115 /* ':' */ #define afiol_header_size 116 +/* CPIO name fields store a full pathname, including the terminating NUL. */ +#define CPIO_PATHNAME_MAX (1024 * 1024) struct links_entry { struct links_entry *next; @@ -200,7 +203,7 @@ static int archive_read_format_cpio_read_data(struct archive_read *, static int archive_read_format_cpio_read_header(struct archive_read *, struct archive_entry *); static int archive_read_format_cpio_skip(struct archive_read *); -static int64_t be4(const unsigned char *); +static int64_t be32dec(const unsigned char *); static int find_odc_header(struct archive_read *); static int find_newc_header(struct archive_read *); static int header_bin_be(struct archive_read *, struct cpio *, @@ -215,7 +218,7 @@ static int header_afiol(struct archive_read *, struct cpio *, struct archive_entry *, size_t *, size_t *); static int is_octal(const char *, size_t); static int is_hex(const char *, size_t); -static int64_t le4(const unsigned char *); +static int64_t le32dec(const unsigned char *); static int record_hardlink(struct archive_read *a, struct cpio *cpio, struct archive_entry *entry); @@ -303,12 +306,12 @@ archive_read_format_cpio_bid(struct archive_read *a, int best_bid) * XXX TODO: More verification; Could check that only hex * digits appear in appropriate header locations. XXX */ - } else if (p[0] * 256 + p[1] == 070707) { + } else if (archive_be16dec(p) == 070707) { /* big-endian binary cpio archives */ cpio->read_header = header_bin_be; bid += 16; /* Is more verification possible here? */ - } else if (p[0] + p[1] * 256 == 070707) { + } else if (archive_le16dec(p) == 070707) { /* little-endian binary cpio archives */ cpio->read_header = header_bin_le; bid += 16; @@ -385,8 +388,15 @@ archive_read_format_cpio_read_header(struct archive_read *a, if (r < ARCHIVE_WARN) return (r); + if (namelength > CPIO_PATHNAME_MAX) { + archive_set_error(&a->archive, ENOMEM, + "Rejecting malformed cpio archive: " + "pathname exceeds 1 megabyte"); + return (ARCHIVE_FATAL); + } + /* Read name from buffer. */ - h = __archive_read_ahead(a, namelength + name_pad, NULL); + h = __archive_read_ahead(a, namelength, NULL); if (h == NULL) return (ARCHIVE_FATAL); if (archive_entry_copy_pathname_l(entry, @@ -403,7 +413,8 @@ archive_read_format_cpio_read_header(struct archive_read *a, } cpio->entry_offset = 0; - __archive_read_consume(a, namelength + name_pad); + __archive_read_consume(a, namelength); + __archive_read_consume(a, name_pad); /* If this is a symlink, read the link contents. */ if (archive_entry_filetype(entry) == AE_IFLNK) { @@ -703,13 +714,24 @@ find_odc_header(struct archive_read *a) { const void *h; const char *p, *q; - size_t skip, skipped = 0; + int64_t skip; + uintmax_t skipped = 0; ssize_t bytes; for (;;) { - h = __archive_read_ahead(a, odc_header_size, &bytes); - if (h == NULL) - return (ARCHIVE_FATAL); + size_t header_size; + + header_size = afiol_header_size; + h = __archive_read_ahead(a, afiol_header_size, &bytes); + if (h == NULL) { + if (bytes >= odc_header_size) { + header_size = odc_header_size; + h = __archive_read_ahead(a, odc_header_size, + &bytes); + } + if (h == NULL) + return (ARCHIVE_FATAL); + } p = h; q = p + bytes; @@ -725,7 +747,7 @@ find_odc_header(struct archive_read *a) * Scan ahead until we find something that looks * like an odc header. */ - while (p + odc_header_size <= q) { + while (p + header_size <= q) { switch (p[5]) { case '7': if ((memcmp("070707", p, 6) == 0 @@ -741,9 +763,9 @@ find_odc_header(struct archive_read *a) if (skipped > 0) { archive_set_error(&a->archive, 0, - "Skipped %d bytes before " + "Skipped %ju bytes before " "finding valid header", - (int)skipped); + skipped); return (ARCHIVE_WARN); } return (ARCHIVE_OK); @@ -828,7 +850,7 @@ header_odc(struct archive_read *a, struct cpio *cpio, * NOTE: if a filename suffix is ".z", it is a file gzipped by afio. * it would be nice if we could show uncompressed file size and * uncompress file contents automatically, unfortunately we have nothing - * to get a uncompressed file size while reading each header. It means + * to get an uncompressed file size while reading each header. It means * we also cannot uncompress file contents under our framework. */ static int @@ -873,7 +895,8 @@ header_afiol(struct archive_read *a, struct cpio *cpio, t = atol16(header + afiol_filesize_offset, afiol_filesize_size); if (t < 0) { - archive_set_error(&a->archive, 0, "Nonsensical file size"); + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Nonsensical file size"); return (ARCHIVE_FATAL); } cpio->entry_bytes_remaining = t; @@ -897,7 +920,7 @@ header_bin_le(struct archive_read *a, struct cpio *cpio, /* Read fixed-size portion of header. */ h = __archive_read_ahead(a, bin_header_size, NULL); if (h == NULL) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "End of file trying to read next cpio header"); return (ARCHIVE_FATAL); } @@ -905,24 +928,24 @@ header_bin_le(struct archive_read *a, struct cpio *cpio, /* Parse out binary fields. */ header = (const unsigned char *)h; - archive_entry_set_dev(entry, header[bin_dev_offset] + header[bin_dev_offset + 1] * 256); - archive_entry_set_ino(entry, header[bin_ino_offset] + header[bin_ino_offset + 1] * 256); - archive_entry_set_mode(entry, header[bin_mode_offset] + header[bin_mode_offset + 1] * 256); + archive_entry_set_dev(entry, archive_le16dec(header + bin_dev_offset)); + archive_entry_set_ino(entry, archive_le16dec(header + bin_ino_offset)); + archive_entry_set_mode(entry, archive_le16dec(header + bin_mode_offset)); if (cpio->option_pwb) { /* turn off random bits left over from V6 inode */ archive_entry_set_mode(entry, archive_entry_mode(entry) & 067777); if ((archive_entry_mode(entry) & AE_IFMT) == 0) archive_entry_set_mode(entry, archive_entry_mode(entry) | AE_IFREG); } - archive_entry_set_uid(entry, header[bin_uid_offset] + header[bin_uid_offset + 1] * 256); - archive_entry_set_gid(entry, header[bin_gid_offset] + header[bin_gid_offset + 1] * 256); - archive_entry_set_nlink(entry, header[bin_nlink_offset] + header[bin_nlink_offset + 1] * 256); - archive_entry_set_rdev(entry, header[bin_rdev_offset] + header[bin_rdev_offset + 1] * 256); - archive_entry_set_mtime(entry, le4(header + bin_mtime_offset), 0); - *namelength = header[bin_namesize_offset] + header[bin_namesize_offset + 1] * 256; + archive_entry_set_uid(entry, archive_le16dec(header + bin_uid_offset)); + archive_entry_set_gid(entry, archive_le16dec(header + bin_gid_offset)); + archive_entry_set_nlink(entry, archive_le16dec(header + bin_nlink_offset)); + archive_entry_set_rdev(entry, archive_le16dec(header + bin_rdev_offset)); + archive_entry_set_mtime(entry, le32dec(header + bin_mtime_offset), 0); + *namelength = archive_le16dec(header + bin_namesize_offset); *name_pad = *namelength & 1; /* Pad to even. */ - cpio->entry_bytes_remaining = le4(header + bin_filesize_offset); + cpio->entry_bytes_remaining = le32dec(header + bin_filesize_offset); archive_entry_set_size(entry, cpio->entry_bytes_remaining); cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */ __archive_read_consume(a, bin_header_size); @@ -942,7 +965,7 @@ header_bin_be(struct archive_read *a, struct cpio *cpio, /* Read fixed-size portion of header. */ h = __archive_read_ahead(a, bin_header_size, NULL); if (h == NULL) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "End of file trying to read next cpio header"); return (ARCHIVE_FATAL); } @@ -950,24 +973,24 @@ header_bin_be(struct archive_read *a, struct cpio *cpio, /* Parse out binary fields. */ header = (const unsigned char *)h; - archive_entry_set_dev(entry, header[bin_dev_offset] * 256 + header[bin_dev_offset + 1]); - archive_entry_set_ino(entry, header[bin_ino_offset] * 256 + header[bin_ino_offset + 1]); - archive_entry_set_mode(entry, header[bin_mode_offset] * 256 + header[bin_mode_offset + 1]); + archive_entry_set_dev(entry, archive_be16dec(header + bin_dev_offset)); + archive_entry_set_ino(entry, archive_be16dec(header + bin_ino_offset)); + archive_entry_set_mode(entry, archive_be16dec(header + bin_mode_offset)); if (cpio->option_pwb) { /* turn off random bits left over from V6 inode */ archive_entry_set_mode(entry, archive_entry_mode(entry) & 067777); if ((archive_entry_mode(entry) & AE_IFMT) == 0) archive_entry_set_mode(entry, archive_entry_mode(entry) | AE_IFREG); } - archive_entry_set_uid(entry, header[bin_uid_offset] * 256 + header[bin_uid_offset + 1]); - archive_entry_set_gid(entry, header[bin_gid_offset] * 256 + header[bin_gid_offset + 1]); - archive_entry_set_nlink(entry, header[bin_nlink_offset] * 256 + header[bin_nlink_offset + 1]); - archive_entry_set_rdev(entry, header[bin_rdev_offset] * 256 + header[bin_rdev_offset + 1]); - archive_entry_set_mtime(entry, be4(header + bin_mtime_offset), 0); - *namelength = header[bin_namesize_offset] * 256 + header[bin_namesize_offset + 1]; + archive_entry_set_uid(entry, archive_be16dec(header + bin_uid_offset)); + archive_entry_set_gid(entry, archive_be16dec(header + bin_gid_offset)); + archive_entry_set_nlink(entry, archive_be16dec(header + bin_nlink_offset)); + archive_entry_set_rdev(entry, archive_be16dec(header + bin_rdev_offset)); + archive_entry_set_mtime(entry, be32dec(header + bin_mtime_offset), 0); + *namelength = archive_be16dec(header + bin_namesize_offset); *name_pad = *namelength & 1; /* Pad to even. */ - cpio->entry_bytes_remaining = be4(header + bin_filesize_offset); + cpio->entry_bytes_remaining = be32dec(header + bin_filesize_offset); archive_entry_set_size(entry, cpio->entry_bytes_remaining); cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */ __archive_read_consume(a, bin_header_size); @@ -994,16 +1017,15 @@ archive_read_format_cpio_cleanup(struct archive_read *a) } static int64_t -le4(const unsigned char *p) +le32dec(const unsigned char *p) { - return ((p[0] << 16) | (((int64_t)p[1]) << 24) | (p[2] << 0) | (p[3] << 8)); + return ((int64_t)archive_le16dec(p) << 16) | archive_le16dec(p + 2); } - static int64_t -be4(const unsigned char *p) +be32dec(const unsigned char *p) { - return ((((int64_t)p[0]) << 24) | (p[1] << 16) | (p[2] << 8) | (p[3])); + return ((int64_t)archive_be16dec(p) << 16) | archive_be16dec(p + 2); } /* @@ -1051,7 +1073,7 @@ atol16u(const char *p, unsigned char_cnt) else if (*p >= '0' && *p <= '9') digit = *p - '0'; else - return ((int64_t)l); + return (l); p++; l <<= 4; l |= digit; @@ -1102,20 +1124,32 @@ record_hardlink(struct archive_read *a, ENOMEM, "Out of memory adding file to list"); return (ARCHIVE_FATAL); } - if (cpio->links_head != NULL) - cpio->links_head->previous = le; - le->next = cpio->links_head; - le->previous = NULL; - cpio->links_head = le; + + const char *pathname = archive_entry_pathname(entry); + if (pathname == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid hardlink entry with no pathname"); + free(le); + return (ARCHIVE_FATAL); + } + le->dev = dev; le->ino = ino; le->links = archive_entry_nlink(entry) - 1; - le->name = strdup(archive_entry_pathname(entry)); + le->name = strdup(pathname); if (le->name == NULL) { archive_set_error(&a->archive, ENOMEM, "Out of memory adding file to list"); + free(le); return (ARCHIVE_FATAL); } + if (cpio->links_head != NULL) + cpio->links_head->previous = le; + le->next = cpio->links_head; + le->previous = NULL; + cpio->links_head = le; + return (ARCHIVE_OK); } diff --git a/contrib/libarchive/libarchive/archive_read_support_format_iso9660.c b/contrib/libarchive/libarchive/archive_read_support_format_iso9660.c index c69fcd272b..e1df6273fe 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_iso9660.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_iso9660.c @@ -268,6 +268,7 @@ struct file_info { uint64_t size; /* File size in bytes. */ uint32_t ce_offset; /* Offset of CE. */ uint32_t ce_size; /* Size of CE. */ + uint64_t ce_processed_end;/* End offset of processed CE. */ char rr_moved; /* Flag to rr_moved. */ char rr_moved_has_re_only; char re; /* Having RRIP "RE" extension. */ @@ -436,7 +437,6 @@ static void parse_rockridge_ZF1(struct file_info *, const unsigned char *, int); static void register_file(struct iso9660 *, struct file_info *); static void release_files(struct iso9660 *); -static unsigned toi(const void *p, int n); static inline void re_add_entry(struct iso9660 *, struct file_info *); static inline struct file_info * re_get_entry(struct iso9660 *); static inline int rede_add_entry(struct file_info *); @@ -1865,7 +1865,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, } name_len = (size_t)isodirrec[DR_name_len_offset]; location = archive_le32dec(isodirrec + DR_extent_offset); - fsize = toi(isodirrec + DR_size_offset, DR_size_size); + fsize = archive_le32dec(isodirrec + DR_size_offset); /* Sanity check that name_len doesn't exceed dr_len. */ if (dr_len - 33 < name_len || name_len == 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -2162,7 +2162,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, fprintf(stderr, "\n ** Unrecognized flag: "); dump_isodirrec(stderr, isodirrec); fprintf(stderr, "\n"); - } else if (toi(isodirrec + DR_volume_sequence_number_offset, 2) != 1) { + } else if (archive_le16dec(isodirrec + DR_volume_sequence_number_offset) != 1) { fprintf(stderr, "\n ** Unrecognized sequence number: "); dump_isodirrec(stderr, isodirrec); fprintf(stderr, "\n"); @@ -2255,9 +2255,10 @@ parse_rockridge(struct archive_read *a, struct file_info *file, */ if (p[1] == 'N') { if (version == 1 && data_length == 16) { - file->rdev = toi(data,4); + file->rdev = archive_le32dec(data); file->rdev <<= 32; - file->rdev |= toi(data + 8, 4); + file->rdev |= + archive_le32dec(data + 8); iso9660->seenRockridge = 1; } } @@ -2272,20 +2273,20 @@ parse_rockridge(struct archive_read *a, struct file_info *file, */ if (version == 1) { if (data_length >= 8) - file->mode - = (__LA_MODE_T)toi(data, 4); + file->mode = (__LA_MODE_T) + archive_le32dec(data); if (data_length >= 16) - file->nlinks - = toi(data + 8, 4); + file->nlinks = + archive_le32dec(data + 8); if (data_length >= 24) - file->uid - = toi(data + 16, 4); + file->uid = + archive_le32dec(data + 16); if (data_length >= 32) - file->gid - = toi(data + 24, 4); + file->gid = + archive_le32dec(data + 24); if (data_length >= 40) - file->number - = toi(data + 32, 4); + file->number = + archive_le32dec(data + 32); iso9660->seenRockridge = 1; } } @@ -2483,6 +2484,7 @@ read_CE(struct archive_read *a, struct iso9660 *iso9660) const unsigned char *b, *p, *end; struct file_info *file; size_t step; + uint64_t ce_start, ce_end; int r; /* Read data which RRIP "CE" extension points. */ @@ -2506,8 +2508,16 @@ read_CE(struct archive_read *a, struct iso9660 *iso9660) "Malformed CE information"); return (ARCHIVE_FATAL); } + ce_start = heap->reqs[0].offset + file->ce_offset; + ce_end = ce_start + file->ce_size; + if (ce_start < file->ce_processed_end) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid parameter in SUSP \"CE\" extension"); + return (ARCHIVE_FATAL); + } p = b + file->ce_offset; end = p + file->ce_size; + file->ce_processed_end = ce_end; next_CE(heap); r = parse_rockridge(a, file, p, end); if (r != ARCHIVE_OK) @@ -3238,17 +3248,6 @@ heap_get_entry(struct heap_queue *heap) } } -static unsigned int -toi(const void *p, int n) -{ - const unsigned char *v = (const unsigned char *)p; - if (n > 1) - return v[0] + 256 * toi(v + 1, n - 1); - if (n == 1) - return v[0]; - return (0); -} - /* * ECMA119/ISO9660 stores multi-byte integers in one of * three different formats: @@ -3493,6 +3492,8 @@ build_pathname_utf16be(unsigned char *p, size_t max, size_t *len, if (file->parent != NULL && file->parent->utf16be_bytes > 0) { if (build_pathname_utf16be(p, max, len, file->parent) != 0) return (-1); + if (*len + 2 > max) + return (-1);/* Path is too long! */ p[*len] = 0; p[*len + 1] = '/'; *len += 2; @@ -3517,26 +3518,24 @@ static void dump_isodirrec(FILE *out, const unsigned char *isodirrec) { fprintf(out, " l %d,", - toi(isodirrec + DR_length_offset, DR_length_size)); + isodirrec[DR_length_offset]); fprintf(out, " a %d,", - toi(isodirrec + DR_ext_attr_length_offset, DR_ext_attr_length_size)); + isodirrec[DR_ext_attr_length_offset]); fprintf(out, " ext 0x%x,", - toi(isodirrec + DR_extent_offset, DR_extent_size)); + archive_le32dec(isodirrec + DR_extent_offset)); fprintf(out, " s %d,", - toi(isodirrec + DR_size_offset, DR_extent_size)); + archive_le32dec(isodirrec + DR_size_offset)); fprintf(out, " f 0x%x,", - toi(isodirrec + DR_flags_offset, DR_flags_size)); + isodirrec[DR_flags_offset]); fprintf(out, " u %d,", - toi(isodirrec + DR_file_unit_size_offset, DR_file_unit_size_size)); + isodirrec[DR_file_unit_size_offset]); fprintf(out, " ilv %d,", - toi(isodirrec + DR_interleave_offset, DR_interleave_size)); + isodirrec[DR_interleave_offset]); fprintf(out, " seq %d,", - toi(isodirrec + DR_volume_sequence_number_offset, - DR_volume_sequence_number_size)); + archive_le16dec(isodirrec + DR_volume_sequence_number_offset)); fprintf(out, " nl %d:", - toi(isodirrec + DR_name_len_offset, DR_name_len_size)); + isodirrec[DR_name_len_offset]); fprintf(out, " `%.*s'", - toi(isodirrec + DR_name_len_offset, DR_name_len_size), - isodirrec + DR_name_offset); + isodirrec[DR_name_len_offset], isodirrec + DR_name_offset); } #endif diff --git a/contrib/libarchive/libarchive/archive_read_support_format_lha.c b/contrib/libarchive/libarchive/archive_read_support_format_lha.c index ff6dbb8df1..b9e6a17893 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_lha.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_lha.c @@ -107,8 +107,8 @@ struct lzh_dec { unsigned char *bitlen; /* - * Use a index table. It's faster than searching a huffman - * coding tree, which is a binary tree. But a use of a large + * Use an index table. It's faster than searching a huffman + * coding tree, which is a binary tree. But usage of a large * index table causes L1 cache read miss many times. */ #define HTBL_BITS 10 @@ -142,7 +142,6 @@ struct lzh_stream { int64_t total_in; const unsigned char *ref_ptr; int avail_out; - int64_t total_out; struct lzh_dec *ds; }; @@ -239,7 +238,6 @@ static int lha_read_data_none(struct archive_read *, const void **, size_t *, int64_t *); static int lha_read_data_lzh(struct archive_read *, const void **, size_t *, int64_t *); -static void lha_crc16_init(void); static uint16_t lha_crc16(uint16_t, const void *, size_t); static int lzh_decode_init(struct lzh_stream *, const char *); static void lzh_decode_free(struct lzh_stream *); @@ -483,8 +481,6 @@ archive_read_format_lha_read_header(struct archive_read *a, struct archive_mstring conv_buffer; const wchar_t *conv_buffer_p; - lha_crc16_init(); - a->archive.archive_format = ARCHIVE_FORMAT_LHA; if (a->archive.archive_format_name == NULL) a->archive.archive_format_name = "lha"; @@ -1588,7 +1584,6 @@ lha_read_data_lzh(struct archive_read *a, const void **buff, /* We've initialized decompression for this stream. */ lha->decompress_init = 1; lha->strm.avail_out = 0; - lha->strm.total_out = 0; } /* @@ -1733,30 +1728,86 @@ lha_calcsum(unsigned char sum, const void *pp, int offset, size_t size) return (sum); } -static uint16_t crc16tbl[2][256]; -static void -lha_crc16_init(void) -{ - unsigned int i; - static int crc16init = 0; - - if (crc16init) - return; - crc16init = 1; - - for (i = 0; i < 256; i++) { - unsigned int j; - uint16_t crc = (uint16_t)i; - for (j = 8; j; j--) - crc = (crc >> 1) ^ ((crc & 1) * 0xA001); - crc16tbl[0][i] = crc; - } - - for (i = 0; i < 256; i++) { - crc16tbl[1][i] = (crc16tbl[0][i] >> 8) - ^ crc16tbl[0][crc16tbl[0][i] & 0xff]; +static const uint16_t crc16tbl[2][256] = { + { + 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, + 0xc241, 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, + 0xc481, 0x0440, 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, + 0xcfc1, 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81, 0x0b40, + 0xc901, 0x09c0, 0x0880, 0xc841, 0xd801, 0x18c0, 0x1980, + 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, + 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, 0x1400, + 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, + 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, + 0x1040, 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, + 0xf281, 0x3240, 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, + 0x35c0, 0x3480, 0xf441, 0x3c00, 0xfcc1, 0xfd81, 0x3d40, + 0xff01, 0x3fc0, 0x3e80, 0xfe41, 0xfa01, 0x3ac0, 0x3b80, + 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, 0x2800, 0xe8c1, + 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 0xee01, + 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, + 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, + 0x2640, 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, + 0x2080, 0xe041, 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, + 0xa3c1, 0xa281, 0x6240, 0x6600, 0xa6c1, 0xa781, 0x6740, + 0xa501, 0x65c0, 0x6480, 0xa441, 0x6c00, 0xacc1, 0xad81, + 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 0xaa01, 0x6ac0, + 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, 0x7800, + 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, + 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, + 0x7c40, 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, + 0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, + 0x71c0, 0x7080, 0xb041, 0x5000, 0x90c1, 0x9181, 0x5140, + 0x9301, 0x53c0, 0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, + 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, 0x9c01, 0x5cc0, + 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 0x5a00, + 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, + 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, + 0x4a40, 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, + 0x4c80, 0x8c41, 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, + 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, + 0x4100, 0x81c1, 0x8081, 0x4040 + }, + { + 0x0000, 0x9001, 0x6001, 0xf000, 0xc002, 0x5003, 0xa003, + 0x3002, 0xc007, 0x5006, 0xa006, 0x3007, 0x0005, 0x9004, + 0x6004, 0xf005, 0xc00d, 0x500c, 0xa00c, 0x300d, 0x000f, + 0x900e, 0x600e, 0xf00f, 0x000a, 0x900b, 0x600b, 0xf00a, + 0xc008, 0x5009, 0xa009, 0x3008, 0xc019, 0x5018, 0xa018, + 0x3019, 0x001b, 0x901a, 0x601a, 0xf01b, 0x001e, 0x901f, + 0x601f, 0xf01e, 0xc01c, 0x501d, 0xa01d, 0x301c, 0x0014, + 0x9015, 0x6015, 0xf014, 0xc016, 0x5017, 0xa017, 0x3016, + 0xc013, 0x5012, 0xa012, 0x3013, 0x0011, 0x9010, 0x6010, + 0xf011, 0xc031, 0x5030, 0xa030, 0x3031, 0x0033, 0x9032, + 0x6032, 0xf033, 0x0036, 0x9037, 0x6037, 0xf036, 0xc034, + 0x5035, 0xa035, 0x3034, 0x003c, 0x903d, 0x603d, 0xf03c, + 0xc03e, 0x503f, 0xa03f, 0x303e, 0xc03b, 0x503a, 0xa03a, + 0x303b, 0x0039, 0x9038, 0x6038, 0xf039, 0x0028, 0x9029, + 0x6029, 0xf028, 0xc02a, 0x502b, 0xa02b, 0x302a, 0xc02f, + 0x502e, 0xa02e, 0x302f, 0x002d, 0x902c, 0x602c, 0xf02d, + 0xc025, 0x5024, 0xa024, 0x3025, 0x0027, 0x9026, 0x6026, + 0xf027, 0x0022, 0x9023, 0x6023, 0xf022, 0xc020, 0x5021, + 0xa021, 0x3020, 0xc061, 0x5060, 0xa060, 0x3061, 0x0063, + 0x9062, 0x6062, 0xf063, 0x0066, 0x9067, 0x6067, 0xf066, + 0xc064, 0x5065, 0xa065, 0x3064, 0x006c, 0x906d, 0x606d, + 0xf06c, 0xc06e, 0x506f, 0xa06f, 0x306e, 0xc06b, 0x506a, + 0xa06a, 0x306b, 0x0069, 0x9068, 0x6068, 0xf069, 0x0078, + 0x9079, 0x6079, 0xf078, 0xc07a, 0x507b, 0xa07b, 0x307a, + 0xc07f, 0x507e, 0xa07e, 0x307f, 0x007d, 0x907c, 0x607c, + 0xf07d, 0xc075, 0x5074, 0xa074, 0x3075, 0x0077, 0x9076, + 0x6076, 0xf077, 0x0072, 0x9073, 0x6073, 0xf072, 0xc070, + 0x5071, 0xa071, 0x3070, 0x0050, 0x9051, 0x6051, 0xf050, + 0xc052, 0x5053, 0xa053, 0x3052, 0xc057, 0x5056, 0xa056, + 0x3057, 0x0055, 0x9054, 0x6054, 0xf055, 0xc05d, 0x505c, + 0xa05c, 0x305d, 0x005f, 0x905e, 0x605e, 0xf05f, 0x005a, + 0x905b, 0x605b, 0xf05a, 0xc058, 0x5059, 0xa059, 0x3058, + 0xc049, 0x5048, 0xa048, 0x3049, 0x004b, 0x904a, 0x604a, + 0xf04b, 0x004e, 0x904f, 0x604f, 0xf04e, 0xc04c, 0x504d, + 0xa04d, 0x304c, 0x0044, 0x9045, 0x6045, 0xf044, 0xc046, + 0x5047, 0xa047, 0x3046, 0xc043, 0x5042, 0xa042, 0x3043, + 0x0041, 0x9040, 0x6040, 0xf041 } -} +}; static uint16_t lha_crc16(uint16_t crc, const void *pp, size_t len) @@ -2084,7 +2135,6 @@ lzh_emit_window(struct lzh_stream *strm, size_t s) { strm->ref_ptr = strm->ds->w_buff; strm->avail_out = (int)s; - strm->total_out += s; } static int diff --git a/contrib/libarchive/libarchive/archive_read_support_format_mtree.c b/contrib/libarchive/libarchive/archive_read_support_format_mtree.c index 4a5a49ca81..66e2cb1605 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_mtree.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_mtree.c @@ -51,6 +51,7 @@ #include "archive.h" #include "archive_entry.h" #include "archive_entry_private.h" +#include "archive_integer.h" #include "archive_platform_stat.h" #include "archive_private.h" #include "archive_rb.h" @@ -1790,12 +1791,16 @@ parse_keyword(struct archive_read *a, struct mtree *mtree, * 123456789.1 represents 123456789 * seconds and 1 nanosecond. */ if (*val == '.') { + int64_t v; + ++val; - ns = (long)mtree_atol(&val, 10); - if (ns < 0) + v = mtree_atol(&val, 10); + if (v < 0) ns = 0; - else if (ns > 999999999) + else if (v > 999999999) ns = 999999999; + else + ns = (long)v; } if (m > my_time_t_max) m = my_time_t_max; @@ -2029,9 +2034,9 @@ parsedigit(char c) if (c >= '0' && c <= '9') return c - '0'; else if (c >= 'a' && c <= 'f') - return c - 'a'; + return 10 + c - 'a'; else if (c >= 'A' && c <= 'F') - return c - 'A'; + return 10 + c - 'A'; else return -1; } @@ -2044,8 +2049,8 @@ parsedigit(char c) static int64_t mtree_atol(char **p, int base) { - int64_t l, limit; - int digit, last_digit_limit; + int64_t l; + int digit; if (base == 0) { if (**p != '0') @@ -2059,29 +2064,24 @@ mtree_atol(char **p, int base) } if (**p == '-') { - limit = INT64_MIN / base; - last_digit_limit = -(INT64_MIN % base); ++(*p); l = 0; digit = parsedigit(**p); while (digit >= 0 && digit < base) { - if (l < limit || (l == limit && digit >= last_digit_limit)) + if (archive_ckd_mul_i64(&l, l, base) || + archive_ckd_sub_i64(&l, l, digit)) return INT64_MIN; - l = (l * base) - digit; digit = parsedigit(*++(*p)); } return l; } else { - limit = INT64_MAX / base; - last_digit_limit = INT64_MAX % base; - l = 0; digit = parsedigit(**p); while (digit >= 0 && digit < base) { - if (l > limit || (l == limit && digit > last_digit_limit)) + if (archive_ckd_mul_i64(&l, l, base) || + archive_ckd_add_i64(&l, l, digit)) return INT64_MAX; - l = (l * base) + digit; digit = parsedigit(*++(*p)); } return l; @@ -2100,8 +2100,7 @@ readline(struct archive_read *a, struct mtree *mtree, char **start, ssize_t bytes_read; ssize_t total_size = 0; ssize_t find_off = 0; - const void *t; - void *nl; + const void *nl, *t; char *u; /* Accumulate line in a line buffer. */ diff --git a/contrib/libarchive/libarchive/archive_read_support_format_rar.c b/contrib/libarchive/libarchive/archive_read_support_format_rar.c index 0ed2540cd0..803b2e281a 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_rar.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_rar.c @@ -154,7 +154,7 @@ #define UNP_BUFFER_SIZE (128 * 1024) /* Define this here for non-Windows platforms */ -#if !((defined(__WIN32__) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)) +#ifndef FILE_ATTRIBUTE_DIRECTORY #define FILE_ATTRIBUTE_DIRECTORY 0x10 #endif @@ -1142,7 +1142,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"); - ret = ARCHIVE_FATAL; + ret = ARCHIVE_FAILED; break; } return (ret); @@ -1513,27 +1513,23 @@ read_header(struct archive_read *a, struct archive_entry *entry, * consumed at the end. */ if (head_type == NEWSUB_HEAD) { - 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"); + "Invalid RAR file: Overlarge extended header"); return (ARCHIVE_FATAL); } - header_size += rar->packed_size; - if ((uintmax_t)header_size > SIZE_MAX) { + if (__archive_read_consume(a, header_size + rar->packed_size - 7) < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Unable to read extended header data"); + "Invalid RAR file: Cannot 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"); - return (ARCHIVE_FATAL); - } - p = h; - endp = p + header_size - 7; - p += distance; + + /* + * NEWSUB records are metadata-only in this reader. The block header + * has already been validated, so it is safe to skip exactly the + * remaining header bytes and the associated data payload. + */ + return ret; } filename_size = archive_le16dec(file_header.name_size); @@ -1829,10 +1825,6 @@ read_header(struct archive_read *a, struct archive_entry *entry, rar->ppmd_valid = rar->ppmd_eod = 0; rar->filters.filterstart = INT64_MAX; - /* Don't set any archive entries for non-file header types */ - if (head_type == NEWSUB_HEAD) - return ret; - archive_entry_set_mtime(entry, rar->mtime, rar->mnsec); archive_entry_set_ctime(entry, rar->ctime, rar->cnsec); archive_entry_set_atime(entry, rar->atime, rar->ansec); @@ -2026,7 +2018,7 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size, #ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "File CRC error"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); #endif } rar->entry_eof = 1; @@ -2038,7 +2030,7 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size, { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated RAR file data"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } *size = bytes_avail; @@ -2058,7 +2050,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, int64_t *offset, size_t looper) { if (looper++ > MAX_COMPRESS_DEPTH) - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); struct rar *rar; int64_t start, end; @@ -2069,7 +2061,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, do { if (!rar->valid) - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); if (rar->filters.bytes_ready > 0) { @@ -2121,7 +2113,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, #ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "File CRC error"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); #endif } rar->entry_eof = 1; @@ -2155,7 +2147,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, if (rar->filters.lastend == rar->filters.filterstart) { if (!run_filters(a)) - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); continue; } @@ -2172,7 +2164,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid symbol"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } if(sym != rar->ppmd_escape) { @@ -2186,7 +2178,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid symbol"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } switch(code) @@ -2213,7 +2205,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid symbol"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } lzss_offset |= code << (i * 8); } @@ -2222,7 +2214,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid symbol"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } lzss_emit_match(rar, lzss_offset + 2, length + 32); rar->bytes_uncopied += length + 32; @@ -2234,7 +2226,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid symbol"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } lzss_emit_match(rar, 1, length + 4); rar->bytes_uncopied += length + 4; @@ -2280,7 +2272,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, * what we would do to solve it. */ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Internal error extracting RAR file"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } } if (rar->bytes_uncopied > (rar->unp_buffer_size - rar->unp_offset)) @@ -2363,7 +2355,7 @@ parse_codes(struct archive_read *a) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated RAR file data"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } /* Make sure ppmd7_context is freed before Ppmd7_Construct @@ -2379,7 +2371,7 @@ parse_codes(struct archive_read *a) if (rar->dictionary_size == 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid zero dictionary size"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } if (!__archive_ppmd7_functions.Ppmd7_Alloc(&rar->ppmd7_context, @@ -2393,7 +2385,7 @@ parse_codes(struct archive_read *a) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Unable to initialize PPMd range decoder"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } __archive_ppmd7_functions.Ppmd7_Init(&rar->ppmd7_context, maxorder); rar->ppmd_valid = 1; @@ -2403,13 +2395,13 @@ parse_codes(struct archive_read *a) if (!rar->ppmd_valid) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid PPMd sequence"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } if (!__archive_ppmd7_functions.PpmdRAR_RangeDec_Init(&rar->range_dec)) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Unable to initialize PPMd range decoder"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } } } @@ -2417,6 +2409,13 @@ parse_codes(struct archive_read *a) { rar_br_consume(br, 1); + /* + * Low-distance repeat state belongs to the current LZ table and + * must not be reused after starting a new table. + */ + rar->lastlowoffset = 0; + rar->numlowoffsetrepeats = 0; + /* Keep existing table flag */ if (!rar_br_read_ahead(a, br, 1)) goto truncated_data; @@ -2459,7 +2458,7 @@ parse_codes(struct archive_read *a) if ((val = read_next_symbol(a, &precode)) < 0) { free(precode.tree); free(precode.table); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } if (val < 16) { @@ -2474,7 +2473,7 @@ parse_codes(struct archive_read *a) free(precode.table); archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Internal error extracting RAR file"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } if(val == 16) { @@ -2564,7 +2563,7 @@ parse_codes(struct archive_read *a) if (new_size == 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Zero window size is invalid"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } new_window = realloc(rar->lzss.window, new_size); if (new_window == NULL) { @@ -2584,7 +2583,7 @@ parse_codes(struct archive_read *a) archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated RAR file data"); rar->valid = 0; - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } static void @@ -2700,7 +2699,7 @@ create_code(struct archive_read *a, struct huffman_code *code, { if (lengths[j] != i) continue; if (add_value(a, code, j, codebits, i) != ARCHIVE_OK) - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); codebits++; if (--symbolsleft <= 0) break; @@ -2752,7 +2751,7 @@ add_value(struct archive_read *a, struct huffman_code *code, int value, { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Prefix found"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } /* @@ -2811,7 +2810,7 @@ add_value(struct archive_read *a, struct huffman_code *code, int value, { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Prefix found"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } /* Set leaf value */ @@ -2850,6 +2849,10 @@ make_table(struct archive_read *a, struct huffman_code *code) code->tablesize = code->maxlength; code->table = calloc(((size_t)1U) << code->tablesize, sizeof(*code->table)); + if (code->table == NULL) { + archive_set_error(&a->archive, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } return make_table_recurse(a, code, 0, code->table, 0, code->tablesize); } @@ -2865,13 +2868,13 @@ make_table_recurse(struct archive_read *a, struct huffman_code *code, int node, { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Huffman tree was not created"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } if (node < 0 || node >= code->numentries) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid location to Huffman tree specified"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } currtablesize = 1 << (maxdepth - depth); @@ -3134,11 +3137,11 @@ expand(struct archive_read *a, int64_t *end) archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated RAR file data"); rar->valid = 0; - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); bad_data: archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Bad RAR file data"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } static int @@ -3153,12 +3156,12 @@ copy_from_lzss_window(struct archive_read *a, uint8_t *buffer, if (length > lzss_size(&rar->lzss)) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Bad RAR file data"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } if (firstpart < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Bad RAR file data"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } if (firstpart < length) { memcpy(buffer, &rar->lzss.window[windowoffs], firstpart); @@ -3200,7 +3203,7 @@ copy_from_lzss_window_to_unp(struct archive_read *a, const void **buffer, if (firstpart < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Bad RAR file data"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } if ((size_t)firstpart < length) { memcpy(&rar->unp_buffer[rar->unp_offset], @@ -3224,7 +3227,7 @@ copy_from_lzss_window_to_unp(struct archive_read *a, const void **buffer, fatal: archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Bad RAR file data"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } static const void * @@ -3556,7 +3559,13 @@ compile_program(const uint8_t *bytes, size_t length) if (membr_bits(&br, 1)) { - prog->staticdatalen = membr_next_rarvm_number(&br) + 1; + uint32_t staticdatalen = membr_next_rarvm_number(&br); + if (staticdatalen >= VM_MEMORY_SIZE) + { + delete_program_code(prog); + return NULL; + } + prog->staticdatalen = staticdatalen + 1; prog->staticdata = malloc(prog->staticdatalen); if (!prog->staticdata) { diff --git a/contrib/libarchive/libarchive/archive_read_support_format_rar5.c b/contrib/libarchive/libarchive/archive_read_support_format_rar5.c index 63dd97b300..cae3391506 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_rar5.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_rar5.c @@ -81,7 +81,9 @@ * * The array itself is decrypted in `rar5_init` function. */ -static unsigned char rar5_signature_xor[] = { 243, 192, 211, 128, 187, 166, 160, 161 }; +static const unsigned char rar5_signature_xor[] = { + 243, 192, 211, 128, 187, 166, 160, 161 +}; static const size_t g_unpack_window_size = 0x20000; /* These could have been static const's, but they aren't, because of @@ -700,7 +702,7 @@ static int run_filter(struct archive_read* a, struct filter_info* flt) { ARCHIVE_ERRNO_FILE_FORMAT, "Unsupported filter type: 0x%x", (unsigned int)flt->type); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } if(ret != ARCHIVE_OK) { @@ -905,11 +907,10 @@ static inline int get_archive_read(struct archive* a, static int read_ahead(struct archive_read* a, size_t how_many, const uint8_t** ptr) { - ssize_t avail = -1; if(!ptr) return 0; - *ptr = __archive_read_ahead(a, how_many, &avail); + *ptr = __archive_read_ahead(a, how_many, NULL); if(*ptr == NULL) { return 0; } @@ -1046,10 +1047,7 @@ static int read_bits_32(struct archive_read* a, struct rar5* rar, return ARCHIVE_FATAL; } - uint32_t bits = ((uint32_t) p[rar->bits.in_addr]) << 24; - bits |= p[rar->bits.in_addr + 1] << 16; - bits |= p[rar->bits.in_addr + 2] << 8; - bits |= p[rar->bits.in_addr + 3]; + uint32_t bits = archive_be32dec(p + rar->bits.in_addr); bits <<= rar->bits.bit_addr; bits |= p[rar->bits.in_addr + 4] >> (8 - rar->bits.bit_addr); *value = bits; @@ -1066,9 +1064,7 @@ static int read_bits_16(struct archive_read* a, struct rar5* rar, return ARCHIVE_FATAL; } - int bits = (int) ((uint32_t) p[rar->bits.in_addr]) << 16; - bits |= (int) p[rar->bits.in_addr + 1] << 8; - bits |= (int) p[rar->bits.in_addr + 2]; + uint32_t bits = archive_be24dec(p + (unsigned)rar->bits.in_addr); bits >>= (8 - rar->bits.bit_addr); *value = bits & 0xffff; return ARCHIVE_OK; @@ -1790,6 +1786,13 @@ static int process_head_file(struct archive_read* a, struct rar5* rar, if(!read_var_sized(a, &data_size, NULL)) return ARCHIVE_EOF; + if(data_size > SSIZE_MAX) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "File data size is too large"); + return ARCHIVE_FATAL; + } + rar->file.bytes_remaining = data_size; } else { rar->file.bytes_remaining = 0; @@ -1946,29 +1949,20 @@ static int process_head_file(struct archive_read* a, struct rar5* rar, archive_entry_set_mode(entry, mode); if (file_attr & (ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM)) { - char *fflags_text, *ptr; - /* allocate for ",rdonly,hidden,system" */ - fflags_text = malloc(22 * sizeof(*fflags_text)); - if (fflags_text != NULL) { - ptr = fflags_text; - if (file_attr & ATTR_READONLY) { - strcpy(ptr, ",rdonly"); - ptr = ptr + 7; - } - if (file_attr & ATTR_HIDDEN) { - strcpy(ptr, ",hidden"); - ptr = ptr + 7; - } - if (file_attr & ATTR_SYSTEM) { - strcpy(ptr, ",system"); - ptr = ptr + 7; - } - if (ptr > fflags_text) { - archive_entry_copy_fflags_text(entry, - fflags_text + 1); - } - free(fflags_text); - } + char buf[sizeof(",rdonly,hidden,system")]; + const char *fflags[3] = { "", "", "" }; + const char **flag = fflags; + + if (file_attr & ATTR_READONLY) + *flag++ = ",rdonly"; + if (file_attr & ATTR_HIDDEN) + *flag++ = ",hidden"; + if (file_attr & ATTR_SYSTEM) + *flag++ = ",system"; + + snprintf(buf, sizeof(buf), "%s%s%s", + fflags[0], fflags[1], fflags[2]); + archive_entry_copy_fflags_text(entry, buf + 1); } } else if(host_os == HOST_UNIX) { /* Host OS is Unix */ @@ -2274,6 +2268,33 @@ static int scan_for_signature(struct archive_read* a); * block. */ +/* + * A header that carries no file data (HEAD_MAIN, or an unknown block + * flagged HFL_SKIP_IF_UNKNOWN) may leave bytes in its body that the + * sub-parser did not read. Skip them before returning ARCHIVE_RETRY, + * otherwise rar5_read_header() re-parses the same block region O(N) + * times instead of O(1), letting a crafted RAR5 file stall the reader + * (GHSA-9h2c-464f-j3hj). + * + * Safe because read_ahead(a, hdr_size, &p) pre-loaded the whole block + * into one contiguous buffer with no compaction until we return, so + * body_start stays valid and (cur - body_start) is the exact number of + * body bytes consumed so far. + */ +static void +rar5_skip_remaining_block(struct archive_read* a, + const uint8_t* body_start, size_t raw_hdr_size) +{ + const uint8_t* cur; + + if(read_ahead(a, 1, &cur)) { + size_t body_used = (size_t)(cur - body_start); + + if(body_used < raw_hdr_size) + (void)consume(a, raw_hdr_size - body_used); + } +} + static int process_base_block(struct archive_read* a, struct archive_entry* entry) { @@ -2285,6 +2306,7 @@ static int process_base_block(struct archive_read* a, size_t header_id = 0; size_t header_flags = 0; const uint8_t* p; + const uint8_t* body_start; int ret; enum HEADER_TYPE { @@ -2346,6 +2368,10 @@ static int process_base_block(struct archive_read* a, #endif } + /* Remember the first byte of the block body so we can later skip + * any bytes the sub-parser leaves unconsumed. */ + body_start = p + hdr_size_len; + /* If the checksum is OK, we proceed with parsing. */ if(ARCHIVE_OK != consume(a, hdr_size_len)) { return ARCHIVE_EOF; @@ -2371,8 +2397,11 @@ static int process_base_block(struct archive_read* a, /* Main header doesn't have any files in it, so it's * pointless to return to the caller. Retry to next * header, which should be HEAD_FILE/HEAD_SERVICE. */ - if(ret == ARCHIVE_OK) + if(ret == ARCHIVE_OK) { + rar5_skip_remaining_block(a, body_start, + raw_hdr_size); return ARCHIVE_RETRY; + } return ret; case HEAD_SERVICE: @@ -2432,6 +2461,8 @@ static int process_base_block(struct archive_read* a, /* If the block is marked as 'skip if unknown', * do as the flag says: skip the block * instead on failing on it. */ + rar5_skip_remaining_block(a, body_start, + raw_hdr_size); return ARCHIVE_RETRY; } } @@ -2561,19 +2592,23 @@ static int rar5_read_header(struct archive_read *a, return ret; } -static void init_unpack(struct rar5* rar) { +static int init_unpack(struct rar5* rar) { rar->file.calculated_crc32 = 0; init_window_mask(rar); free(rar->cstate.window_buf); free(rar->cstate.filtered_buf); + rar->cstate.window_buf = NULL; + rar->cstate.filtered_buf = NULL; + if(rar->cstate.window_size > 0) { rar->cstate.window_buf = calloc(1, rar->cstate.window_size); + if(rar->cstate.window_buf == NULL) + return ARCHIVE_FATAL; rar->cstate.filtered_buf = calloc(1, rar->cstate.window_size); - } else { - rar->cstate.window_buf = NULL; - rar->cstate.filtered_buf = NULL; + if(rar->cstate.filtered_buf == NULL) + return ARCHIVE_FATAL; } clear_data_ready_stack(rar); @@ -2586,6 +2621,7 @@ static void init_unpack(struct rar5* rar) { memset(&rar->cstate.dd, 0, sizeof(rar->cstate.dd)); memset(&rar->cstate.ldd, 0, sizeof(rar->cstate.ldd)); memset(&rar->cstate.rd, 0, sizeof(rar->cstate.rd)); + return ARCHIVE_OK; } static void update_crc(struct rar5* rar, const uint8_t* p, size_t to_read) { @@ -2647,6 +2683,15 @@ static int create_decode_tables(uint8_t* bit_length, upper_limit <<= 1; } + /* Verify the code-length distribution is not over-subscribed. + * After the loop above, upper_limit == sum(lc[i] * 2^(16-i)). + * For a valid prefix-free code this must be <= 2^16 = 65536. + * An over-subscribed table (> 65536) cannot produce a valid + * decode table and must be rejected. */ + if(upper_limit > 65536) { + return ARCHIVE_FAILED; + } + memcpy(decode_pos_clone, table->decode_pos, sizeof(decode_pos_clone)); for(i = 0; i < size; i++) { @@ -2748,7 +2793,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated data in huffman tables"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } value = (p[i] & nibble_mask) >> nibble_shift; @@ -2794,7 +2839,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar, if(ret != ARCHIVE_OK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Decoding huffman tables failed"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } for(i = 0; i < HUFF_TABLE_SIZE;) { @@ -2805,7 +2850,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Decoding huffman tables failed"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } if(num < 16) { @@ -2839,7 +2884,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar, ARCHIVE_ERRNO_FILE_FORMAT, "Unexpected error when decoding " "huffman tables"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } } else { /* other codes: fill with zeroes `n` times */ @@ -2867,7 +2912,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar, if(ret != ARCHIVE_OK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Failed to create literal table"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } idx += HUFF_NC; @@ -2876,7 +2921,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar, if(ret != ARCHIVE_OK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Failed to create distance table"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } idx += HUFF_DC; @@ -2885,7 +2930,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar, if(ret != ARCHIVE_OK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Failed to create lower bits of distances table"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } idx += HUFF_LDC; @@ -2894,7 +2939,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar, if(ret != ARCHIVE_OK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Failed to create repeating distances table"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } return ARCHIVE_OK; @@ -2912,7 +2957,7 @@ static int parse_block_header(struct archive_read* a, const uint8_t* p, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Unsupported block header size (was %d, max is 2)", bf_byte_count(hdr)); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } /* This should probably use bit reader interface in order to be more @@ -2956,7 +3001,7 @@ static int parse_block_header(struct archive_read* a, const uint8_t* p, "Block checksum error: got 0x%x, expected 0x%x", hdr->block_cksum, calculated_cksum); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; #endif } @@ -3037,20 +3082,17 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) { filter_type >>= 13; skip_bits(rar, 3); - /* Perform some sanity checks on this filter parameters. Note that we - * allow only DELTA, E8/E9 and ARM filters here, because rest of - * filters are not used in RARv5. */ + /* Perform some sanity checks on this filter parameters. */ if(block_length < 4 || block_length > 0x400000 || - filter_type > FILTER_ARM || !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"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } /* Allocate a new filter. */ @@ -3203,7 +3245,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) { ARCHIVE_ERRNO_PROGRAMMER, "Failed to decode the code length"); - return ARCHIVE_FATAL; + return rar->main.solid ? ARCHIVE_FATAL : ARCHIVE_FAILED; } if(ARCHIVE_OK != decode_number(a, &rar->cstate.dd, p, @@ -3213,7 +3255,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) { ARCHIVE_ERRNO_PROGRAMMER, "Failed to decode the distance slot"); - return ARCHIVE_FATAL; + return rar->main.solid ? ARCHIVE_FATAL : ARCHIVE_FAILED; } if(dist_slot < 4) { @@ -3258,7 +3300,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) { "Failed to decode the " "distance slot"); - return ARCHIVE_FATAL; + return rar->main.solid ? ARCHIVE_FATAL : ARCHIVE_FAILED; } if(dist >= INT_MAX - low_dist - 1) { @@ -3268,7 +3310,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) { ARCHIVE_ERRNO_FILE_FORMAT, "Distance pointer " "overflow"); - return ARCHIVE_FATAL; + return rar->main.solid ? ARCHIVE_FATAL : ARCHIVE_FAILED; } dist += low_dist; @@ -3303,7 +3345,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) { rar->cstate.last_len = len; if(ARCHIVE_OK != copy_string(a, len, dist)) - return ARCHIVE_FATAL; + return rar->main.solid ? ARCHIVE_FATAL : ARCHIVE_FAILED; continue; } else if(num == 256) { @@ -3319,7 +3361,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) { rar->cstate.last_len, rar->cstate.dist_cache[0])) { - return ARCHIVE_FATAL; + return rar->main.solid ? ARCHIVE_FATAL : ARCHIVE_FAILED; } } @@ -3334,18 +3376,18 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) { if(ARCHIVE_OK != decode_number(a, &rar->cstate.rd, p, &len_slot)) { - return ARCHIVE_FATAL; + return rar->main.solid ? ARCHIVE_FATAL : ARCHIVE_FAILED; } len = decode_code_length(a, rar, p, len_slot); if (len == -1) { - return ARCHIVE_FATAL; + return rar->main.solid ? ARCHIVE_FATAL : ARCHIVE_FAILED; } rar->cstate.last_len = len; if(ARCHIVE_OK != copy_string(a, len, dist)) - return ARCHIVE_FATAL; + return rar->main.solid ? ARCHIVE_FATAL : ARCHIVE_FAILED; continue; } @@ -3507,6 +3549,7 @@ static int merge_block(struct archive_read* a, ssize_t block_size, if(!rar->vol.push_buf) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for a merge block buffer"); + rar->cstate.switch_multivolume = 0; return ARCHIVE_FATAL; } @@ -3524,15 +3567,21 @@ static int merge_block(struct archive_read* a, ssize_t block_size, cur_block_size = rar5_min(rar->file.bytes_remaining, block_size - partial_offset); - if(cur_block_size == 0) { + if(cur_block_size < 1) { + /* bytes_remaining is less than 1 at the wrong point in + * the merge loop, indicating corrupt volume + * accounting. */ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Encountered block size == 0 during block merge"); + "Encountered invalid block size during block merge"); + rar->cstate.switch_multivolume = 0; return ARCHIVE_FATAL; } - if(!read_ahead(a, cur_block_size, &lp)) + if(!read_ahead(a, cur_block_size, &lp)) { + rar->cstate.switch_multivolume = 0; return ARCHIVE_EOF; + } /* Sanity check; there should never be a situation where this * function reads more data than the block's size. */ @@ -3540,6 +3589,7 @@ static int merge_block(struct archive_read* a, ssize_t block_size, archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, "Consumed too much data when merging blocks"); + rar->cstate.switch_multivolume = 0; return ARCHIVE_FATAL; } @@ -3549,8 +3599,12 @@ static int merge_block(struct archive_read* a, ssize_t block_size, memcpy(&rar->vol.push_buf[partial_offset], lp, cur_block_size); /* Advance the stream read pointer by this block chunk size. */ - if(ARCHIVE_OK != consume(a, cur_block_size)) - return ARCHIVE_EOF; + if(ARCHIVE_OK != consume(a, cur_block_size)) { + /* Data was copied but stream pointer didn't advance; + * stream position is unrecoverable. */ + rar->cstate.switch_multivolume = 0; + return ARCHIVE_FATAL; + } /* Update the pointers. `partial_offset` contains information * about the sum of merged block chunks. */ @@ -3571,6 +3625,7 @@ static int merge_block(struct archive_read* a, ssize_t block_size, ret = advance_multivolume(a); rar->merge_mode--; if(ret != ARCHIVE_OK) { + rar->cstate.switch_multivolume = 0; return ret; } } @@ -3627,6 +3682,15 @@ static int process_block(struct archive_read* a) { to_skip = sizeof(struct compressed_block_header) + bf_byte_count(&rar->last_block_hdr) + 1; + /* If the block header's to_skip value exceeds the declared + * remaining data, the archive is malformed. */ + if(to_skip > rar->file.bytes_remaining) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Block header size exceeds remaining file data"); + return ARCHIVE_FATAL; + } + if(ARCHIVE_OK != consume(a, to_skip)) return ARCHIVE_EOF; @@ -3863,7 +3927,8 @@ static int do_uncompress_file(struct archive_read* a) { /* Don't perform full context reinitialization if we're * processing a solid archive. */ if(!rar->main.solid || !rar->cstate.window_buf) { - init_unpack(rar); + if((ret = init_unpack(rar)) != ARCHIVE_OK) + return ret; } rar->cstate.initialized = 1; @@ -3876,7 +3941,7 @@ static int do_uncompress_file(struct archive_read* a) { "Invalid window size declaration in this file"); /* This should never happen in valid files. */ - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } if(rar->cstate.all_filters_applied == 1) { @@ -3887,7 +3952,7 @@ static int do_uncompress_file(struct archive_read* a) { * files). */ while(1) { ret = process_block(a); - if(ret == ARCHIVE_EOF || ret == ARCHIVE_FATAL) + if(ret != ARCHIVE_OK) return ret; if(rar->cstate.last_write_ptr == @@ -3913,12 +3978,10 @@ static int do_uncompress_file(struct archive_read* a) { ret = apply_filters(a); if(ret == ARCHIVE_RETRY) { return ARCHIVE_OK; - } else if(ret == ARCHIVE_FATAL) { - return ARCHIVE_FATAL; + } else if(ret != ARCHIVE_OK) { + return ret; } - /* If apply_filters() will return ARCHIVE_OK, we can continue here. */ - if(cdeque_size(&rar->cstate.filters) > 0) { /* Check if we can write something before hitting first * filter. */ @@ -4131,7 +4194,7 @@ static int verify_checksums(struct archive_read* a) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Checksum error: CRC32"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; #endif } else { DEBUG_CODE { @@ -4166,7 +4229,7 @@ static int verify_checksums(struct archive_read* a) { ARCHIVE_ERRNO_FILE_FORMAT, "Checksum error: BLAKE2"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; #endif } } @@ -4207,7 +4270,7 @@ static int rar5_read_data(struct archive_read *a, const void **buff, if (rar->headers_are_encrypted || rar->cstate.data_encrypted) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Reading encrypted data is not currently supported"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } if(rar->file.dir > 0) { diff --git a/contrib/libarchive/libarchive/archive_read_support_format_tar.c b/contrib/libarchive/libarchive/archive_read_support_format_tar.c index 2979492767..ac3dd446cb 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_tar.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_tar.c @@ -42,6 +42,7 @@ #include "archive_acl_private.h" /* For ACL parsing routines. */ #include "archive_entry.h" #include "archive_entry_locale.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_read_private.h" @@ -153,6 +154,8 @@ struct tar { int compat_2x; int process_mac_extensions; int read_concatenated_archives; + int default_inode; + int default_dev; }; /* Track which size fields were present in the headers */ @@ -248,6 +251,36 @@ static const size_t fflags_limit = 512; /* Longest fflags */ static const size_t acl_limit = 131072; /* Longest textual ACL: 128kiB */ static const int64_t entry_limit = 0xfffffffffffffffLL; /* 2^60 bytes = 1 ExbiByte */ +/* + * There's no standard for TIME_T_MAX. So we compute it + * here. TODO: Move this to configure time, but be careful + * about cross-compile environments. + */ +static time_t +get_time_t_max(void) +{ +#if defined(TIME_T_MAX) + return TIME_T_MAX; +#else + /* ISO C allows time_t to be a floating-point type, + but POSIX requires an integer type. The following + should work on any system that follows the POSIX + conventions. */ + if (((time_t)0) < ((time_t)-1)) { + /* Time_t is unsigned */ + return (~(time_t)0); + } else { + /* Time_t is signed. */ + /* Assume it's the same as int64_t or int32_t */ + if (sizeof(time_t) == sizeof(int64_t)) { + return (time_t)INT64_MAX; + } else { + return (time_t)INT32_MAX; + } + } +#endif +} + int archive_read_support_format_gnutar(struct archive *a) { @@ -522,10 +555,6 @@ archive_read_format_tar_read_header(struct archive_read *a, * probably not worthwhile just to support the relatively * obscure tar->cpio conversion case. */ - /* TODO: Move this into `struct tar` to avoid conflicts - * when reading multiple archives */ - static int default_inode; - static int default_dev; struct tar *tar; const char *p; const wchar_t *wp; @@ -533,16 +562,17 @@ archive_read_format_tar_read_header(struct archive_read *a, size_t l; int64_t unconsumed = 0; + tar = (struct tar *)(a->format->data); + /* Assign default device/inode values. */ - archive_entry_set_dev(entry, 1 + default_dev); /* Don't use zero. */ - archive_entry_set_ino(entry, ++default_inode); /* Don't use zero. */ + archive_entry_set_dev(entry, 1 + tar->default_dev); /* Don't use zero. */ + archive_entry_set_ino(entry, ++tar->default_inode); /* Don't use zero. */ /* Limit generated st_ino number to 16 bits. */ - if (default_inode >= 0xffff) { - ++default_dev; - default_inode = 0; + if (tar->default_inode >= 0xffff) { + ++tar->default_dev; + tar->default_inode = 0; } - tar = (struct tar *)(a->format->data); tar->entry_offset = 0; gnu_clear_sparse_list(tar); tar->size_fields = 0; /* We don't have any size info yet */ @@ -586,16 +616,16 @@ archive_read_format_tar_read_header(struct archive_read *a, * directory: This is needed for certain old tar * variants and even for some broken newer ones. */ - if ((wp = archive_entry_pathname_w(entry)) != NULL) { - l = wcslen(wp); - if (l > 0 && wp[l - 1] == L'/') { + if ((p = archive_entry_pathname(entry)) != NULL) { + l = strlen(p); + if (l > 0 && p[l - 1] == '/') { archive_entry_set_filetype(entry, AE_IFDIR); tar->entry_bytes_remaining = 0; tar->entry_padding = 0; } - } else if ((p = archive_entry_pathname(entry)) != NULL) { - l = strlen(p); - if (l > 0 && p[l - 1] == '/') { + } else if ((wp = archive_entry_pathname_w(entry)) != NULL) { + l = wcslen(wp); + if (l > 0 && wp[l - 1] == L'/') { archive_entry_set_filetype(entry, AE_IFDIR); tar->entry_bytes_remaining = 0; tar->entry_padding = 0; @@ -1369,7 +1399,12 @@ header_common(struct archive_read *a, struct tar *tar, archive_entry_set_gid(entry, tar_atol(header->gid, sizeof(header->gid))); } if (!archive_entry_mtime_is_set(entry)) { - archive_entry_set_mtime(entry, tar_atol(header->mtime, sizeof(header->mtime)), 0); + int64_t t64 = tar_atol(header->mtime, sizeof(header->mtime)); + time_t t = (time_t)t64; + if ((int64_t)t != t64) { /* time_t overflowed */ + t = get_time_t_max(); + } + archive_entry_set_mtime(entry, t, 0); } /* Reconcile the size info. */ @@ -1782,32 +1817,42 @@ header_ustar(struct archive_read *a, struct tar *tar, struct archive_entry *entry, const void *h) { const struct archive_entry_header_ustar *header; - struct archive_string as; int err = ARCHIVE_OK, r; header = (const struct archive_entry_header_ustar *)h; - /* Copy name into an internal buffer to ensure null-termination. */ + /* + * The name field is fixed-width and may not be NUL-terminated. + * Use a temporary string only when prefix/name joining is required. + */ const char *existing_pathname = archive_entry_pathname(entry); const wchar_t *existing_wcs_pathname = archive_entry_pathname_w(entry); if ((existing_pathname == NULL || existing_pathname[0] == '\0') && (existing_wcs_pathname == NULL || existing_wcs_pathname[0] == '\0')) { + struct archive_string as; + const char *pathname; + size_t pathname_length; + archive_string_init(&as); if (header->prefix[0]) { archive_strncpy(&as, header->prefix, sizeof(header->prefix)); if (as.s[archive_strlen(&as) - 1] != '/') archive_strappend_char(&as, '/'); archive_strncat(&as, header->name, sizeof(header->name)); + pathname = as.s; + pathname_length = archive_strlen(&as); } else { - archive_strncpy(&as, header->name, sizeof(header->name)); + pathname = header->name; + pathname_length = sizeof(header->name); } - if (archive_entry_copy_pathname_l(entry, as.s, archive_strlen(&as), - tar->sconv) != 0) { + r = archive_entry_copy_pathname_l(entry, pathname, + pathname_length, tar->sconv); + archive_string_free(&as); + if (r != 0) { err = set_conversion_failed_error(a, tar->sconv, "Pathname"); if (err == ARCHIVE_FATAL) return (err); } - archive_string_free(&as); } /* Handle rest of common fields. */ @@ -2009,6 +2054,7 @@ header_pax_extension(struct archive_read *a, struct tar *tar, /* Consume size, name, and `=` */ *unconsumed += p - attr_start; if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) { + archive_string_free(&attr_name); return (ARCHIVE_FATAL); } @@ -2016,6 +2062,7 @@ header_pax_extension(struct archive_read *a, struct tar *tar, archive_set_error(&a->archive, EINVAL, "Malformed pax attributes"); *unconsumed += ext_size + ext_padding; + archive_string_free(&attr_name); return (ARCHIVE_WARN); } @@ -2266,7 +2313,7 @@ pax_attribute_SCHILY_acl(struct archive_read *a, struct tar *tar, } static int -pax_attribute_read_time(struct archive_read *a, size_t value_length, int64_t *ps, long *pn, int64_t *unconsumed) { +pax_attribute_read_time(struct archive_read *a, size_t value_length, __LA_TIME_T *ps, long *pn, int64_t *unconsumed) { struct archive_string as; int r; @@ -2286,12 +2333,16 @@ pax_attribute_read_time(struct archive_read *a, size_t value_length, int64_t *ps return (r); } - pax_time(as.s, archive_strlen(&as), ps, pn); + int64_t sec = 0; + pax_time(as.s, archive_strlen(&as), &sec, pn); archive_string_free(&as); - if (*ps == INT64_MIN) { + + if (sec == INT64_MIN) { *ps = 0; *pn = 0; return (ARCHIVE_WARN); + } else { + *ps = (__LA_TIME_T)sec; } return (ARCHIVE_OK); } @@ -2348,7 +2399,6 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent int64_t t; long n; const char *p; - ssize_t bytes_read; int err = ARCHIVE_OK; switch (key[0]) { @@ -2432,7 +2482,7 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent (unsigned long long)sparse_map_limit); err = ARCHIVE_FAILED; } else { - p = __archive_read_ahead(a, value_length, &bytes_read); + p = __archive_read_ahead(a, value_length, NULL); if (p == NULL) { archive_set_error(&a->archive, EINVAL, "Truncated archive" @@ -2507,15 +2557,20 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent */ if (key_length == 12 && memcmp(key, "creationtime", 12) == 0) { /* LIBARCHIVE.creationtime */ - if ((err = pax_attribute_read_time(a, value_length, &t, &n, unconsumed)) == ARCHIVE_OK) { - archive_entry_set_birthtime(entry, t, n); + __LA_TIME_T sec = 0; + if ((err = pax_attribute_read_time(a, value_length, &sec, &n, unconsumed)) == ARCHIVE_OK) { + archive_entry_set_birthtime(entry, sec, n); + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Ignoring malformed pax creationtime"); } return (err); } else if (key_length == 11 && memcmp(key, "symlinktype", 11) == 0) { /* LIBARCHIVE.symlinktype */ if (value_length < 16) { - p = __archive_read_ahead(a, value_length, &bytes_read); + p = __archive_read_ahead(a, value_length, NULL); if (p == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated tar archive " @@ -2549,7 +2604,7 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent if (value_length > xattr_limit) { err = ARCHIVE_WARN; } else { - p = __archive_read_ahead(a, value_length, &bytes_read); + p = __archive_read_ahead(a, value_length, NULL); if (p == NULL) { archive_set_error(&a->archive, EINVAL, "Truncated archive" @@ -2579,7 +2634,7 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent /* TODO: Should this be FAILED instead? */ err = ARCHIVE_WARN; } else { - p = __archive_read_ahead(a, value_length, &bytes_read); + p = __archive_read_ahead(a, value_length, NULL); if (p == NULL) { archive_set_error(&a->archive, EINVAL, "Truncated archive" @@ -2632,7 +2687,7 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent } else if (key_length == 6 && memcmp(key, "fflags", 6) == 0) { if (value_length < fflags_limit) { - p = __archive_read_ahead(a, value_length, &bytes_read); + p = __archive_read_ahead(a, value_length, NULL); if (p == NULL) { /* Truncated archive */ archive_set_error(&a->archive, EINVAL, @@ -2679,7 +2734,7 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent key_length -= 6; key += 6; if (value_length < xattr_limit) { - p = __archive_read_ahead(a, value_length, &bytes_read); + p = __archive_read_ahead(a, value_length, NULL); if (p == NULL) { archive_set_error(&a->archive, EINVAL, "Truncated archive" @@ -2709,7 +2764,7 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent if (key_length == 9 && memcmp(key, "holesdata", 9) == 0) { /* SUN.holesdata */ if (value_length < sparse_map_limit) { - p = __archive_read_ahead(a, value_length, &bytes_read); + p = __archive_read_ahead(a, value_length, NULL); if (p == NULL) { archive_set_error(&a->archive, EINVAL, "Truncated archive" @@ -2736,16 +2791,26 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent break; case 'a': if (key_length == 5 && memcmp(key, "atime", 5) == 0) { - if ((err = pax_attribute_read_time(a, value_length, &t, &n, unconsumed)) == ARCHIVE_OK) { - archive_entry_set_atime(entry, t, n); + __LA_TIME_T sec = 0; + if ((err = pax_attribute_read_time(a, value_length, &sec, &n, unconsumed)) == ARCHIVE_OK) { + archive_entry_set_atime(entry, sec, n); + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Ignoring malformed pax atime"); } return (err); } break; case 'c': if (key_length == 5 && memcmp(key, "ctime", 5) == 0) { - if ((err = pax_attribute_read_time(a, value_length, &t, &n, unconsumed)) == ARCHIVE_OK) { - archive_entry_set_ctime(entry, t, n); + __LA_TIME_T sec = 0; + if ((err = pax_attribute_read_time(a, value_length, &sec, &n, unconsumed)) == ARCHIVE_OK) { + archive_entry_set_ctime(entry, sec, n); + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Ignoring malformed pax ctime"); } return (err); } else if (key_length == 7 && memcmp(key, "charset", 7) == 0) { @@ -2773,7 +2838,7 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent case 'h': if (key_length == 10 && memcmp(key, "hdrcharset", 10) == 0) { if (value_length < 64) { - p = __archive_read_ahead(a, value_length, &bytes_read); + p = __archive_read_ahead(a, value_length, NULL); if (p == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated tar archive " @@ -2817,8 +2882,13 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent break; case 'm': if (key_length == 5 && memcmp(key, "mtime", 5) == 0) { - if ((err = pax_attribute_read_time(a, value_length, &t, &n, unconsumed)) == ARCHIVE_OK) { - archive_entry_set_mtime(entry, t, n); + __LA_TIME_T sec; + if ((err = pax_attribute_read_time(a, value_length, &sec, &n, unconsumed)) == ARCHIVE_OK) { + archive_entry_set_mtime(entry, sec, n); + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Ignoring malformed pax mtime"); } return (err); } @@ -2885,7 +2955,8 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent /* * Parse a decimal time value, which may include a fractional portion * - * Sets ps to INT64_MIN on error. + * Sets ps to INT64_MIN on error, including syntax issues such as non-digits, + * or a time value that's outside the range of time_t. */ static void pax_time(const char *p, size_t length, int64_t *ps, long *pn) @@ -2894,10 +2965,6 @@ pax_time(const char *p, size_t length, int64_t *ps, long *pn) int64_t s; unsigned long l; int sign; - int64_t limit, last_digit_limit; - - limit = INT64_MAX / 10; - last_digit_limit = INT64_MAX % 10; if (length <= 0) { *ps = 0; @@ -2913,34 +2980,73 @@ pax_time(const char *p, size_t length, int64_t *ps, long *pn) } while (length > 0 && *p >= '0' && *p <= '9') { digit = *p - '0'; - if (s > limit || - (s == limit && digit > last_digit_limit)) { + if (archive_ckd_mul_i64(&s, s, 10) || + archive_ckd_add_i64(&s, s, digit)) { *ps = INT64_MIN; *pn = 0; return; } - s = (s * 10) + digit; ++p; --length; } *ps = s * sign; +#if ARCHIVE_VERSION_NUMBER < 4000000 + /* Libarchive 4.0 will have __LA_TIME_T == int64_t, so + this will be unnecessary. */ + /* Test whether it overflows __LA_TIME_T */ + __LA_TIME_T sec = (__LA_TIME_T)*ps; + if ((int64_t)sec != *ps) { + *ps = INT64_MIN; + *pn = 0; + return; + } +#endif + /* Calculate nanoseconds. */ *pn = 0; - if (length <= 0 || *p != '.') + if (length <= 0) { return; + } + + /* Skip `.` */ + if (*p != '.') { + *ps = INT64_MIN; + *pn = 0; + return; + } + ++p; + --length; l = 100000000UL; do { + if (length <= 0) { + return; + } + if (*p >= '0' && *p <= '9') { + *pn += (*p - '0') * l; + } else { + *ps = INT64_MIN; + *pn = 0; + return; + } ++p; --length; - if (length > 0 && *p >= '0' && *p <= '9') - *pn += (*p - '0') * l; - else - break; } while (l /= 10); + + /* Ignore resolution beyond nanoseconds, + but verify it's all decimal digits. */ + while (length > 0) { + if (*p < '0' || *p > '9') { + *ps = INT64_MIN; + *pn = 0; + return; + } + ++p; + --length; + } } /* @@ -3103,7 +3209,6 @@ static int gnu_sparse_old_read(struct archive_read *a, struct tar *tar, const struct archive_entry_header_gnutar *header, int64_t *unconsumed) { - ssize_t bytes_read; const void *data; struct extended { struct gnu_sparse sparse[21]; @@ -3121,7 +3226,7 @@ gnu_sparse_old_read(struct archive_read *a, struct tar *tar, if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) { return (ARCHIVE_FATAL); } - data = __archive_read_ahead(a, 512, &bytes_read); + data = __archive_read_ahead(a, 512, NULL); if (data == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated tar archive " @@ -3239,14 +3344,12 @@ static int64_t gnu_sparse_10_atol(struct archive_read *a, struct tar *tar, int64_t *remaining, int64_t *unconsumed) { - int64_t l, limit, last_digit_limit; + int64_t l; const char *p; ssize_t bytes_read; int base, digit; base = 10; - limit = INT64_MAX / base; - last_digit_limit = INT64_MAX % base; /* * Skip any lines starting with '#'; GNU tar specs @@ -3267,10 +3370,10 @@ gnu_sparse_10_atol(struct archive_read *a, struct tar *tar, if (*p < '0' || *p >= '0' + base) return (ARCHIVE_WARN); digit = *p - '0'; - if (l > limit || (l == limit && digit > last_digit_limit)) + if (archive_ckd_mul_i64(&l, l, base) || + archive_ckd_add_i64(&l, l, digit)) { l = INT64_MAX; /* Truncate on overflow. */ - else - l = (l * base) + digit; + } p++; bytes_read--; } @@ -3416,13 +3519,9 @@ tar_atol(const char *p, size_t char_cnt) static int64_t tar_atol_base_n(const char *p, size_t char_cnt, int base) { - int64_t l, maxval, limit, last_digit_limit; + int64_t l; int digit, sign; - maxval = INT64_MAX; - limit = INT64_MAX / base; - last_digit_limit = INT64_MAX % base; - /* the pointer will not be dereferenced if char_cnt is zero * due to the way the && operator is evaluated. */ @@ -3436,25 +3535,22 @@ tar_atol_base_n(const char *p, size_t char_cnt, int base) sign = -1; p++; char_cnt--; - - maxval = INT64_MIN; - limit = -(INT64_MIN / base); - last_digit_limit = -(INT64_MIN % base); } l = 0; if (char_cnt != 0) { digit = *p - '0'; - while (digit >= 0 && digit < base && char_cnt != 0) { - if (l>limit || (l == limit && digit >= last_digit_limit)) { - return maxval; /* Truncate on overflow. */ + while (digit >= 0 && digit < base && char_cnt != 0) { + if (archive_ckd_mul_i64(&l, l, base) || + archive_ckd_add_i64(&l, l, sign * digit)) { + /* Truncate on overflow. */ + return sign < 0 ? INT64_MIN : INT64_MAX; } - l = (l * base) + digit; digit = *++p - '0'; char_cnt--; } } - return (sign < 0) ? -l : l; + return l; } static int64_t @@ -3534,9 +3630,8 @@ readline(struct archive_read *a, struct tar *tar, const char **start, { ssize_t bytes_read; ssize_t total_size = 0; - const void *t; + const void *p, *t; const char *s; - void *p; if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) { return (ARCHIVE_FATAL); @@ -3608,24 +3703,20 @@ readline(struct archive_read *a, struct tar *tar, const char **start, static char * base64_decode(const char *s, size_t len, size_t *out_len) { - static const unsigned char digits[64] = { - 'A','B','C','D','E','F','G','H','I','J','K','L','M','N', - 'O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b', - 'c','d','e','f','g','h','i','j','k','l','m','n','o','p', - 'q','r','s','t','u','v','w','x','y','z','0','1','2','3', - '4','5','6','7','8','9','+','/' }; - static unsigned char decode_table[128]; + static const unsigned char decode_table[128] = { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, + 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, + 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 255, 255, 255, 255, 255 }; char *out, *d; const unsigned char *src = (const unsigned char *)s; - /* If the decode table is not yet initialized, prepare it. */ - if (decode_table[digits[1]] != 1) { - unsigned i; - memset(decode_table, 0xff, sizeof(decode_table)); - for (i = 0; i < sizeof(digits); i++) - decode_table[digits[i]] = i; - } - /* Allocate enough space to hold the entire output. */ /* Note that we may not use all of this... */ out = malloc(len - len / 4 + 1); diff --git a/contrib/libarchive/libarchive/archive_read_support_format_xar.c b/contrib/libarchive/libarchive/archive_read_support_format_xar.c index 874501fc07..e61ca0e642 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_xar.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_xar.c @@ -56,6 +56,7 @@ #include "archive_endian.h" #include "archive_entry.h" #include "archive_entry_locale.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_read_private.h" @@ -387,8 +388,7 @@ static int rd_contents_init(struct archive_read *, enum enctype, int, int); static int rd_contents(struct archive_read *, const void **, size_t *, size_t *, uint64_t); -static uint64_t atol10(const char *, size_t); -static int64_t atol8(const char *, size_t); +static int atou64(const char *, size_t, int, uint64_t *); static size_t atohex(unsigned char *, size_t, const char *, size_t); static time_t parse_time(const char *p, size_t n); static int heap_add_entry(struct archive_read *a, @@ -421,7 +421,7 @@ static void unknowntag_end(struct xar *, const char *); static int xml_start(struct archive_read *, const char *, struct xmlattr_list *); static void xml_end(void *, const char *); -static void xml_data(void *, const char *, size_t); +static int xml_data(void *, const char *, size_t); static int xml_parse_file_flags(struct xar *, const char *); static int xml_parse_file_ext2(struct xar *, const char *); #if defined(HAVE_LIBXML_XMLREADER_H) @@ -1071,44 +1071,26 @@ rd_contents(struct archive_read *a, const void **buff, size_t *size, * it does obey locale. */ -static uint64_t -atol10(const char *p, size_t char_cnt) +static int +atou64(const char *p, size_t char_cnt, int base, uint64_t *val) { uint64_t l; - int digit; - - if (char_cnt == 0) - return (0); l = 0; - digit = *p - '0'; - while (digit >= 0 && digit < 10 && char_cnt-- > 0) { - l = (l * 10) + digit; - digit = *++p - '0'; - } - return (l); -} + if (char_cnt > 0) { + int digit; -static int64_t -atol8(const char *p, size_t char_cnt) -{ - int64_t l; - int digit; - - if (char_cnt == 0) - return (0); - - l = 0; - while (char_cnt-- > 0) { - if (*p >= '0' && *p <= '7') - digit = *p - '0'; - else - break; - p++; - l <<= 3; - l |= digit; + digit = *p - '0'; + while (digit >= 0 && digit < base && char_cnt-- > 0) { + if (archive_ckd_mul_u64(&l, l, base) || + archive_ckd_add_u64(&l, l, digit)) + return (ARCHIVE_FATAL); + digit = *++p - '0'; + } } - return (l); + + *val = l; + return (ARCHIVE_OK); } static size_t @@ -1173,48 +1155,42 @@ parse_time(const char *p, size_t n) { struct tm tm; time_t t = 0; - int64_t data; + uint64_t data; memset(&tm, 0, sizeof(tm)); if (n != 20) return (t); - data = atol10(p, 4); - if (data < 1900) + if (atou64(p, 4, 10, &data) != ARCHIVE_OK || data < 1900) return (t); tm.tm_year = (int)data - 1900; p += 4; if (*p++ != '-') return (t); - data = atol10(p, 2); - if (data < 1 || data > 12) + if (atou64(p, 4, 10, &data) != ARCHIVE_OK || data < 1 || data > 12) return (t); tm.tm_mon = (int)data -1; p += 2; if (*p++ != '-') return (t); - data = atol10(p, 2); - if (data < 1 || data > 31) + if (atou64(p, 4, 10, &data) != ARCHIVE_OK || data < 1 || data > 31) return (t); tm.tm_mday = (int)data; p += 2; if (*p++ != 'T') return (t); - data = atol10(p, 2); - if (data < 0 || data > 23) + if (atou64(p, 4, 10, &data) != ARCHIVE_OK || data > 23) return (t); tm.tm_hour = (int)data; p += 2; if (*p++ != ':') return (t); - data = atol10(p, 2); - if (data < 0 || data > 59) + if (atou64(p, 4, 10, &data) != ARCHIVE_OK || data > 59) return (t); tm.tm_min = (int)data; p += 2; if (*p++ != ':') return (t); - data = atol10(p, 2); - if (data < 0 || data > 60) + if (atou64(p, 4, 10, &data) != ARCHIVE_OK || data > 60) return (t); tm.tm_sec = (int)data; #if 0 @@ -1800,12 +1776,20 @@ file_new(struct archive_read *a, struct xar *xar, struct xmlattr_list *list) file->mode = 0777 | AE_IFREG; file->atime = 0; file->mtime = 0; - xar->file = file; xar->xattr = NULL; for (attr = list->first; attr != NULL; attr = attr->next) { - if (strcmp(attr->name, "id") == 0) - file->id = atol10(attr->value, strlen(attr->value)); + if (strcmp(attr->name, "id") == 0) { + int r; + + r = atou64(attr->value, strlen(attr->value), + 10, &file->id); + if (r != ARCHIVE_OK) { + free(file); + return (r); + } + } } + xar->file = file; file->nlink = 1; if (heap_add_entry(a, &(xar->file_queue), file) != ARCHIVE_OK) return (ARCHIVE_FATAL); @@ -1822,6 +1806,7 @@ file_free(struct xar_file *file) archive_string_free(&(file->uname)); archive_string_free(&(file->gname)); archive_string_free(&(file->hardlink)); + archive_string_free(&(file->fflags_text)); xattr = file->xattr_list; while (xattr != NULL) { struct xattr *next; @@ -1845,11 +1830,19 @@ xattr_new(struct archive_read *a, struct xar *xar, struct xmlattr_list *list) archive_set_error(&a->archive, ENOMEM, "Out of memory"); return (ARCHIVE_FATAL); } - xar->xattr = xattr; for (attr = list->first; attr != NULL; attr = attr->next) { - if (strcmp(attr->name, "id") == 0) - xattr->id = atol10(attr->value, strlen(attr->value)); + if (strcmp(attr->name, "id") == 0) { + int r; + + r = atou64(attr->value, strlen(attr->value), + 10, &xattr->id); + if (r != ARCHIVE_OK) { + free(xattr); + return (r); + } + } } + xar->xattr = xattr; /* Chain to xattr list. */ for (nx = &(xar->file->xattr_list); *nx != NULL; nx = &((*nx)->next)) { @@ -1866,6 +1859,7 @@ static void xattr_free(struct xattr *xattr) { archive_string_free(&(xattr->name)); + archive_string_free(&(xattr->fstype)); free(xattr); } @@ -2065,8 +2059,17 @@ xml_start(struct archive_read *a, const char *name, struct xmlattr_list *list) xar->file->hdnext = xar->hdlink_orgs; xar->hdlink_orgs = xar->file; } else { - xar->file->link = (unsigned)atol10(attr->value, - strlen(attr->value)); + uint64_t val; + int r; + r = atou64(attr->value, + strlen(attr->value), 10, &val); + if (r != ARCHIVE_OK) { + return (r); + } + if (val > UINT_MAX) { + return (ARCHIVE_FATAL); + } + xar->file->link = (unsigned)val; if (xar->file->link > 0) if (add_link(a, xar, xar->file) != ARCHIVE_OK) { return (ARCHIVE_FATAL); @@ -2673,11 +2676,13 @@ is_string(const char *known, const char *data, size_t len) return memcmp(data, known, len); } -static void +static int xml_data(void *userData, const char *s, size_t len) { + uint64_t val; struct archive_read *a; struct xar *xar; + int r; a = (struct archive_read *)userData; xar = (struct xar *)(a->format->data); @@ -2685,25 +2690,30 @@ xml_data(void *userData, const char *s, size_t len) #if DEBUG { char buff[1024]; - if (len > (int)(sizeof(buff)-1)) - len = (int)(sizeof(buff)-1); - strncpy(buff, s, len); - buff[len] = 0; - fprintf(stderr, "\tlen=%d:\"%s\"\n", len, buff); + size_t dlen = len; + if (dlen > sizeof(buff) - 1) + dlen = sizeof(buff) - 1; + strncpy(buff, s, dlen); + buff[dlen] = 0; + fprintf(stderr, "\tlen=%zu:\"%s\"\n", dlen, buff); } #endif switch (xar->xmlsts) { case TOC_CHECKSUM_OFFSET: - xar->toc_chksum_offset = atol10(s, len); + r = atou64(s, len, 10, &xar->toc_chksum_offset); + if (r != ARCHIVE_OK) + return (r); break; case TOC_CHECKSUM_SIZE: - xar->toc_chksum_size = atol10(s, len); + r = atou64(s, len, 10, &xar->toc_chksum_size); + if (r != ARCHIVE_OK) + return (r); break; default: break; } if (xar->file == NULL) - return; + return (ARCHIVE_OK); switch (xar->xmlsts) { case FILE_NAME: @@ -2752,42 +2762,76 @@ xml_data(void *userData, const char *s, size_t len) xar->file->has |= HAS_TYPE; break; case FILE_INODE: + r = atou64(s, len, 10, &val); + if (r != ARCHIVE_OK) + return (r); + if (val > (uint64_t)INT64_MAX) + return (ARCHIVE_FATAL); xar->file->has |= HAS_INO; - xar->file->ino64 = atol10(s, len); + xar->file->ino64 = (int64_t)val; break; case FILE_DEVICE_MAJOR: + r = atou64(s, len, 10, &val); + if (r != ARCHIVE_OK) + return (r); + if (val != (dev_t)val) + return (ARCHIVE_FATAL); xar->file->has |= HAS_DEVMAJOR; - xar->file->devmajor = (dev_t)atol10(s, len); + xar->file->devmajor = (dev_t)val; break; case FILE_DEVICE_MINOR: + r = atou64(s, len, 10, &val); + if (r != ARCHIVE_OK) + return (r); + if (val != (dev_t)val) + return (ARCHIVE_FATAL); xar->file->has |= HAS_DEVMINOR; - xar->file->devminor = (dev_t)atol10(s, len); + xar->file->devminor = (dev_t)val; break; case FILE_DEVICENO: + r = atou64(s, len, 10, &val); + if (r != ARCHIVE_OK) + return (r); + if (val != (dev_t)val) + return (ARCHIVE_FATAL); xar->file->has |= HAS_DEV; - xar->file->dev = (dev_t)atol10(s, len); + xar->file->dev = (dev_t)val; break; case FILE_MODE: + r = atou64(s, len, 8, &val); + if (r != ARCHIVE_OK) + return (r); + if (val != (mode_t)val) + return (ARCHIVE_FATAL); xar->file->has |= HAS_MODE; xar->file->mode = - (xar->file->mode & AE_IFMT) | - ((mode_t)(atol8(s, len)) & ~AE_IFMT); + (xar->file->mode & AE_IFMT) | ((mode_t)val & ~AE_IFMT); break; case FILE_GROUP: xar->file->has |= HAS_GID; archive_strncpy(&(xar->file->gname), s, len); break; case FILE_GID: + r = atou64(s, len, 10, &val); + if (r != ARCHIVE_OK) + return (r); + if (val > (uint64_t)INT64_MAX) + return (ARCHIVE_FATAL); xar->file->has |= HAS_GID; - xar->file->gid = atol10(s, len); + xar->file->gid = (int64_t)val; break; case FILE_USER: xar->file->has |= HAS_UID; archive_strncpy(&(xar->file->uname), s, len); break; case FILE_UID: + r = atou64(s, len, 10, &val); + if (r != ARCHIVE_OK) + return (r); + if (val > (uint64_t)INT64_MAX) + return (ARCHIVE_FATAL); xar->file->has |= HAS_UID; - xar->file->uid = atol10(s, len); + xar->file->uid = (int64_t)val; break; case FILE_CTIME: xar->file->has |= HAS_TIME | HAS_CTIME; @@ -2802,16 +2846,22 @@ xml_data(void *userData, const char *s, size_t len) xar->file->atime = parse_time(s, len); break; case FILE_DATA_LENGTH: + r = atou64(s, len, 10, &xar->file->length); + if (r != ARCHIVE_OK) + return (r); xar->file->has |= HAS_DATA; - xar->file->length = atol10(s, len); break; case FILE_DATA_OFFSET: + r = atou64(s, len, 10, &xar->file->offset); + if (r != ARCHIVE_OK) + return (r); xar->file->has |= HAS_DATA; - xar->file->offset = atol10(s, len); break; case FILE_DATA_SIZE: + r = atou64(s, len, 10, &xar->file->size); + if (r != ARCHIVE_OK) + return (r); xar->file->has |= HAS_DATA; - xar->file->size = atol10(s, len); break; case FILE_DATA_A_CHECKSUM: xar->file->a_sum.len = atohex(xar->file->a_sum.val, @@ -2822,16 +2872,22 @@ xml_data(void *userData, const char *s, size_t len) sizeof(xar->file->e_sum.val), s, len); break; case FILE_EA_LENGTH: + r = atou64(s, len, 10, &xar->xattr->length); + if (r != ARCHIVE_OK) + return (r); xar->file->has |= HAS_XATTR; - xar->xattr->length = atol10(s, len); break; case FILE_EA_OFFSET: + r = atou64(s, len, 10, &xar->xattr->offset); + if (r != ARCHIVE_OK) + return (r); xar->file->has |= HAS_XATTR; - xar->xattr->offset = atol10(s, len); break; case FILE_EA_SIZE: + r = atou64(s, len, 10, &xar->xattr->size); + if (r != ARCHIVE_OK) + return (r); xar->file->has |= HAS_XATTR; - xar->xattr->size = atol10(s, len); break; case FILE_EA_A_CHECKSUM: xar->file->has |= HAS_XATTR; @@ -2907,6 +2963,8 @@ xml_data(void *userData, const char *s, size_t len) case UNKNOWN: break; } + + return (ARCHIVE_OK); } /* @@ -3205,7 +3263,12 @@ xml2_read_toc(struct archive_read *a) break; case XML_READER_TYPE_TEXT: value = (const char *)xmlTextReaderConstValue(reader); - xml_data(a, value, strlen(value)); + r = xml_data(a, value, strlen(value)); + if (r != ARCHIVE_OK) { + xmlFreeTextReader(reader); + xmlCleanupParser(); + return (r); + } break; case XML_READER_TYPE_SIGNIFICANT_WHITESPACE: default: @@ -3285,7 +3348,10 @@ expat_data_cb(void *userData, const XML_Char *s, int len) { struct expat_userData *ud = (struct expat_userData *)userData; - xml_data(ud->archive, s, (size_t)len); + if (ud->state != ARCHIVE_OK) + return; + + ud->state = xml_data(ud->archive, s, (size_t)len); } static int @@ -3321,7 +3387,7 @@ expat_read_toc(struct archive_read *a) d = NULL; r = rd_contents(a, &d, &outbytes, &used, xar->toc_remaining); - if (r != ARCHIVE_OK) { + if (r != ARCHIVE_OK || outbytes > INT_MAX) { XML_ParserFree(parser); return (r); } @@ -3638,7 +3704,11 @@ xmllite_read_toc(struct archive_read *a) goto out; } - xml_data(a, as.s, (int)archive_strlen(&as)); + r = xml_data(a, as.s, archive_strlen(&as)); + if (r != ARCHIVE_OK) { + /* xml_data sets an appropriate error */ + goto out; + } archive_string_free(&as); case XmlNodeType_None: diff --git a/contrib/libarchive/libarchive/archive_read_support_format_zip.c b/contrib/libarchive/libarchive/archive_read_support_format_zip.c index 00796b288a..fa9995d963 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_zip.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_zip.c @@ -272,6 +272,10 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff, size_t *size, int64_t *offset); #endif +static void +trad_enc_decrypt_update(struct trad_enc_ctx *, const uint8_t *, size_t, + uint8_t *, size_t); + /* This function is used by Ppmd8_DecodeSymbol during decompression of Ppmd8 * streams inside ZIP files. It has 2 purposes: one is to fetch the next * compressed byte from the stream, second one is to increase the counter how @@ -281,15 +285,32 @@ ppmd_read(void* p) { /* Get the handle to current decompression context. */ struct archive_read *a = ((IByteIn*)p)->a; struct zip *zip = (struct zip*) a->format->data; - ssize_t bytes_avail = 0; /* Fetch next byte. */ - const uint8_t* data = __archive_read_ahead(a, 1, &bytes_avail); - if(bytes_avail < 1) { + const uint8_t* data = __archive_read_ahead(a, 1, NULL); + if(data == NULL) { zip->ppmd8_stream_failed = 1; return 0; } + if (zip->tctx_valid || zip->cctx_valid) { + uint8_t val; + if (zip->tctx_valid) { + trad_enc_decrypt_update(&zip->tctx, + data, 1, &val, 1); + } else { + size_t dsize = 1; + archive_decrypto_aes_ctr_update(&zip->cctx, + data, 1, &val, &dsize); + } + if (zip->hctx_valid) + archive_hmac_sha1_update(&zip->hctx, data, 1); + + __archive_read_consume(a, 1); + ++zip->zipx_ppmd_read_compressed; + return val; + } + __archive_read_consume(a, 1); /* Increment the counter. */ @@ -401,6 +422,146 @@ crypt_derive_key_sha1(const void *p, int size, unsigned char *key, } #endif +/* Read and decrypt bytes for zipx init headers. + * Used by format-specific init functions (lzma, ppmd) that need to + * read a small header from the compressed stream. When encryption is + * active the bytes are decrypted in-place into the decryption buffer. */ +static int +zipx_read_header_and_decrypt(struct archive_read *a, const void **buf, size_t in_len, + size_t *out_len, size_t *consumed) +{ + struct zip *zip = (struct zip *)(a->format->data); + const void *raw; + ssize_t bytes_avail; + size_t to_decrypt; + + raw = __archive_read_ahead(a, in_len, &bytes_avail); + if (raw == NULL || bytes_avail < (ssize_t)in_len) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file data"); + return (ARCHIVE_FATAL); + } + + if (zip->tctx_valid || zip->cctx_valid) { + to_decrypt = in_len; + if (to_decrypt > zip->decrypted_buffer_size) + to_decrypt = zip->decrypted_buffer_size; + + if (zip->tctx_valid) { + trad_enc_decrypt_update(&zip->tctx, + raw, to_decrypt, + zip->decrypted_buffer, to_decrypt); + } else { + size_t dsize = to_decrypt; + archive_decrypto_aes_ctr_update(&zip->cctx, + raw, to_decrypt, + zip->decrypted_buffer, &dsize); + } + if (zip->hctx_valid) + archive_hmac_sha1_update(&zip->hctx, + raw, to_decrypt); + + *buf = zip->decrypted_buffer; + *out_len = to_decrypt; + *consumed = to_decrypt; + } else { + *buf = raw; + *out_len = in_len; + *consumed = in_len; + } + return (ARCHIVE_OK); +} + +/* Decrypt bulk compressed data for zipx decompression. + * Manages the decryption buffer, handles partial fills, and returns decrypted + * data pointer + length. `sp` is set to the raw pointer for HMAC accounting. */ +static void +zip_read_decrypt(struct zip *zip, const void *compressed_buff, + ssize_t bytes_avail, const void **result_buff, ssize_t *result_avail, + const void **sp) +{ + *sp = compressed_buff; + + if (zip->tctx_valid || zip->cctx_valid) { + if (zip->decrypted_bytes_remaining < (size_t)bytes_avail) { + size_t buff_remaining = + (zip->decrypted_buffer + + zip->decrypted_buffer_size) + - (zip->decrypted_ptr + + zip->decrypted_bytes_remaining); + /* The new bytes to decrypt start after decrypted_bytes_remaining + * in the raw stream: those leading bytes were already + * decrypted on a previous call but have not yet been consumed. */ + size_t new_bytes = + (size_t)bytes_avail + - zip->decrypted_bytes_remaining; + + if (buff_remaining > new_bytes) + buff_remaining = new_bytes; + + if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END) && + zip->entry_bytes_remaining > 0) { + if ((int64_t)(zip->decrypted_bytes_remaining + + buff_remaining) + > zip->entry_bytes_remaining) { + if (zip->entry_bytes_remaining < + (int64_t)zip->decrypted_bytes_remaining) + buff_remaining = 0; + else + buff_remaining = + (size_t)zip->entry_bytes_remaining + - zip->decrypted_bytes_remaining; + } + } + if (buff_remaining > 0) { + if (zip->tctx_valid) { + trad_enc_decrypt_update(&zip->tctx, + (const uint8_t *)compressed_buff + + zip->decrypted_bytes_remaining, + buff_remaining, + zip->decrypted_ptr + + zip->decrypted_bytes_remaining, + buff_remaining); + } else { + size_t dsize = buff_remaining; + archive_decrypto_aes_ctr_update( + &zip->cctx, + (const uint8_t *)compressed_buff + + zip->decrypted_bytes_remaining, + buff_remaining, + zip->decrypted_ptr + + zip->decrypted_bytes_remaining, + &dsize); + } + zip->decrypted_bytes_remaining += + buff_remaining; + } + } + *result_avail = zip->decrypted_bytes_remaining; + *result_buff = (const char *)zip->decrypted_ptr; + } else { + *result_buff = compressed_buff; + *result_avail = bytes_avail; + } +} + +/* Post-decompression decrypt state update. + * Updates decrypt buffer pointers and HMAC after the decompressor + * has consumed `to_consume` bytes. */ +static void +zip_read_decrypt_update(struct zip *zip, ssize_t to_consume, const void *sp) +{ + if (zip->tctx_valid || zip->cctx_valid) { + zip->decrypted_bytes_remaining -= to_consume; + if (zip->decrypted_bytes_remaining == 0) + zip->decrypted_ptr = zip->decrypted_buffer; + else + zip->decrypted_ptr += to_consume; + } + if (zip->hctx_valid) + archive_hmac_sha1_update(&zip->hctx, sp, to_consume); +} + /* * Common code for streaming or seeking modes. * @@ -1775,7 +1936,7 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip) * "lzma alone" decoder from XZ Utils. */ memset(&zip->zipx_lzma_stream, 0, sizeof(zip->zipx_lzma_stream)); - r = lzma_alone_decoder(&zip->zipx_lzma_stream, UINT64_MAX); + r = lzma_alone_decoder(&zip->zipx_lzma_stream, 576 * ((uint64_t)1 << 20)); if (r != LZMA_OK) { archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, "lzma initialization failed (%d)", r); @@ -1825,12 +1986,32 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip) */ /* Read magic1,magic2,lzma_params from the ZIPX stream. */ - if(zip->entry_bytes_remaining < 9 || (p = __archive_read_ahead(a, 9, NULL)) == NULL) { + if(zip->entry_bytes_remaining < 9) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzma data"); return (ARCHIVE_FATAL); } + if (zip->tctx_valid || zip->cctx_valid) { + const void *decrypted; + size_t out_len; + size_t consumed; + int ret; + + ret = zipx_read_header_and_decrypt(a, &decrypted, 9, &out_len, &consumed); + if (ret != ARCHIVE_OK) + return ret; + p = decrypted; + } else { + p = __archive_read_ahead(a, 9, NULL); + if (p == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated lzma data"); + return (ARCHIVE_FATAL); + } + } + if(p[2] != 0x05 || p[3] != 0x00) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid lzma data"); @@ -1868,8 +2049,12 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip) * output bytes yet. */ r = lzma_code(&zip->zipx_lzma_stream, LZMA_RUN); if (r != LZMA_OK) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, - "lzma stream initialization error"); + if (r == LZMA_MEMLIMIT_ERROR) + archive_set_error(&a->archive, ENOMEM, + "lzma stream requires too much memory"); + else + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "lzma stream initialization error"); return ARCHIVE_FATAL; } @@ -1890,6 +2075,7 @@ zip_read_data_zipx_xz(struct archive_read *a, const void **buff, int ret; lzma_ret lz_ret; const void* compressed_buf; + const void* sp; ssize_t bytes_avail, in_bytes, to_consume = 0; (void) offset; /* UNUSED */ @@ -1901,7 +2087,7 @@ zip_read_data_zipx_xz(struct archive_read *a, const void **buff, return (ret); } - compressed_buf = __archive_read_ahead(a, 1, &bytes_avail); + compressed_buf = sp = __archive_read_ahead(a, 1, &bytes_avail); if (bytes_avail < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated xz file body"); @@ -1909,6 +2095,10 @@ zip_read_data_zipx_xz(struct archive_read *a, const void **buff, } in_bytes = (ssize_t)zipmin(zip->entry_bytes_remaining, bytes_avail); + + zip_read_decrypt(zip, compressed_buf, in_bytes, + &compressed_buf, &in_bytes, &sp); + zip->zipx_lzma_stream.next_in = compressed_buf; zip->zipx_lzma_stream.avail_in = in_bytes; zip->zipx_lzma_stream.total_in = 0; @@ -1957,6 +2147,16 @@ zip_read_data_zipx_xz(struct archive_read *a, const void **buff, zip->entry_compressed_bytes_read += to_consume; zip->entry_uncompressed_bytes_read += zip->zipx_lzma_stream.total_out; + zip_read_decrypt_update(zip, to_consume, sp); + + if (zip->end_of_entry) { + if (zip->hctx_valid) { + ret = check_authentication_code(a, NULL); + if (ret != ARCHIVE_OK) + return ret; + } + } + *size = (size_t)zip->zipx_lzma_stream.total_out; *buff = zip->uncompressed_buffer; @@ -1971,6 +2171,7 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff, int ret; lzma_ret lz_ret; const void* compressed_buf; + const void* sp; ssize_t bytes_avail, in_bytes, to_consume; (void) offset; /* UNUSED */ @@ -2000,6 +2201,9 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff, /* Set decompressor parameters. */ in_bytes = (ssize_t)zipmin(zip->entry_bytes_remaining, bytes_avail); + zip_read_decrypt(zip, compressed_buf, in_bytes, + &compressed_buf, &in_bytes, &sp); + zip->zipx_lzma_stream.next_in = compressed_buf; zip->zipx_lzma_stream.avail_in = in_bytes; zip->zipx_lzma_stream.total_in = 0; @@ -2039,6 +2243,12 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff, case LZMA_OK: break; + case LZMA_BUF_ERROR: + if (zip->zipx_lzma_stream.avail_out == 0) { + zip->end_of_entry = 1; + break; + } + /* FALL THROUGH */ default: archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "lzma unknown error (%d)", (int) lz_ret); @@ -2053,16 +2263,37 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff, zip->entry_compressed_bytes_read += to_consume; zip->entry_uncompressed_bytes_read += zip->zipx_lzma_stream.total_out; + zip_read_decrypt_update(zip, to_consume, sp); + if(zip->entry_bytes_remaining == 0) { zip->end_of_entry = 1; } + if(zip->end_of_entry && zip->entry_bytes_remaining > 0) { + ssize_t remaining = (ssize_t)zip->entry_bytes_remaining; + const void *p = __archive_read_ahead(a, remaining, NULL); + if (p != NULL) { + if (zip->hctx_valid) + archive_hmac_sha1_update(&zip->hctx, + p, remaining); + __archive_read_consume(a, remaining); + zip->entry_compressed_bytes_read += remaining; + zip->entry_bytes_remaining = 0; + } + } + /* Free lzma decoder handle because we'll no longer need it. */ /* This cannot be folded into LZMA_STREAM_END handling above * because the stream end marker is not required in this format. */ if(zip->end_of_entry) { lzma_end(&zip->zipx_lzma_stream); zip->zipx_lzma_valid = 0; + + if (zip->hctx_valid) { + ret = check_authentication_code(a, NULL); + if (ret != ARCHIVE_OK) + return ret; + } } /* Return values. */ @@ -2104,11 +2335,22 @@ zipx_ppmd8_init(struct archive_read *a, struct zip *zip) zip->zipx_ppmd_read_compressed = 0; /* Read Ppmd8 header (2 bytes). */ - p = __archive_read_ahead(a, 2, NULL); - if(!p) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Truncated file data in PPMd8 stream"); - return (ARCHIVE_FATAL); + if (zip->tctx_valid || zip->cctx_valid) { + size_t out_len; + size_t consumed; + int ret; + + ret = zipx_read_header_and_decrypt(a, &p, 2, &out_len, &consumed); + if (ret != ARCHIVE_OK) + return ret; + } else { + p = __archive_read_ahead(a, 2, NULL); + if(!p) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated file data in PPMd8 stream"); + return (ARCHIVE_FATAL); + } } __archive_read_consume(a, 2); @@ -2178,7 +2420,6 @@ zip_read_data_zipx_ppmd(struct archive_read *a, const void **buff, struct zip* zip = (struct zip *)(a->format->data); int ret; size_t consumed_bytes = 0; - ssize_t bytes_avail = 0; (void) offset; /* UNUSED */ @@ -2192,8 +2433,7 @@ zip_read_data_zipx_ppmd(struct archive_read *a, const void **buff, /* Fetch for more data. We're reading 1 byte here, but libarchive * should prefetch more bytes. */ - (void) __archive_read_ahead(a, 1, &bytes_avail); - if(bytes_avail < 0) { + if(__archive_read_ahead(a, 1, NULL) == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated PPMd8 file body"); return (ARCHIVE_FATAL); @@ -2234,6 +2474,12 @@ zip_read_data_zipx_ppmd(struct archive_read *a, const void **buff, if(zip->end_of_entry) { __archive_ppmd8_functions.Ppmd8_Free(&zip->ppmd8); zip->ppmd8_valid = 0; + + if (zip->hctx_valid) { + int r = check_authentication_code(a, NULL); + if (r != ARCHIVE_OK) + return (r); + } } /* Update pointers for libarchive. */ @@ -2293,6 +2539,7 @@ zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff, struct zip *zip = (struct zip *)(a->format->data); ssize_t bytes_avail = 0, in_bytes, to_consume; const void *compressed_buff; + const void *sp; int r; uint64_t total_out; @@ -2325,6 +2572,9 @@ zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff, return (ARCHIVE_FATAL); } + zip_read_decrypt(zip, compressed_buff, in_bytes, + &compressed_buff, &in_bytes, &sp); + /* Setup buffer boundaries. */ zip->bzstream.next_in = (char*)(uintptr_t) compressed_buff; zip->bzstream.avail_in = (uint32_t)in_bytes; @@ -2375,6 +2625,14 @@ zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff, zip->entry_compressed_bytes_read += to_consume; zip->entry_uncompressed_bytes_read += total_out; + zip_read_decrypt_update(zip, to_consume, sp); + + if (zip->end_of_entry && zip->hctx_valid) { + r = check_authentication_code(a, NULL); + if (r != ARCHIVE_OK) + return r; + } + /* Give libarchive its due. */ *size = (size_t)total_out; *buff = zip->uncompressed_buffer; @@ -2436,6 +2694,7 @@ zip_read_data_zipx_zstd(struct archive_read *a, const void **buff, struct zip *zip = (struct zip *)(a->format->data); ssize_t bytes_avail = 0, in_bytes, to_consume; const void *compressed_buff; + const void *sp; int r; size_t ret; uint64_t total_out; @@ -2452,7 +2711,7 @@ zip_read_data_zipx_zstd(struct archive_read *a, const void **buff, } /* Fetch more compressed bytes */ - compressed_buff = __archive_read_ahead(a, 1, &bytes_avail); + compressed_buff = sp = __archive_read_ahead(a, 1, &bytes_avail); if(bytes_avail < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated zstd file body"); @@ -2470,6 +2729,9 @@ zip_read_data_zipx_zstd(struct archive_read *a, const void **buff, return (ARCHIVE_FATAL); } + zip_read_decrypt(zip, compressed_buff, in_bytes, + &compressed_buff, &in_bytes, &sp); + /* Setup buffer boundaries */ in.src = compressed_buff; in.size = in_bytes; @@ -2504,6 +2766,14 @@ zip_read_data_zipx_zstd(struct archive_read *a, const void **buff, zip->entry_compressed_bytes_read += to_consume; zip->entry_uncompressed_bytes_read += total_out; + zip_read_decrypt_update(zip, to_consume, sp); + + if (zip->end_of_entry && zip->hctx_valid) { + r = check_authentication_code(a, NULL); + if (r != ARCHIVE_OK) + return r; + } + /* Give libarchive its due. */ *size = (size_t)total_out; *buff = zip->uncompressed_buffer; @@ -2544,7 +2814,8 @@ zip_read_data_deflate(struct archive_read *a, const void **buff, { struct zip *zip; ssize_t bytes_avail, to_consume = 0; - const void *compressed_buff, *sp; + const void *compressed_buff; + const void *sp; int r; (void)offset; /* UNUSED */ @@ -2584,54 +2855,8 @@ zip_read_data_deflate(struct archive_read *a, const void **buff, return (ARCHIVE_FATAL); } - if (zip->tctx_valid || zip->cctx_valid) { - if (zip->decrypted_bytes_remaining < (size_t)bytes_avail) { - size_t buff_remaining = - (zip->decrypted_buffer + - zip->decrypted_buffer_size) - - (zip->decrypted_ptr + - zip->decrypted_bytes_remaining); - - if (buff_remaining > (size_t)bytes_avail) - buff_remaining = (size_t)bytes_avail; - - if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END) && - zip->entry_bytes_remaining > 0) { - if ((int64_t)(zip->decrypted_bytes_remaining - + buff_remaining) - > zip->entry_bytes_remaining) { - if (zip->entry_bytes_remaining < - (int64_t)zip->decrypted_bytes_remaining) - buff_remaining = 0; - else - buff_remaining = - (size_t)zip->entry_bytes_remaining - - zip->decrypted_bytes_remaining; - } - } - if (buff_remaining > 0) { - if (zip->tctx_valid) { - trad_enc_decrypt_update(&zip->tctx, - compressed_buff, buff_remaining, - zip->decrypted_ptr - + zip->decrypted_bytes_remaining, - buff_remaining); - } else { - size_t dsize = buff_remaining; - archive_decrypto_aes_ctr_update( - &zip->cctx, - compressed_buff, buff_remaining, - zip->decrypted_ptr - + zip->decrypted_bytes_remaining, - &dsize); - } - zip->decrypted_bytes_remaining += - buff_remaining; - } - } - bytes_avail = zip->decrypted_bytes_remaining; - compressed_buff = (const char *)zip->decrypted_ptr; - } + zip_read_decrypt(zip, compressed_buff, bytes_avail, + &compressed_buff, &bytes_avail, &sp); /* * A bug in zlib.h: stream.next_in should be marked 'const' @@ -2670,22 +2895,12 @@ zip_read_data_deflate(struct archive_read *a, const void **buff, zip->entry_compressed_bytes_read += to_consume; zip->entry_uncompressed_bytes_read += zip->stream.total_out; - if (zip->tctx_valid || zip->cctx_valid) { - zip->decrypted_bytes_remaining -= to_consume; - if (zip->decrypted_bytes_remaining == 0) - zip->decrypted_ptr = zip->decrypted_buffer; - else - zip->decrypted_ptr += to_consume; - } - if (zip->hctx_valid) - archive_hmac_sha1_update(&zip->hctx, sp, to_consume); + zip_read_decrypt_update(zip, to_consume, sp); - if (zip->end_of_entry) { - if (zip->hctx_valid) { - r = check_authentication_code(a, NULL); - if (r != ARCHIVE_OK) { - return (r); - } + if (zip->end_of_entry && zip->hctx_valid) { + r = check_authentication_code(a, NULL); + if (r != ARCHIVE_OK) { + return r; } } diff --git a/contrib/libarchive/libarchive/archive_string.c b/contrib/libarchive/libarchive/archive_string.c index 0ac6876944..02bb3a774a 100644 --- a/contrib/libarchive/libarchive/archive_string.c +++ b/contrib/libarchive/libarchive/archive_string.c @@ -1372,7 +1372,7 @@ free_sconv_object(struct archive_string_conv *sc) } #if defined(_WIN32) && !defined(__CYGWIN__) -# if defined(WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) # define GetOEMCP() CP_OEMCP # endif diff --git a/contrib/libarchive/libarchive/archive_time.c b/contrib/libarchive/libarchive/archive_time.c index 3352c809bd..bc77082889 100644 --- a/contrib/libarchive/libarchive/archive_time.c +++ b/contrib/libarchive/libarchive/archive_time.c @@ -24,11 +24,20 @@ */ #include "archive_platform.h" -#include "archive_private.h" -#include "archive_time_private.h" + +#ifdef HAVE_LIMITS_H #include +#endif +#ifdef HAVE_STDLIB_H #include +#endif +#ifdef HAVE_STRING_H #include +#endif + +#include "archive_integer.h" +#include "archive_private.h" +#include "archive_time_private.h" #define NTFS_EPOC_TIME ARCHIVE_LITERAL_ULL(11644473600) #define NTFS_TICKS ARCHIVE_LITERAL_ULL(10000000) @@ -149,15 +158,11 @@ unix_to_ntfs(int64_t secs, uint32_t nsecs) if (secs < -(int64_t)NTFS_EPOC_TIME) return 0; - ntfs = secs + NTFS_EPOC_TIME; - - if (ntfs > UINT64_MAX / NTFS_TICKS) - return UINT64_MAX; - - ntfs *= NTFS_TICKS; - - if (ntfs > UINT64_MAX - nsecs/100) + /* (secs + NTFS_EPOC_TIME) * NTFS_TICKS + nsecs / 100 */ + if (archive_ckd_add_u64(&ntfs, secs, NTFS_EPOC_TIME) || + archive_ckd_mul_u64(&ntfs, ntfs, NTFS_TICKS) || + archive_ckd_add_u64(&ntfs, ntfs, nsecs / 100)) return UINT64_MAX; - return ntfs + nsecs/100; + return ntfs; } diff --git a/contrib/libarchive/libarchive/archive_util.3 b/contrib/libarchive/libarchive/archive_util.3 index 3aa508f25a..26026d4323 100644 --- a/contrib/libarchive/libarchive/archive_util.3 +++ b/contrib/libarchive/libarchive/archive_util.3 @@ -33,12 +33,15 @@ .Nm archive_errno , .Nm archive_error_string , .Nm archive_file_count , +.Nm archive_filter_bytes , .Nm archive_filter_code , .Nm archive_filter_count , .Nm archive_filter_name , .Nm archive_format , .Nm archive_format_name , -.Nm archive_position , +.Nm archive_free , +.Nm archive_position_compressed , +.Nm archive_position_uncompressed , .Nm archive_set_error .Nd libarchive utility functions .Sh LIBRARY @@ -59,6 +62,8 @@ Streaming Archive Library (libarchive, -larchive) .Fn archive_error_string "struct archive *" .Ft int .Fn archive_file_count "struct archive *" +.Ft int64_t +.Fn archive_filter_bytes "struct archive *" "int" .Ft int .Fn archive_filter_code "struct archive *" "int" .Ft int @@ -69,8 +74,12 @@ Streaming Archive Library (libarchive, -larchive) .Fn archive_format "struct archive *" .Ft const char * .Fn archive_format_name "struct archive *" +.Ft int +.Fn archive_free "struct archive *" +.Ft int64_t +.Fn archive_position_compressed "struct archive *" .Ft int64_t -.Fn archive_position "struct archive *" "int" +.Fn archive_position_uncompressed "struct archive *" .Ft void .Fo archive_set_error .Fa "struct archive *" @@ -140,13 +149,13 @@ filter 0 is the gunzip filter, filter 1 is the uudecode filter, and filter 2 is the pseudo-filter that wraps the archive read functions. In this case, requesting -.Fn archive_position a -1 +.Fn archive_filter_bytes a -1 would be a synonym for -.Fn archive_position a 2 +.Fn archive_filter_bytes a 2 which would return the number of bytes currently read from the archive, while -.Fn archive_position a 1 +.Fn archive_filter_bytes a 1 would return the number of bytes after uudecoding, and -.Fn archive_position a 0 +.Fn archive_filter_bytes a 0 would return the number of bytes after decompression. .It Fn archive_filter_name Returns a textual name identifying the indicated filter. @@ -165,16 +174,24 @@ utilize GNU tar extensions and several entries that do not. These entries will have different format codes. .It Fn archive_format_name A textual description of the format of the current entry. -.It Fn archive_position +.It Fn archive_free +Closes the archive if necessary, then releases all resources. +.It Fn archive_filter_bytes Returns the number of bytes read from or written to the indicated filter. In particular, -.Fn archive_position a 0 +.Fn archive_filter_bytes a 0 returns the number of bytes read or written by the format handler, while -.Fn archive_position a -1 +.Fn archive_filter_bytes a -1 returns the number of bytes read or written to the archive. See .Fn archive_filter_count for details of the numbering here. +.It Fn archive_position_compressed +Synonym for +.Fn archive_filter_bytes a -1 . +.It Fn archive_position_uncompressed +Synonym for +.Fn archive_filter_bytes a 0 . .It Fn archive_set_error Sets the numeric error code and error description that will be returned by diff --git a/contrib/libarchive/libarchive/archive_util.c b/contrib/libarchive/libarchive/archive_util.c index 0d1de1ef20..5e0b916de4 100644 --- a/contrib/libarchive/libarchive/archive_util.c +++ b/contrib/libarchive/libarchive/archive_util.c @@ -42,18 +42,12 @@ #include #endif #if defined(_WIN32) && !defined(__CYGWIN__) -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA -/* don't use bcrypt when XP needs to be supported */ #include /* Common in other bcrypt implementations, but missing from VS2008. */ #ifndef BCRYPT_SUCCESS #define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS) #endif - -#elif defined(HAVE_WINCRYPT_H) -#include -#endif #endif #ifdef HAVE_ZLIB_H #include @@ -110,8 +104,7 @@ archive_errno(struct archive *a) const char * archive_error_string(struct archive *a) { - - if (a->error != NULL && *a->error != '\0') + if (a->error != NULL && *a->error != '\0') return (a->error); else return (NULL); @@ -250,11 +243,7 @@ __archive_mktempx(const char *tmpdir, wchar_t *template) DWORD attr; wchar_t *xp, *ep; int fd; -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA BCRYPT_ALG_HANDLE hAlg = NULL; -#else - HCRYPTPROV hProv = (HCRYPTPROV)NULL; -#endif fd = -1; ws = NULL; archive_string_init(&temp_name); @@ -262,22 +251,36 @@ __archive_mktempx(const char *tmpdir, wchar_t *template) if (template == NULL) { /* Get a temporary directory. */ if (tmpdir == NULL) { - size_t l; - wchar_t *tmp; + wchar_t buf[MAX_PATH + 1]; + wchar_t *p = buf, *buf2 = NULL; + size_t l, s; - l = GetTempPathW(0, NULL); + s = MAX_PATH + 1; + l = GetTempPathW((DWORD)s, buf); if (l == 0) { la_dosmaperr(GetLastError()); goto exit_tmpfile; } - tmp = malloc(l*sizeof(wchar_t)); - if (tmp == NULL) { - errno = ENOMEM; - goto exit_tmpfile; + while (l > s) { + wchar_t *tmp; + + s = l; + tmp = realloc(buf2, s * sizeof(wchar_t)); + if (tmp == NULL) { + free(buf2); + errno = ENOMEM; + goto exit_tmpfile; + } + p = buf2 = tmp; + l = GetTempPathW((DWORD)s, buf2); + if (l == 0) { + free(buf2); + la_dosmaperr(GetLastError()); + goto exit_tmpfile; + } } - GetTempPathW((DWORD)l, tmp); - archive_wstrcpy(&temp_name, tmp); - free(tmp); + archive_wstrcpy(&temp_name, p); + free(buf2); } else { if (archive_wstring_append_from_mbs(&temp_name, tmpdir, strlen(tmpdir)) < 0) @@ -328,19 +331,11 @@ __archive_mktempx(const char *tmpdir, wchar_t *template) abort(); } -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM, NULL, 0))) { la_dosmaperr(GetLastError()); goto exit_tmpfile; } -#else - if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT)) { - la_dosmaperr(GetLastError()); - goto exit_tmpfile; - } -#endif for (;;) { wchar_t *p; @@ -351,19 +346,11 @@ __archive_mktempx(const char *tmpdir, wchar_t *template) /* Generate a random file name through CryptGenRandom(). */ p = xp; -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA if (!BCRYPT_SUCCESS(BCryptGenRandom(hAlg, (PUCHAR)p, (DWORD)(ep - p)*sizeof(wchar_t), 0))) { la_dosmaperr(GetLastError()); goto exit_tmpfile; } -#else - if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t), - (BYTE*)p)) { - la_dosmaperr(GetLastError()); - goto exit_tmpfile; - } -#endif for (; p < ep; p++) *p = num[((DWORD)*p) % (sizeof(num)/sizeof(num[0]))]; @@ -417,13 +404,8 @@ __archive_mktempx(const char *tmpdir, wchar_t *template) break;/* success! */ } exit_tmpfile: -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA if (hAlg != NULL) BCryptCloseAlgorithmProvider(hAlg, 0); -#else - if (hProv != (HCRYPTPROV)NULL) - CryptReleaseContext(hProv, 0); -#endif free(ws); if (template == temp_name.s) archive_wstring_free(&temp_name); diff --git a/contrib/libarchive/libarchive/archive_version_details.c b/contrib/libarchive/libarchive/archive_version_details.c index 9063faa794..be11aad67e 100644 --- a/contrib/libarchive/libarchive/archive_version_details.c +++ b/contrib/libarchive/libarchive/archive_version_details.c @@ -157,10 +157,6 @@ archive_crypto_version(struct archive_string* str) #if defined(ARCHIVE_CRYPTOR_USE_LIBMD) archive_strcat(str, " libmd/"); archive_strcat(str, archive_libmd_version()); -#endif -#if defined(ARCHIVE_CRYPTOR_USE_WINCRYPT) - archive_strcat(str, " WinCrypt/"); - archive_strcat(str, archive_wincrypt_version()); #endif // Just in case (void)str; /* UNUSED */ @@ -180,7 +176,7 @@ archive_version_details(void) const char *libiconv = archive_libiconv_version(); const char *libacl = archive_libacl_version(); const char *librichacl = archive_librichacl_version(); - const char *libattr = archive_libacl_version(); + const char *libattr = archive_libattr_version(); if (!init) { archive_string_init(&str); @@ -234,6 +230,7 @@ archive_version_details(void) archive_strcat(&str, " libiconv/"); archive_strcat(&str, libiconv); } + init = 1; } return str.s; } @@ -431,27 +428,7 @@ archive_cng_version(void) const char * archive_wincrypt_version(void) { -#if defined(ARCHIVE_CRYPTOR_USE_WINCRYPT) || defined(ARCHIVE_CRYPTO_WINCRYPT) - HCRYPTPROV prov; - if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - if (GetLastError() != (DWORD)NTE_BAD_KEYSET) - return NULL; - if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) - return NULL; - } - DWORD version, length = sizeof(version); - if (!CryptGetProvParam(prov, PP_VERSION, (BYTE *)&version, &length, 0)) { - return NULL; - } else { - char major = (version >> 8) & 0xFF; - char minor = version & 0xFF; - static char wincrypt_version[6]; - snprintf(wincrypt_version, 6, "%hhd.%hhd", major, minor); - return wincrypt_version; - } -#else return NULL; -#endif } const char * diff --git a/contrib/libarchive/libarchive/archive_write.c b/contrib/libarchive/libarchive/archive_write.c index 14dc7339ec..68f452ec30 100644 --- a/contrib/libarchive/libarchive/archive_write.c +++ b/contrib/libarchive/libarchive/archive_write.c @@ -761,7 +761,7 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry) archive_entry_ino_is_set(entry) && archive_entry_dev(entry) == (dev_t)a->skip_file_dev && archive_entry_ino64(entry) == a->skip_file_ino) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, EIO, "Can't add archive to itself"); return (ARCHIVE_FAILED); } diff --git a/contrib/libarchive/libarchive/archive_write_add_filter.c b/contrib/libarchive/libarchive/archive_write_add_filter.c index aa962515a0..ddcf282538 100644 --- a/contrib/libarchive/libarchive/archive_write_add_filter.c +++ b/contrib/libarchive/libarchive/archive_write_add_filter.c @@ -49,7 +49,7 @@ struct { int code; int (*setter)(struct archive *); } codes[] = { ARCHIVE_FILTER_LZ4, archive_write_add_filter_lz4 }, { ARCHIVE_FILTER_LZIP, archive_write_add_filter_lzip }, { ARCHIVE_FILTER_LZMA, archive_write_add_filter_lzma }, - { ARCHIVE_FILTER_LZOP, archive_write_add_filter_lzip }, + { ARCHIVE_FILTER_LZOP, archive_write_add_filter_lzop }, { ARCHIVE_FILTER_UU, archive_write_add_filter_uuencode }, { ARCHIVE_FILTER_XZ, archive_write_add_filter_xz }, { ARCHIVE_FILTER_ZSTD, archive_write_add_filter_zstd }, diff --git a/contrib/libarchive/libarchive/archive_write_add_filter_b64encode.c b/contrib/libarchive/libarchive/archive_write_add_filter_b64encode.c index d2c4742d2e..2c4e5ba6ee 100644 --- a/contrib/libarchive/libarchive/archive_write_add_filter_b64encode.c +++ b/contrib/libarchive/libarchive/archive_write_add_filter_b64encode.c @@ -39,6 +39,7 @@ #endif #include "archive.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_string.h" #include "archive_write_private.h" @@ -308,10 +309,9 @@ atol8(const char *p, size_t char_cnt) else return (-1); p++; - if (l > (INT64_MAX >> 3)) + if (archive_ckd_mul_i64(&l, l, 8) || + archive_ckd_add_i64(&l, l, digit)) return (-1); - l <<= 3; - l |= digit; } return (l); } diff --git a/contrib/libarchive/libarchive/archive_write_add_filter_bzip2.c b/contrib/libarchive/libarchive/archive_write_add_filter_bzip2.c index 94b342d41b..209b152854 100644 --- a/contrib/libarchive/libarchive/archive_write_add_filter_bzip2.c +++ b/contrib/libarchive/libarchive/archive_write_add_filter_bzip2.c @@ -57,7 +57,6 @@ struct private_data { int compression_level; #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) bz_stream stream; - int64_t total_in; char *compressed; size_t compressed_buffer_size; #else @@ -239,9 +238,6 @@ archive_compressor_bzip2_write(struct archive_write_filter *f, { struct private_data *data = (struct private_data *)f->data; - /* Update statistics */ - data->total_in += length; - /* Compress input data to output buffer */ SET_NEXT_IN(data, buff); data->stream.avail_in = (uint32_t)length; diff --git a/contrib/libarchive/libarchive/archive_write_add_filter_gzip.c b/contrib/libarchive/libarchive/archive_write_add_filter_gzip.c index 0a2f22408b..7112ef3728 100644 --- a/contrib/libarchive/libarchive/archive_write_add_filter_gzip.c +++ b/contrib/libarchive/libarchive/archive_write_add_filter_gzip.c @@ -40,6 +40,7 @@ #endif #include "archive.h" +#include "archive_endian.h" #include "archive_private.h" #include "archive_string.h" #include "archive_write_private.h" @@ -61,7 +62,7 @@ struct private_data { char *original_filename; #ifdef HAVE_ZLIB_H z_stream stream; - int64_t total_in; + uint64_t total_in; unsigned char *compressed; size_t compressed_buffer_size; unsigned long crc; @@ -178,7 +179,7 @@ archive_compressor_gzip_options(struct archive_write_filter *f, const char *key, if (value) { data->original_filename = strdup(value); if (data->original_filename == NULL) - return (ARCHIVE_WARN); + return (ARCHIVE_FAILED); } return (ARCHIVE_OK); } @@ -230,11 +231,8 @@ archive_compressor_gzip_open(struct archive_write_filter *f) data->compressed[2] = 0x08; /* "Deflate" compression */ data->compressed[3] = 0x00; /* Flags */ if (data->timestamp >= 0) { - time_t t = time(NULL); - data->compressed[4] = (uint8_t)(t)&0xff; /* Timestamp */ - data->compressed[5] = (uint8_t)(t>>8)&0xff; - data->compressed[6] = (uint8_t)(t>>16)&0xff; - data->compressed[7] = (uint8_t)(t>>24)&0xff; + uint32_t t = (uint32_t)time(NULL); + archive_le32enc(data->compressed + 4, t); /* Timestamp */ } else { memset(&data->compressed[4], 0, 4); } @@ -253,9 +251,9 @@ archive_compressor_gzip_open(struct archive_write_filter *f) /* Limit "original filename" to 32k or the * remaining space in the buffer, whichever is smaller. */ - int ofn_length = strlen(data->original_filename); - int ofn_max_length = 32768; - int ofn_space_available = data->compressed + size_t ofn_length = strlen(data->original_filename); + size_t ofn_max_length = 32768; + size_t ofn_space_available = data->compressed + data->compressed_buffer_size - data->stream.next_out - 1; @@ -358,14 +356,8 @@ archive_compressor_gzip_close(struct archive_write_filter *f) } if (ret == ARCHIVE_OK) { /* Build and write out 8-byte trailer. */ - trailer[0] = (uint8_t)(data->crc)&0xff; - trailer[1] = (uint8_t)(data->crc >> 8)&0xff; - trailer[2] = (uint8_t)(data->crc >> 16)&0xff; - trailer[3] = (uint8_t)(data->crc >> 24)&0xff; - trailer[4] = (uint8_t)(data->total_in)&0xff; - trailer[5] = (uint8_t)(data->total_in >> 8)&0xff; - trailer[6] = (uint8_t)(data->total_in >> 16)&0xff; - trailer[7] = (uint8_t)(data->total_in >> 24)&0xff; + archive_le32enc(trailer, data->crc); + archive_le32enc(trailer + 4, data->total_in); ret = __archive_write_filter(f->next_filter, trailer, 8); } diff --git a/contrib/libarchive/libarchive/archive_write_add_filter_lz4.c b/contrib/libarchive/libarchive/archive_write_add_filter_lz4.c index efc408e2a3..de5283f156 100644 --- a/contrib/libarchive/libarchive/archive_write_add_filter_lz4.c +++ b/contrib/libarchive/libarchive/archive_write_add_filter_lz4.c @@ -61,7 +61,6 @@ struct private_data { unsigned preset_dictionary:1; unsigned block_maximum_size:3; #if defined(HAVE_LIBLZ4) && LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 2 - int64_t total_in; char *out; char *out_buffer; size_t out_buffer_size; @@ -88,7 +87,7 @@ static int archive_filter_lz4_write(struct archive_write_filter *, const void *, size_t); /* - * Add a lz4 compression filter to this write handle. + * Add an lz4 compression filter to this write handle. */ int archive_write_add_filter_lz4(struct archive *_a) @@ -228,7 +227,7 @@ archive_filter_lz4_open(struct archive_write_filter *f) { struct private_data *data = (struct private_data *)f->data; size_t required_size; - static size_t const bkmap[] = { 64 * 1024, 256 * 1024, 1 * 1024 * 1024, + static const size_t bkmap[] = { 64 * 1024, 256 * 1024, 1 * 1024 * 1024, 4 * 1024 * 1024 }; size_t pre_block_size; @@ -243,7 +242,7 @@ archive_filter_lz4_open(struct archive_write_filter *f) free(data->out_buffer); if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { /* Buffer size should be a multiple number of - * the of bytes per block for performance. */ + * the bytes per block for performance. */ bpb = archive_write_get_bytes_per_block(f->archive); if (bpb > bs) bs = bpb; @@ -306,9 +305,6 @@ archive_filter_lz4_write(struct archive_write_filter *f, data->header_written = 1; } - /* Update statistics */ - data->total_in += length; - p = (const char *)buff; remaining = length; while (remaining) { @@ -417,9 +413,11 @@ lz4_write_stream_descriptor(struct archive_write_filter *f) sd[5] = (data->block_maximum_size << 4); sd[6] = (__archive_xxhash.XXH32(&sd[4], 2, 0) >> 8) & 0xff; data->out += 7; - if (data->stream_checksum) + if (data->stream_checksum) { data->xxh32_state = __archive_xxhash.XXH32_init(0); - else + if (data->xxh32_state == NULL) + return (ARCHIVE_FATAL); + } else data->xxh32_state = NULL; return (ARCHIVE_OK); } diff --git a/contrib/libarchive/libarchive/archive_write_add_filter_program.c b/contrib/libarchive/libarchive/archive_write_add_filter_program.c index f12db33738..cb92dc04f0 100644 --- a/contrib/libarchive/libarchive/archive_write_add_filter_program.c +++ b/contrib/libarchive/libarchive/archive_write_add_filter_program.c @@ -184,6 +184,10 @@ __archive_write_program_allocate(const char *program) data->child_stdin = -1; data->child_stdout = -1; data->program_name = strdup(program); + if (data->program_name == NULL) { + free(data); + return (NULL); + } return (data); } diff --git a/contrib/libarchive/libarchive/archive_write_add_filter_uuencode.c b/contrib/libarchive/libarchive/archive_write_add_filter_uuencode.c index d25236fa9b..b338b4aff0 100644 --- a/contrib/libarchive/libarchive/archive_write_add_filter_uuencode.c +++ b/contrib/libarchive/libarchive/archive_write_add_filter_uuencode.c @@ -39,6 +39,7 @@ #endif #include "archive.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_string.h" #include "archive_write_private.h" @@ -299,10 +300,9 @@ atol8(const char *p, size_t char_cnt) else return (-1); p++; - if (l > (INT64_MAX >> 3)) + if (archive_ckd_mul_i64(&l, l, 8) || + archive_ckd_add_i64(&l, l, digit)) return (-1); - l <<= 3; - l |= digit; } return (l); } diff --git a/contrib/libarchive/libarchive/archive_write_add_filter_zstd.c b/contrib/libarchive/libarchive/archive_write_add_filter_zstd.c index 7149abb2b8..2c6b91eba1 100644 --- a/contrib/libarchive/libarchive/archive_write_add_filter_zstd.c +++ b/contrib/libarchive/libarchive/archive_write_add_filter_zstd.c @@ -73,7 +73,6 @@ struct private_data { size_t cur_frame; size_t cur_frame_in; size_t cur_frame_out; - size_t total_in; ZSTD_CStream *cstream; ZSTD_outBuffer out; #else @@ -505,7 +504,6 @@ drive_compressor(struct archive_write_filter *f, data->state = running; break; } - data->total_in += in.pos - ipos; data->cur_frame_in += in.pos - ipos; data->cur_frame_out += data->out.pos - opos; if (data->state == running) { diff --git a/contrib/libarchive/libarchive/archive_write_disk_posix.c b/contrib/libarchive/libarchive/archive_write_disk_posix.c index 5ee36888ef..f9d4e9a7d2 100644 --- a/contrib/libarchive/libarchive/archive_write_disk_posix.c +++ b/contrib/libarchive/libarchive/archive_write_disk_posix.c @@ -308,6 +308,10 @@ struct archive_write_disk { int stream_valid; int decmpfs_compression_level; #endif +#if !(ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_AIX ||\ + ARCHIVE_XATTR_FREEBSD) + int warning_done; +#endif }; /* @@ -596,11 +600,12 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) a->pst = NULL; a->current_fixup = NULL; a->deferred = 0; - if (a->entry) { - archive_entry_free(a->entry); - a->entry = NULL; - } + archive_entry_free(a->entry); a->entry = archive_entry_clone(entry); + if (a->entry == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } a->fd = -1; a->fd_offset = 0; a->offset = 0; @@ -971,7 +976,7 @@ write_data_block(struct archive_write_disk *a, const char *buff, size_t size) return (ARCHIVE_OK); if (a->filesize == 0 || a->fd < 0) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, EIO, "Attempt to write to an empty file"); return (ARCHIVE_WARN); } @@ -1595,7 +1600,7 @@ hfs_write_data_block(struct archive_write_disk *a, const char *buff, return (ARCHIVE_OK); if (a->filesize == 0 || a->fd < 0) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, EIO, "Attempt to write to an empty file"); return (ARCHIVE_WARN); } @@ -1674,7 +1679,7 @@ _archive_write_disk_data_block(struct archive *_a, if (r < ARCHIVE_OK) return (r); if ((size_t)r < size) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, EOVERFLOW, "Too much data: Truncating file at %ju bytes", (uintmax_t)a->filesize); return (ARCHIVE_WARN); @@ -2196,7 +2201,7 @@ restore_entry(struct archive_write_disk *a) if (a->skip_file_set && a->st.st_dev == (dev_t)a->skip_file_dev && a->st.st_ino == (ino_t)a->skip_file_ino) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, EIO, "Refusing to overwrite archive"); return (ARCHIVE_FAILED); } @@ -2996,7 +3001,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, */ /* if (!S_ISLNK(path)) { - fsobj_error(a_eno, a_estr, 0, + fsobj_error(a_eno, a_estr, -1, "Removing symlink ", path); } */ @@ -3012,7 +3017,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, #endif if (r != 0) { tail[0] = c; - fsobj_error(a_eno, a_estr, 0, + fsobj_error(a_eno, a_estr, EIO, "Cannot remove intervening " "symlink ", path); res = ARCHIVE_FAILED; @@ -3072,7 +3077,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, head = tail + 1; } else { tail[0] = c; - fsobj_error(a_eno, a_estr, 0, + fsobj_error(a_eno, a_estr, ELOOP, "Cannot extract through " "symlink ", path); res = ARCHIVE_FAILED; @@ -3080,7 +3085,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, } } else { tail[0] = c; - fsobj_error(a_eno, a_estr, 0, + fsobj_error(a_eno, a_estr, ELOOP, "Cannot extract through symlink ", path); res = ARCHIVE_FAILED; break; @@ -4693,12 +4698,10 @@ set_xattrs(struct archive_write_disk *a) static int set_xattrs(struct archive_write_disk *a) { - static int warning_done = 0; - /* If there aren't any extended attributes, then it's okay not * to extract them, otherwise, issue a single warning. */ - if (archive_entry_xattr_count(a->entry) != 0 && !warning_done) { - warning_done = 1; + if (archive_entry_xattr_count(a->entry) != 0 && !a->warning_done) { + a->warning_done = 1; archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Cannot restore extended attributes on this system"); return (ARCHIVE_WARN); diff --git a/contrib/libarchive/libarchive/archive_write_filter.3 b/contrib/libarchive/libarchive/archive_write_filter.3 index b39cabe047..9939de414b 100644 --- a/contrib/libarchive/libarchive/archive_write_filter.3 +++ b/contrib/libarchive/libarchive/archive_write_filter.3 @@ -50,6 +50,8 @@ Streaming Archive Library (libarchive, -larchive) .Ft int .Fn archive_write_add_filter_b64encode "struct archive *" .Ft int +.Fn archive_write_add_filter_by_name "struct archive *" "const char *name" +.Ft int .Fn archive_write_add_filter_bzip2 "struct archive *" .Ft int .Fn archive_write_add_filter_compress "struct archive *" @@ -100,6 +102,8 @@ Note that the compressed output is always properly blocked. .Xc The output will be encoded as specified. The encoded output is always properly blocked. +.It Fn archive_write_add_filter_by_name +Sets the corresponding filter based on the common name. .It Fn archive_write_add_filter_none This is never necessary. It is provided only for backwards compatibility. @@ -111,6 +115,10 @@ write callbacks. .Sh RETURN VALUES These functions return .Cm ARCHIVE_OK +.Po or +.Cm ARCHIVE_WARN +if an external program had to be executed to handle the filter +.Pc on success, or .Cm ARCHIVE_FATAL . .\" diff --git a/contrib/libarchive/libarchive/archive_write_format.3 b/contrib/libarchive/libarchive/archive_write_format.3 index 9e331368ae..1b26c1c464 100644 --- a/contrib/libarchive/libarchive/archive_write_format.3 +++ b/contrib/libarchive/libarchive/archive_write_format.3 @@ -129,7 +129,9 @@ Sets the corresponding format based on the common name. .Fn archive_write_set_format_filter_by_ext .Fn archive_write_set_format_filter_by_ext_def .Xc -Sets both filters and format based on the output filename. +Sets both filters and format based on the output filename, optionally +referring to a default extension if the supplied filename does not have a +known one. Supported extensions: .7z, .zip, .jar, .cpio, .iso, .a, .ar, .tar, .tgz, .tar.gz, .tar.bz2, .tar.xz .It Xo .Fn archive_write_set_format_7zip diff --git a/contrib/libarchive/libarchive/archive_write_set_format_7zip.c b/contrib/libarchive/libarchive/archive_write_set_format_7zip.c index 92ad810635..cecc7b4e99 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_7zip.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_7zip.c @@ -314,7 +314,7 @@ static int _7z_compression_init_encoder(struct archive_write *, unsigned, int); static int compression_init_encoder_zstd(struct archive *, struct la_zstream *, int, int); -#if defined(HAVE_ZSTD_H) +#if HAVE_ZSTD_H && HAVE_ZSTD_compressStream static int compression_code_zstd(struct archive *, struct la_zstream *, enum la_zaction); static int compression_end_zstd(struct archive *, struct la_zstream *); @@ -379,7 +379,7 @@ archive_write_set_format_7zip(struct archive *_a) zip->opt_compression = _7Z_BZIP2; #elif defined(HAVE_ZLIB_H) zip->opt_compression = _7Z_DEFLATE; -#elif HAVE_ZSTD_H +#elif HAVE_ZSTD_H && HAVE_ZSTD_compressStream zip->opt_compression = _7Z_ZSTD; #else zip->opt_compression = _7Z_COPY; @@ -841,7 +841,8 @@ copy_out(struct archive_write *a, uint64_t offset, uint64_t length) return (ARCHIVE_FATAL); } if (rs == 0) { - archive_set_error(&(a->archive), 0, + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated 7-Zip archive"); return (ARCHIVE_FATAL); } @@ -1685,7 +1686,7 @@ file_new(struct archive_write *a, struct archive_entry *entry, const char* linkpath; linkpath = archive_entry_symlink_utf8(entry); if (linkpath == NULL) { - free(file); + file_free(file); archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "symlink path could not be converted to UTF-8"); return (ARCHIVE_FAILED); diff --git a/contrib/libarchive/libarchive/archive_write_set_format_ar.c b/contrib/libarchive/libarchive/archive_write_set_format_ar.c index e5e9c806b6..9912835b8f 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_ar.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_ar.c @@ -172,7 +172,7 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry) /* * If we are now at the beginning of the archive, - * we need first write the ar global header. + * we have to write the ar global header first. */ if (!ar->wrote_global_header) { __archive_write_output(a, "!\n", 8); diff --git a/contrib/libarchive/libarchive/archive_write_set_format_cpio_binary.c b/contrib/libarchive/libarchive/archive_write_set_format_cpio_binary.c index 4777e75f29..b0864a0dc9 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_cpio_binary.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_cpio_binary.c @@ -380,12 +380,12 @@ write_header(struct archive_write *a, struct archive_entry *entry) { struct cpio *cpio; const char *p, *path; - int pathlength, ret, ret_final; + int ret, ret_final; int64_t ino; struct cpio_binary_header h; struct archive_string_conv *sconv; struct archive_entry *entry_main; - size_t len; + size_t len, pathlength; cpio = (struct cpio *)a->format_data; ret_final = ARCHIVE_OK; @@ -423,7 +423,7 @@ write_header(struct archive_write *a, struct archive_entry *entry) ret_final = ARCHIVE_WARN; } /* Include trailing null */ - pathlength = (int)len + 1; + pathlength = len + 1; h.h_magic = la_swap16(070707); h.h_dev = la_swap16(archive_entry_dev(entry)); @@ -472,7 +472,13 @@ write_header(struct archive_write *a, struct archive_entry *entry) h.h_majmin = 0; h.h_mtime = la_swap32((uint32_t)archive_entry_mtime(entry)); - h.h_namesize = la_swap16(pathlength); + if (pathlength > 0xffff) { + archive_set_error(&a->archive, ERANGE, + "Filename is too long for cpio format"); + ret_final = ARCHIVE_FAILED; + goto exit_write_header; + } + h.h_namesize = la_swap16((uint16_t)pathlength); /* Non-regular files don't store bodies. */ if (archive_entry_filetype(entry) != AE_IFREG) diff --git a/contrib/libarchive/libarchive/archive_write_set_format_cpio_newc.c b/contrib/libarchive/libarchive/archive_write_set_format_cpio_newc.c index d72434d8ae..e281417bf6 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_cpio_newc.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_cpio_newc.c @@ -219,11 +219,11 @@ write_header(struct archive_write *a, struct archive_entry *entry) int64_t ino; struct cpio *cpio; const char *p, *path; - int pathlength, ret, ret_final; + int ret, ret_final; char h[c_header_size]; struct archive_string_conv *sconv; struct archive_entry *entry_main; - size_t len; + size_t len, pathlength; int pad; cpio = (struct cpio *)a->format_data; @@ -261,7 +261,7 @@ write_header(struct archive_write *a, struct archive_entry *entry) archive_string_conversion_charset_name(sconv)); ret_final = ARCHIVE_WARN; } - pathlength = (int)len + 1; /* Include trailing null. */ + pathlength = len + 1; /* Include trailing null. */ memset(h, 0, c_header_size); format_hex(0x070701, h + c_magic_offset, c_magic_size); @@ -292,7 +292,12 @@ write_header(struct archive_write *a, struct archive_entry *entry) format_hex(0, h + c_rdevminor_offset, c_rdevminor_size); } format_hex(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size); - format_hex(pathlength, h + c_namesize_offset, c_namesize_size); + if (format_hex(pathlength, h + c_namesize_offset, c_namesize_size)) { + archive_set_error(&a->archive, ERANGE, + "Filename is too long for cpio format"); + ret_final = ARCHIVE_FAILED; + goto exit_write_header; + } format_hex(0, h + c_checksum_offset, c_checksum_size); /* Non-regular files don't store bodies. */ diff --git a/contrib/libarchive/libarchive/archive_write_set_format_cpio_odc.c b/contrib/libarchive/libarchive/archive_write_set_format_cpio_odc.c index ffac716b8e..6b9a7f4ec6 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_cpio_odc.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_cpio_odc.c @@ -277,12 +277,12 @@ write_header(struct archive_write *a, struct archive_entry *entry) { struct cpio *cpio; const char *p, *path; - int pathlength, ret, ret_final; + int ret, ret_final; int64_t ino; char h[76]; struct archive_string_conv *sconv; struct archive_entry *entry_main; - size_t len; + size_t len, pathlength; cpio = (struct cpio *)a->format_data; ret_final = ARCHIVE_OK; @@ -320,7 +320,7 @@ write_header(struct archive_write *a, struct archive_entry *entry) ret_final = ARCHIVE_WARN; } /* Include trailing null. */ - pathlength = (int)len + 1; + pathlength = len + 1; memset(h, 0, sizeof(h)); format_octal(070707, h + c_magic_offset, c_magic_size); @@ -351,7 +351,12 @@ write_header(struct archive_write *a, struct archive_entry *entry) else format_octal(0, h + c_rdev_offset, c_rdev_size); format_octal(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size); - format_octal(pathlength, h + c_namesize_offset, c_namesize_size); + if (format_octal((int64_t)pathlength, h + c_namesize_offset, c_namesize_size)) { + archive_set_error(&a->archive, ERANGE, + "Filename is too long for cpio format"); + ret_final = ARCHIVE_FAILED; + goto exit_write_header; + } /* Non-regular files don't store bodies. */ if (archive_entry_filetype(entry) != AE_IFREG) diff --git a/contrib/libarchive/libarchive/archive_write_set_format_gnutar.c b/contrib/libarchive/libarchive/archive_write_set_format_gnutar.c index b67007a631..f2ba4a0db4 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_gnutar.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_gnutar.c @@ -321,7 +321,8 @@ archive_write_gnutar_header(struct archive_write *a, const wchar_t *wp; wp = archive_entry_pathname_w(entry); - if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + if (wp != NULL && wp[0] != L'\0' && + wp[wcslen(wp) - 1] != L'/') { struct archive_wstring ws; archive_string_init(&ws); diff --git a/contrib/libarchive/libarchive/archive_write_set_format_iso9660.c b/contrib/libarchive/libarchive/archive_write_set_format_iso9660.c index 359a273736..e3cf9aad2a 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_iso9660.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_iso9660.c @@ -119,6 +119,8 @@ static const unsigned char zisofs_magic[8] = { #define ZF_LOG2_BS 15 /* log2 block size; 32K bytes. */ #define ZF_BLOCK_SIZE (1UL << ZF_LOG2_BS) +#define MAX_JOLIET_ID_NUM 46656 /* 3 base 36 digits */ + /* * Manage extra records. */ @@ -764,7 +766,7 @@ struct iso9660 { #ifdef HAVE_ZLIB_H /* * Copy a compressed file to iso9660.zisofs.temp_fd - * and also copy a uncompressed file(original file) to + * and also copy an uncompressed file(original file) to * iso9660.temp_fd . If the number of logical block * of the compressed file is less than the number of * logical block of the uncompressed file, use it and @@ -1008,7 +1010,7 @@ static int idr_start(struct archive_write *, struct idr *, static void idr_register(struct idr *, struct isoent *, int, int); static void idr_extend_identifier(struct idrent *, int, int); -static void idr_resolve(struct idr *, void (*)(unsigned char *, int)); +static int idr_resolve(struct idr *, void (*)(unsigned char *, int)); static void idr_set_num(unsigned char *, int); static void idr_set_num_beutf16(unsigned char *, int); static int isoent_gen_iso9660_identifier(struct archive_write *, @@ -1168,6 +1170,7 @@ archive_write_set_format_iso9660(struct archive *_a) iso9660->cur_dirent = iso9660->primary.rootent; archive_string_init(&(iso9660->cur_dirstr)); if (archive_string_ensure(&(iso9660->cur_dirstr), 1) == NULL) { + free(iso9660->cur_dirent); free(iso9660); archive_set_error(&a->archive, ENOMEM, "Can't allocate memory"); @@ -3036,8 +3039,8 @@ set_directory_record_rr(unsigned char *bp, int dr_len, const char *sl; char sl_last; - if (extra_space(&ctl) < 7) - bp = extra_next_record(&ctl, 7); + if (extra_space(&ctl) < 12) + bp = extra_next_record(&ctl, 12); sl = file->symlink.s; sl_last = '\0'; if (bp != NULL) { @@ -4281,9 +4284,11 @@ _write_path_table(struct archive_write *a, int type_m, int depth, set_num_731(bp+3, np->dir_location); /* Parent Directory Number */ if (type_m) - set_num_722(bp+7, np->parent->dir_number); + set_num_722(bp+7, + np->parent != NULL ? np->parent->dir_number : 0); else - set_num_721(bp+7, np->parent->dir_number); + set_num_721(bp+7, + np->parent != NULL ? np->parent->dir_number : 0); /* Directory Identifier */ if (np->identifier == NULL) bp[9] = 0; @@ -4910,20 +4915,29 @@ isofile_gen_utility_names(struct archive_write *a, struct isofile *file) * --> 'dir/dir2/' */ char *rp = p -1; + size_t off; + for (off = 4; p[off] == '/'; off++) + ; while (rp >= dirname) { if (*rp == '/') break; --rp; } if (rp > dirname) { - strcpy(rp, p+3); + memmove(rp + 1, p + off, strlen(p + off) + 1); p = rp; } else { - strcpy(dirname, p+4); + memmove(dirname, p + off, strlen(p + off) + 1); p = dirname; } } else p++; + } else if (p == dirname && p[0] == '.' && p[1] == '.' && p[2] == '/') { + size_t off; + for (off = 3; p[off] == '/'; off++) + ; + memmove(dirname, p + off, strlen(p + off) + 1); + p = dirname; } else p++; } @@ -5526,7 +5540,7 @@ isoent_setup_file_location(struct iso9660 *iso9660, int location) static int get_path_component(char *name, size_t n, const char *fn) { - char *p; + const char *p; size_t l; p = strchr(fn, '/'); @@ -5903,21 +5917,22 @@ idr_register(struct idr *idr, struct isoent *isoent, int weight, int noff) static void idr_extend_identifier(struct idrent *wnp, int numsize, int nullsize) { - unsigned char *p; - int wnp_ext_off; - - wnp_ext_off = wnp->isoent->ext_off; - if (wnp->noff + numsize != wnp_ext_off) { - p = (unsigned char *)wnp->isoent->identifier; - /* Extend the filename; foo.c --> foo___.c */ - memmove(p + wnp->noff + numsize, p + wnp_ext_off, + if (wnp->noff + numsize != wnp->isoent->ext_off) { + /* + * Extend the filename; foo.c --> foo___.c + * + * The caller must verify that enough memory is available. + */ + memmove(wnp->isoent->identifier + wnp->noff + numsize, + wnp->isoent->identifier + wnp->isoent->ext_off, wnp->isoent->ext_len + nullsize); - wnp->isoent->ext_off = wnp_ext_off = wnp->noff + numsize; - wnp->isoent->id_len = wnp_ext_off + wnp->isoent->ext_len; + wnp->isoent->ext_off = wnp->noff + numsize; + wnp->isoent->id_len = + wnp->isoent->ext_off + wnp->isoent->ext_len; } } -static void +static int idr_resolve(struct idr *idr, void (*fsetnum)(unsigned char *p, int num)) { struct idrent *n; @@ -5927,10 +5942,13 @@ idr_resolve(struct idr *idr, void (*fsetnum)(unsigned char *p, int num)) idr_extend_identifier(n, idr->num_size, idr->null_size); p = (unsigned char *)n->isoent->identifier + n->noff; do { + if (n->avail->rename_num >= MAX_JOLIET_ID_NUM) + return (-ERANGE); fsetnum(p, n->avail->rename_num++); } while (!__archive_rb_tree_insert_node( &(idr->rbtree), &(n->rbnode))); } + return (0); } static void @@ -5990,6 +6008,10 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, static const struct archive_rb_tree_ops rb_ops = { isoent_cmp_node_iso9660, isoent_cmp_key_iso9660 }; + const int num_size = 3; + const int dot_size = 1; + const int version_size = 2; + const int null_size = 1; if (isoent->children.cnt == 0) return (0); @@ -6030,7 +6052,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, fnmax = ffmax = dnmax = 207; } - r = idr_start(a, idr, isoent->children.cnt, ffmax, 3, 1, &rb_ops); + r = idr_start(a, idr, isoent->children.cnt, ffmax, num_size, null_size, &rb_ops); if (r < 0) return (r); @@ -6039,7 +6061,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, int ext_off, noff, weight; l = (int)np->file->basename.length; - p = malloc(l+31+2+1); + p = malloc(l + num_size + dot_size + version_size + null_size); if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory"); @@ -6189,13 +6211,19 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, noff = ext_off - 1; else noff = ext_off; + if (noff < 0) + noff = 0; } /* Register entry to the identifier resolver. */ idr_register(idr, np, weight, noff); } /* Resolve duplicate identifier. */ - idr_resolve(idr, idr_set_num); + r = idr_resolve(idr, idr_set_num); + if (r < 0) { + archive_set_error(&a->archive, -r, "Too many duplicated identifiers"); + return (ARCHIVE_FATAL); + } /* Add a period and a version number to identifiers. */ for (np = isoent->children.first; np != NULL; np = np->chnext) { @@ -6239,6 +6267,8 @@ isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent, static const struct archive_rb_tree_ops rb_ops = { isoent_cmp_node_joliet, isoent_cmp_key_joliet }; + const int num_size = 6; + const int null_size = 2; if (isoent->children.cnt == 0) return (0); @@ -6249,7 +6279,7 @@ isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent, else ffmax = 128; - r = idr_start(a, idr, isoent->children.cnt, (int)ffmax, 6, 2, &rb_ops); + r = idr_start(a, idr, isoent->children.cnt, (int)ffmax, num_size, null_size, &rb_ops); if (r < 0) return (r); @@ -6265,7 +6295,7 @@ isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent, if ((l = np->file->basename_utf16.length) > ffmax) l = ffmax; - p = malloc((l+1)*2); + p = malloc(l + num_size + null_size); if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory"); @@ -6334,12 +6364,18 @@ isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent, noff = ext_off - 2; else noff = ext_off; + if (noff < 0) + noff = 0; /* Register entry to the identifier resolver. */ idr_register(idr, np, weight, noff); } /* Resolve duplicate identifier with Joliet Volume. */ - idr_resolve(idr, idr_set_num_beutf16); + r = idr_resolve(idr, idr_set_num_beutf16); + if (r < 0) { + archive_set_error(&a->archive, -r, "Too many duplicated identifiers"); + return (ARCHIVE_FATAL); + } return (ARCHIVE_OK); } @@ -6727,7 +6763,12 @@ isoent_rr_move_dir(struct archive_write *a, struct isoent **rr_moved, /* * The mvent becomes a child of the rr_moved entry. */ - isoent_add_child_tail(rrmoved, mvent); + if (!isoent_add_child_tail(rrmoved, mvent)) { + _isoent_free(mvent); + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Unable to insert rr_moved entry"); + return (ARCHIVE_FATAL); + } archive_entry_set_nlink(rrmoved->file->entry, archive_entry_nlink(rrmoved->file->entry) + 1); /* @@ -6820,7 +6861,15 @@ _compare_path_table(const void *v1, const void *v2) p2 = *((const struct isoent **)(uintptr_t)v2); /* Compare parent directory number */ - cmp = p1->parent->dir_number - p2->parent->dir_number; + if (p1->parent == NULL || p2->parent == NULL) { + if (p1->parent == p2->parent) + cmp = 0; + else if (p1->parent == NULL) + return (-1); + else + return (1); + } else + cmp = p1->parent->dir_number - p2->parent->dir_number; if (cmp != 0) return (cmp); @@ -6863,7 +6912,15 @@ _compare_path_table_joliet(const void *v1, const void *v2) p2 = *((const struct isoent **)(uintptr_t)v2); /* Compare parent directory number */ - cmp = p1->parent->dir_number - p2->parent->dir_number; + if (p1->parent == NULL || p2->parent == NULL) { + if (p1->parent == p2->parent) + cmp = 0; + else if (p1->parent == NULL) + return (-1); + else + return (1); + } else + cmp = p1->parent->dir_number - p2->parent->dir_number; if (cmp != 0) return (cmp); diff --git a/contrib/libarchive/libarchive/archive_write_set_format_mtree.c b/contrib/libarchive/libarchive/archive_write_set_format_mtree.c index a4ffec8954..ed53849bfb 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_mtree.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_mtree.c @@ -307,14 +307,14 @@ static const uint32_t crctab[] = { static const unsigned char safe_char[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */ - /* !"$%&'()*+,-./ EXCLUSION:0x20( ) 0x23(#) */ - 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */ - /* 0123456789:;<>? EXCLUSION:0x3d(=) */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, /* 30 - 3F */ + /* !"$%&'()+,-./ EXCLUSION:0x20( ) 0x23(#) 0x2a(*) */ + 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* 20 - 2F */ + /* 0123456789:;<> EXCLUSION:0x3d(=) 0x3f(?) */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, /* 30 - 3F */ /* @ABCDEFGHIJKLMNO */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */ - /* PQRSTUVWXYZ[]^_ EXCLUSION:0x5c(\) */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, /* 50 - 5F */ + /* PQRSTUVWXYZ]^_ EXCLUSION:0x5b([) 0x5c(\) */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, /* 50 - 5F */ /* `abcdefghijklmno */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */ /* pqrstuvwxyz{|}~ */ @@ -801,6 +801,8 @@ mtree_entry_new(struct archive_write *a, struct archive_entry *entry, archive_strcpy(&me->symlink, s); me->nlink = archive_entry_nlink(entry); me->filetype = archive_entry_filetype(entry); + if (me->filetype == AE_IFLNK && me->symlink.s == NULL) + archive_strcpy(&me->symlink, ""); me->mode = archive_entry_mode(entry) & 07777; me->uid = archive_entry_uid(entry); me->gid = archive_entry_gid(entry); @@ -988,7 +990,8 @@ write_mtree_entry(struct archive_write *a, struct mtree_entry *me) * a full pathname. */ mtree_quote(str, me->parentdir.s); - archive_strappend_char(str, '/'); + if (strcmp(me->basename.s, ".") != 0) + archive_strappend_char(str, '/'); } mtree_quote(str, me->basename.s); @@ -1145,6 +1148,8 @@ write_mtree_entry_tree(struct archive_write *a) int ret; do { + if (np->dir_info == NULL) + break; if (mtree->output_global_set) { /* * Collect attribute information to know which value @@ -1611,6 +1616,7 @@ sum_update(struct mtree_writer *mtree, const void *buff, size_t n) static void sum_final(struct mtree_writer *mtree, struct reg_info *reg) { + struct ae_digest digest; if (mtree->compute_sum & F_CKSUM) { uint64_t len; @@ -1620,40 +1626,34 @@ sum_final(struct mtree_writer *mtree, struct reg_info *reg) reg->crc = ~mtree->crc; } #ifdef ARCHIVE_HAS_MD5 - if ((mtree->compute_sum & F_MD5) - && !(reg->mset_digest & AE_MSET_DIGEST_MD5)) + if (mtree->compute_sum & F_MD5) - archive_md5_final(&mtree->md5ctx, reg->digest.md5); + archive_md5_final(&mtree->md5ctx, (reg->mset_digest & AE_MSET_DIGEST_MD5) ? digest.md5 : reg->digest.md5); #endif #ifdef ARCHIVE_HAS_RMD160 - if ((mtree->compute_sum & F_RMD160) - && !(reg->mset_digest & AE_MSET_DIGEST_RMD160)) + if (mtree->compute_sum & F_RMD160) - archive_rmd160_final(&mtree->rmd160ctx, reg->digest.rmd160); + archive_rmd160_final(&mtree->rmd160ctx, (reg->mset_digest & AE_MSET_DIGEST_RMD160) ? digest.rmd160 : reg->digest.rmd160); #endif #ifdef ARCHIVE_HAS_SHA1 - if ((mtree->compute_sum & F_SHA1) - && !(reg->mset_digest & AE_MSET_DIGEST_SHA1)) + if (mtree->compute_sum & F_SHA1) - archive_sha1_final(&mtree->sha1ctx, reg->digest.sha1); + archive_sha1_final(&mtree->sha1ctx, (reg->mset_digest & AE_MSET_DIGEST_SHA1) ? digest.sha1 : reg->digest.sha1); #endif #ifdef ARCHIVE_HAS_SHA256 - if ((mtree->compute_sum & F_SHA256) - && !(reg->mset_digest & AE_MSET_DIGEST_SHA256)) + if (mtree->compute_sum & F_SHA256) - archive_sha256_final(&mtree->sha256ctx, reg->digest.sha256); + archive_sha256_final(&mtree->sha256ctx, (reg->mset_digest & AE_MSET_DIGEST_SHA256) ? digest.sha256 : reg->digest.sha256); #endif #ifdef ARCHIVE_HAS_SHA384 - if ((mtree->compute_sum & F_SHA384) - && !(reg->mset_digest & AE_MSET_DIGEST_SHA384)) + if (mtree->compute_sum & F_SHA384) - archive_sha384_final(&mtree->sha384ctx, reg->digest.sha384); + archive_sha384_final(&mtree->sha384ctx, (reg->mset_digest & AE_MSET_DIGEST_SHA384) ? digest.sha384 : reg->digest.sha384); #endif #ifdef ARCHIVE_HAS_SHA512 - if ((mtree->compute_sum & F_SHA512) - && !(reg->mset_digest & AE_MSET_DIGEST_SHA512)) + if (mtree->compute_sum & F_SHA512) - archive_sha512_final(&mtree->sha512ctx, reg->digest.sha512); + archive_sha512_final(&mtree->sha512ctx, (reg->mset_digest & AE_MSET_DIGEST_SHA512) ? digest.sha512 : reg->digest.sha512); #endif /* Save what types of sum are computed. */ reg->compute_sum = mtree->compute_sum; @@ -1886,20 +1886,29 @@ mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file, * --> 'dir/dir2/' */ char *rp = p -1; + size_t off; + for (off = 4; p[off] == '/'; off++) + ; while (rp >= dirname) { if (*rp == '/') break; --rp; } if (rp > dirname) { - strcpy(rp, p+3); + memmove(rp + 1, p + off, strlen(p + off) + 1); p = rp; } else { - strcpy(dirname, p+4); + memmove(dirname, p + off, strlen(p + off) + 1); p = dirname; } } else p++; + } else if (p == dirname && p[0] == '.' && p[1] == '.' && p[2] == '/') { + size_t off; + for (off = 3; p[off] == '/'; off++) + ; + memmove(dirname, p + off, strlen(p + off) + 1); + p = dirname; } else p++; } @@ -2041,7 +2050,7 @@ mtree_entry_find_child(struct mtree_entry *parent, const char *child_name) static int get_path_component(char *name, size_t n, const char *fn) { - char *p; + const char *p; size_t l; p = strchr(fn, '/'); @@ -2079,6 +2088,11 @@ mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep) file = *filep; if (file->parentdir.length == 0 && file->basename.length == 1 && file->basename.s[0] == '.') { + if (file->filetype != AE_IFDIR) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Root entry '.' must be a directory"); + return (ARCHIVE_FAILED); + } file->parent = file; if (mtree->root != NULL) { np = mtree->root; diff --git a/contrib/libarchive/libarchive/archive_write_set_format_pax.c b/contrib/libarchive/libarchive/archive_write_set_format_pax.c index f3589d6859..cda1ffd904 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_pax.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_pax.c @@ -40,6 +40,7 @@ #include "archive.h" #include "archive_entry.h" #include "archive_entry_locale.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_write_private.h" #include "archive_write_set_format_private.h" @@ -676,7 +677,8 @@ archive_write_pax_header(struct archive_write *a, const wchar_t *wp; wp = archive_entry_pathname_w(entry_original); - if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + if (wp != NULL && wp[0] != L'\0' && + wp[wcslen(wp) - 1] != L'/') { struct archive_wstring ws; archive_string_init(&ws); @@ -1934,17 +1936,17 @@ url_encode(const char *in) for (s = in; *s != '\0'; s++) { if (*s < 33 || *s > 126 || *s == '%' || *s == '=') { - if (SIZE_MAX - out_len < 4) + if (archive_ckd_add_size(&out_len, out_len, 3)) return (NULL); - out_len += 3; } else { - if (SIZE_MAX - out_len < 2) + if (archive_ckd_add_size(&out_len, out_len, 1)) return (NULL); - out_len++; } } - out = malloc(out_len + 1); + if (archive_ckd_add_size(&out_len, out_len, 1)) + return (NULL); + out = malloc(out_len); if (out == NULL) return (NULL); diff --git a/contrib/libarchive/libarchive/archive_write_set_format_shar.c b/contrib/libarchive/libarchive/archive_write_set_format_shar.c index f6f28debdf..ad8d5b78dc 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_shar.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_shar.c @@ -38,6 +38,7 @@ #endif #include "archive.h" +#include "archive_endian.h" #include "archive_entry.h" #include "archive_private.h" #include "archive_write_private.h" @@ -173,6 +174,10 @@ archive_write_shar_header(struct archive_write *a, struct archive_entry *entry) /* Save the entry for the closing. */ archive_entry_free(shar->entry); shar->entry = archive_entry_clone(entry); + if (shar->entry == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } name = archive_entry_pathname(entry); /* Handle some preparatory issues. */ @@ -408,9 +413,9 @@ static void uuencode_group(const char _in[3], char out[4]) { const unsigned char *in = (const unsigned char *)_in; - int t; + uint32_t t; - t = (in[0] << 16) | (in[1] << 8) | in[2]; + t = archive_be24dec(in); out[0] = UUENC( 0x3f & (t >> 18) ); out[1] = UUENC( 0x3f & (t >> 12) ); out[2] = UUENC( 0x3f & (t >> 6) ); diff --git a/contrib/libarchive/libarchive/archive_write_set_format_ustar.c b/contrib/libarchive/libarchive/archive_write_set_format_ustar.c index 97724c1588..e84152ea18 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_ustar.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_ustar.c @@ -281,7 +281,8 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry) const wchar_t *wp; wp = archive_entry_pathname_w(entry); - if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + if (wp != NULL && wp[0] != L'\0' && + wp[wcslen(wp) - 1] != L'/') { struct archive_wstring ws; archive_string_init(&ws); diff --git a/contrib/libarchive/libarchive/archive_write_set_format_v7tar.c b/contrib/libarchive/libarchive/archive_write_set_format_v7tar.c index 37ba73a132..91c5e8e42f 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_v7tar.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_v7tar.c @@ -259,7 +259,8 @@ archive_write_v7tar_header(struct archive_write *a, struct archive_entry *entry) const wchar_t *wp; wp = archive_entry_pathname_w(entry); - if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + if (wp != NULL && wp[0] != L'\0' && + wp[wcslen(wp) - 1] != L'/') { struct archive_wstring ws; archive_string_init(&ws); diff --git a/contrib/libarchive/libarchive/archive_write_set_format_warc.c b/contrib/libarchive/libarchive/archive_write_set_format_warc.c index 3d22e1f4ba..2192995362 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_warc.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_warc.c @@ -245,6 +245,7 @@ _warc_header(struct archive_write *a, struct archive_entry *entry) r = _popul_ehdr(&hdr, MAX_HDR_SIZE, rh); if (r < 0) { /* don't bother */ + archive_string_free(&hdr); archive_set_error( &a->archive, ARCHIVE_ERRNO_FILE_FORMAT, @@ -371,7 +372,7 @@ _popul_ehdr(struct archive_string *tgt, size_t tsz, warc_essential_hdr_t hdr) static const char _uri[] = ""; static const char _fil[] = "file://"; const char *u; - char *chk = strchr(hdr.tgturi, ':'); + const char *chk = strchr(hdr.tgturi, ':'); if (chk != NULL && chk[1U] == '/' && chk[2U] == '/') { /* yep, it's definitely a URI */ diff --git a/contrib/libarchive/libarchive/archive_write_set_format_xar.c b/contrib/libarchive/libarchive/archive_write_set_format_xar.c index 6ecccdef64..98bc4952da 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_xar.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_xar.c @@ -819,9 +819,7 @@ xar_finish_entry(struct archive_write *a) if (s > a->null_length) s = a->null_length; w = xar_write_data(a, a->nulls, s); - if (w > 0) - xar->bytes_remaining -= w; - else + if (w <= 0) return ((int)w); } file = xar->cur_file; @@ -1110,30 +1108,27 @@ make_fflags_entry(struct archive_write *a, struct xml_writer *writer, { NULL, NULL} }; const struct flagentry *fe, *flagentry; -#define FLAGENTRY_MAXSIZE ((sizeof(flagbsd)+sizeof(flagext2))/sizeof(flagbsd)) - const struct flagentry *avail[FLAGENTRY_MAXSIZE]; const char *p; - int i, n, r; + int r, started; if (strcmp(element, "ext2") == 0) flagentry = flagext2; else flagentry = flagbsd; - n = 0; p = fflags_text; + started = 0; do { - const char *cp; + const char *cp, *name = NULL; cp = strchr(p, ','); if (cp == NULL) cp = p + strlen(p); for (fe = flagentry; fe->name != NULL; fe++) { - if (fe->name[cp - p] != '\0' - || p[0] != fe->name[0]) - continue; if (strncmp(p, fe->name, cp - p) == 0) { - avail[n++] = fe; + if (fe->name[cp - p] != '\0') + continue; + name = fe->xarname; break; } } @@ -1141,23 +1136,26 @@ make_fflags_entry(struct archive_write *a, struct xml_writer *writer, p = cp + 1; else p = NULL; - } while (p != NULL); - if (n > 0) { - r = xml_writer_start_element(writer, element); - if (r < 0) { - archive_set_error(&a->archive, - ARCHIVE_ERRNO_MISC, - "xml_writer_start_element() failed: %d", r); - return (ARCHIVE_FATAL); - } - for (i = 0; i < n; i++) { - r = xmlwrite_string(a, writer, - avail[i]->xarname, NULL); + if (name != NULL) { + if (!started) { + r = xml_writer_start_element(writer, element); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xml_writer_start_element()" + " failed: %d", r); + return (ARCHIVE_FATAL); + } + started = 1; + } + r = xmlwrite_string(a, writer, name, NULL); if (r != ARCHIVE_OK) return (r); } + } while (p != NULL); + if (started) { r = xml_writer_end_element(writer); if (r < 0) { archive_set_error(&a->archive, @@ -1439,7 +1437,7 @@ make_file_entry(struct archive_write *a, struct xml_writer *writer, } /* - * Make a mtime entry, "". + * Make an mtime entry, "". */ if (archive_entry_mtime_is_set(file->entry)) { r = xmlwrite_time(a, writer, "mtime", @@ -1866,7 +1864,8 @@ copy_out(struct archive_write *a, uint64_t offset, uint64_t length) return (ARCHIVE_FATAL); } if (rs == 0) { - archive_set_error(&(a->archive), 0, + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated xar archive"); return (ARCHIVE_FATAL); } @@ -2205,20 +2204,29 @@ file_gen_utility_names(struct archive_write *a, struct file *file) * --> 'dir/dir2/' */ char *rp = p -1; + size_t off; + for (off = 4; p[off] == '/'; off++) + ; while (rp >= dirname) { if (*rp == '/') break; --rp; } if (rp > dirname) { - strcpy(rp, p+3); + memmove(rp + 1, p + off, strlen(p + off) + 1); p = rp; } else { - strcpy(dirname, p+4); + memmove(dirname, p + off, strlen(p + off) + 1); p = dirname; } } else p++; + } else if (p == dirname && p[0] == '.' && p[1] == '.' && p[2] == '/') { + size_t off; + for (off = 3; p[off] == '/'; off++) + ; + memmove(dirname, p + off, strlen(p + off) + 1); + p = dirname; } else p++; } @@ -2272,7 +2280,7 @@ file_gen_utility_names(struct archive_write *a, struct file *file) static int get_path_component(char *name, int n, const char *fn) { - char *p; + const char *p; int l; p = strchr(fn, '/'); @@ -2378,10 +2386,24 @@ file_tree(struct archive_write *a, struct file **filepp) archive_string_init(&as); archive_strncat(&as, p, fn - p + l); - if (as.s[as.length-1] == '/') { + if (as.length > 0 && as.s[as.length-1] == '/') { as.s[as.length-1] = '\0'; as.length--; } + if (as.length == 0) { + archive_string_free(&as); + fn += strspn(fn, "/"); + l = get_path_component(name, sizeof(name), fn); + if (l < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "A name buffer is too small"); + file_free(file); + *filepp = NULL; + return (ARCHIVE_FATAL); + } + continue; + } vp = file_create_virtual_dir(a, xar, as.s); if (vp == NULL) { archive_string_free(&as); diff --git a/contrib/libarchive/libarchive/archive_write_set_format_zip.c b/contrib/libarchive/libarchive/archive_write_set_format_zip.c index 81d3db0db0..33d60ce864 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_zip.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_zip.c @@ -797,6 +797,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) unsigned char *e; unsigned char *cd_extra; size_t filename_length; + const char *path; const char *slink = NULL; size_t slink_size = 0; struct archive_string_conv *sconv = get_sconv(a, zip); @@ -960,6 +961,19 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) } filename_length = path_length(zip->entry); + /* Reject empty or overlong pathnames */ + path = archive_entry_pathname(zip->entry); + if (path == NULL || path[0] == '\0') { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "ZIP format requires a non-empty pathname"); + return (ARCHIVE_FAILED); + } + if (filename_length > 0xffff) { + archive_set_error(&a->archive, ENAMETOOLONG, + "Pathname too long for ZIP format"); + return (ARCHIVE_FAILED); + } + /* Determine appropriate compression and size for this entry. */ if (type == AE_IFLNK) { slink = archive_entry_symlink(zip->entry); @@ -2304,7 +2318,7 @@ write_path(struct archive_entry *entry, struct archive_write *archive) written_bytes += strlen(path); /* Folders are recognized by a trailing slash. */ - if ((type == AE_IFDIR) & (path[strlen(path) - 1] != '/')) { + if ((type == AE_IFDIR) && (path[strlen(path) - 1] != '/')) { ret = __archive_write_output(archive, "/", 1); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); diff --git a/contrib/libarchive/libarchive/libarchive-formats.5 b/contrib/libarchive/libarchive/libarchive-formats.5 index 1b057b4da0..eb720eb740 100644 --- a/contrib/libarchive/libarchive/libarchive-formats.5 +++ b/contrib/libarchive/libarchive/libarchive-formats.5 @@ -210,7 +210,7 @@ values of varying byte order and length. .Bl -tag -width indent .It Cm binary The libarchive library transparently reads both big-endian and -little-endian variants of the the two binary cpio formats; the +little-endian variants of the two binary cpio formats; the original one from PWB/UNIX, and the later, more widely used, variant. This format used 32-bit binary values for file size and mtime, and 16-bit binary values for the other fields. The formats support only diff --git a/contrib/libarchive/libarchive/test/test_acl_nfs4_null_id_overflow.c b/contrib/libarchive/libarchive/test/test_acl_nfs4_null_id_overflow.c new file mode 100644 index 0000000000..590c704595 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_acl_nfs4_null_id_overflow.c @@ -0,0 +1,105 @@ +/*- + * 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" + +/* + * A USER NFSv4 ACL entry with a NULL name and a large numeric qualifier + * triggers a heap buffer overflow in archive_acl_to_text_l(). + * + * archive_acl_text_len() only reserves space for the trailing ":id" digits + * when ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID is set, but the serializer always + * writes them for USER/GROUP entries when the name is NULL. With a 7-digit + * ID the allocated buffer is too short and append_id() writes past its end. + * + * Without the fix, libarchive's own post-write guard fires: + * "Fatal Internal Error: Buffer overrun" + * (or under AddressSanitizer a heap-buffer-overflow is reported at + * archive_acl.c in append_id / append_entry). + */ +DEFINE_TEST(test_acl_nfs4_null_id_overflow) +{ + struct archive_entry *ae; + char *text; + ssize_t len; + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0644); + + /* NULL name + 7-digit id: the missing ":9999999" overflows the buffer */ + archive_entry_acl_add_entry(ae, + ARCHIVE_ENTRY_ACL_TYPE_DENY, + 0, + ARCHIVE_ENTRY_ACL_USER, + 9999999, + NULL); + + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + assert(text != NULL); + /* The numeric id must appear in the output as the user name */ + assert(strstr(text, "9999999") != NULL); + free(text); + + archive_entry_free(ae); +} + +/* + * The wide (wchar_t) serializer has a related bug: when the name is NULL + * it passes id=-1 to append_entry_w() instead of the actual numeric id, + * so the id is never written and a garbage character appears in the name + * slot instead. + * + * The wide estimator has the same missing-id-digits gap as the narrow one, + * and both must be fixed together with the wide serializer. + */ +DEFINE_TEST(test_acl_nfs4_null_id_overflow_w) +{ + struct archive_entry *ae; + wchar_t *wtext; + ssize_t len; + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0644); + + archive_entry_acl_add_entry(ae, + ARCHIVE_ENTRY_ACL_TYPE_DENY, + 0, + ARCHIVE_ENTRY_ACL_USER, + 9999999, + NULL); + + wtext = archive_entry_acl_to_text_w(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + assert(wtext != NULL); + /* The numeric id must appear in the output as the user name */ + assert(wcsstr(wtext, L"9999999") != NULL); + free(wtext); + + archive_entry_free(ae); +} diff --git a/contrib/libarchive/libarchive/test/test_acl_nfs4_text.c b/contrib/libarchive/libarchive/test/test_acl_nfs4_text.c new file mode 100644 index 0000000000..165d18ed8f --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_acl_nfs4_text.c @@ -0,0 +1,426 @@ +/*- + * 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" +#include + +/* + * Focused tests for NFSv4 ACL text parsing and serialization. + * + * test_acl_text.c already covers basic round-trips with well-formed input. + * These tests probe areas not reached there: all four ACL types, numeric IDs, + * extra-ID field override, isint() overflow, malformed entries, compact mode, + * and the wide-char path. + */ + +/* NFSv4 text in standard (no extra ID), extra-ID, and compact+extra-ID forms. + * These are the same strings used in test_acl_text.c acltext[9..11]. */ +static const char *nfs4_std = + "user:user77:rw-p--a-R-c-o-:-------:allow\n" + "user:user101:-w-pdD--------:fdin---:deny\n" + "group:group78:r-----a-R-c---:------I:allow\n" + "owner@:rwxp--aARWcCo-:-------:allow\n" + "group@:rw-p--a-R-c---:-------:allow\n" + "everyone@:r-----a-R-c--s:-------:allow"; + +static const char *nfs4_extra_id = + "user:user77:rw-p--a-R-c-o-:-------:allow:77\n" + "user:user101:-w-pdD--------:fdin---:deny:101\n" + "group:group78:r-----a-R-c---:------I:allow:78\n" + "owner@:rwxp--aARWcCo-:-------:allow\n" + "group@:rw-p--a-R-c---:-------:allow\n" + "everyone@:r-----a-R-c--s:-------:allow"; + +static const char *nfs4_compact = + "user:user77:rwpaRco::allow:77\n" + "user:user101:wpdD:fdin:deny:101\n" + "group:group78:raRc:I:allow:78\n" + "owner@:rwxpaARWcCo::allow\n" + "group@:rwpaRc::allow\n" + "everyone@:raRcs::allow"; + +static wchar_t * +s_to_ws(const char *s) +{ + size_t len = strlen(s) + 1; + wchar_t *ws = malloc(len * sizeof(wchar_t)); + assert(ws != NULL); + assert(mbstowcs(ws, s, len) != (size_t)-1); + return (ws); +} + +/* + * Round-trip: parse NFS4 text → serialize → compare. + * Covers standard, extra-ID, and compact+extra-ID formats, + * for both the narrow and wide serializers. + */ +DEFINE_TEST(test_acl_nfs4_text_roundtrip) +{ + struct archive_entry *ae; + char *text; + wchar_t *wtext, *ws; + ssize_t len; + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0644); + + /* Standard format */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, nfs4_std, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + assertEqualString(nfs4_std, text); + free(text); + archive_entry_acl_clear(ae); + + /* Extra-ID format: trailing :id must be preserved */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, nfs4_extra_id, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4 | ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID); + assertEqualString(nfs4_extra_id, text); + free(text); + archive_entry_acl_clear(ae); + + /* Compact format: empty perm/flag fields must round-trip */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, nfs4_compact, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4 | + ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID | + ARCHIVE_ENTRY_ACL_STYLE_COMPACT); + assertEqualString(nfs4_compact, text); + free(text); + archive_entry_acl_clear(ae); + + /* Wide: standard format */ + ws = s_to_ws(nfs4_std); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text_w(ae, ws, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + wtext = archive_entry_acl_to_text_w(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + assertEqualWString(ws, wtext); + free(wtext); + free(ws); + archive_entry_acl_clear(ae); + + /* Wide: compact+extra-ID format */ + ws = s_to_ws(nfs4_compact); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text_w(ae, ws, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + wtext = archive_entry_acl_to_text_w(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4 | + ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID | + ARCHIVE_ENTRY_ACL_STYLE_COMPACT); + assertEqualWString(ws, wtext); + free(wtext); + free(ws); + archive_entry_acl_clear(ae); + + archive_entry_free(ae); +} + +/* + * All four ACL entry types: allow, deny, audit, alarm. + * test_acl_text.c only exercises allow and deny. + */ +DEFINE_TEST(test_acl_nfs4_text_types) +{ + struct archive_entry *ae; + char *text; + wchar_t *wtext, *ws; + ssize_t len; + int type, permset, tag, qual; + const char *name; + static const char *audit_alarm_text = + "user:alice:rw-p--aARWcCos:-------:audit\n" + "group:staff:rw-p--aARWcCos:-------:alarm"; + + ae = archive_entry_new(); + assert(ae != NULL); + + /* Parse and verify both audit and alarm entries are stored */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, audit_alarm_text, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(2, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_AUDIT, type); + assertEqualString("alice", name); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ALARM, type); + assertEqualString("staff", name); + + /* Round-trip: serialize then compare */ + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + assertEqualString(audit_alarm_text, text); + + /* Verify same round-trip via wide path */ + ws = s_to_ws(audit_alarm_text); + wtext = archive_entry_acl_to_text_w(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + assertEqualWString(ws, wtext); + free(ws); + free(wtext); + free(text); + + archive_entry_free(ae); +} + +/* + * Numeric IDs in the name field and the extra-ID override field. + * + * 1. "user:1000:..." — the name field is a pure number; id is set from it. + * 2. "user:name:...:42" — the trailing id field overrides any id derived + * from the name. + * 3. "user:1000:...:42" — trailing id overrides even a numeric name. + * 4. isint() overflow: a field with more than 10 digits is clamped to INT_MAX. + */ +DEFINE_TEST(test_acl_nfs4_text_numeric_id) +{ + struct archive_entry *ae; + char *text; + ssize_t len; + int type, permset, tag, qual; + const char *name; + + ae = archive_entry_new(); + assert(ae != NULL); + + /* 1. Numeric-only name → id derived from name field */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, + "user:1000:rw-p--a-R-c-o-:-------:allow", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(1, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(1000, qual); + assertEqualString("1000", name); + /* Without EXTRA_ID the id is carried by the name string, not :id */ + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + assertEqualString("user:1000:rw-p--a-R-c-o-:-------:allow", text); + free(text); + /* With EXTRA_ID the id is appended */ + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4 | ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID); + assertEqualString("user:1000:rw-p--a-R-c-o-:-------:allow:1000", text); + free(text); + archive_entry_acl_clear(ae); + + /* 2. Trailing extra-ID field overrides name-derived id */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, + "user:user77:rw-p--a-R-c-o-:-------:allow:42", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(1, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(42, qual); + assertEqualString("user77", name); + archive_entry_acl_clear(ae); + + /* 3. Trailing extra-ID also overrides a numeric name */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, + "user:1000:rw-p--a-R-c-o-:-------:allow:42", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(1, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(42, qual); + archive_entry_acl_clear(ae); + + /* 4. isint() overflow: extra-ID field too large → entry rejected */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user:name:rw-p--a-R-c-o-:-------:allow:99999999999", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + /* 5. INT_MAX (2147483647) in the extra-ID field → also rejected */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user:name:rw-p--a-R-c-o-:-------:allow:2147483647", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + /* 6. INT_MAX - 1 (2147483646) is the largest accepted id */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, + "user:name:rw-p--a-R-c-o-:-------:allow:2147483646", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(1, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(2147483646, qual); + archive_entry_acl_clear(ae); + + /* 7. Overflow in the name field (numeric name too large) → rejected */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user:99999999999:rw-p--a-R-c-o-:-------:allow", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + archive_entry_free(ae); +} + +/* + * Malformed NFS4 ACL entries — each should return ARCHIVE_WARN without + * crashing. Also verifies that valid entries before an invalid one are + * still stored. + */ +DEFINE_TEST(test_acl_nfs4_text_invalid) +{ + struct archive_entry *ae; + int type, permset, tag, qual; + const char *name; + + ae = archive_entry_new(); + assert(ae != NULL); + + /* Unknown tag */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "bogus:name:rw-p--a-R-c-o-:-------:allow", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + /* Unknown type string */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user:name:rw-p--a-R-c-o-:-------:bogus", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + /* Invalid character in perms field */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user:name:rq-p--a-R-c-o-:-------:allow", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + /* Invalid character in flags field */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user:name:rw-p--a-R-c-o-:q------:allow", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + /* Just a tag with no colon-separated fields */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, "user", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + /* Valid entry followed by an invalid one: valid entry must be stored + * and ARCHIVE_WARN returned (not ARCHIVE_FATAL). */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user:alice:rw-p--a-R-c-o-:-------:allow\n" + "bogus:bob:rw-p--a-R-c-o-:-------:deny", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(1, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ALLOW, type); + assertEqualString("alice", name); + archive_entry_acl_clear(ae); + + /* Same tests via the wide parser */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text_w(ae, + L"bogus:name:rw-p--a-R-c-o-:-------:allow", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text_w(ae, + L"user:name:rw-p--a-R-c-o-:-------:bogus", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text_w(ae, + L"user:name:rq-p--a-R-c-o-:-------:allow", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text_w(ae, + L"user:name:rw-p--a-R-c-o-:q------:allow", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + archive_entry_free(ae); +} diff --git a/contrib/libarchive/libarchive/test/test_acl_posix1e_text.c b/contrib/libarchive/libarchive/test/test_acl_posix1e_text.c new file mode 100644 index 0000000000..57084465d5 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_acl_posix1e_text.c @@ -0,0 +1,530 @@ +/*- + * 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" +#include + +/* + * Focused tests for POSIX.1e ACL text parsing and serialization. + * + * test_acl_text.c covers basic POSIX.1e round-trips but does not exercise: + * the mask entry, the Solaris two-field format for mask and other, uppercase + * mode letters (R/W/X), isint() overflow on the POSIX path, and various + * invalid-input error paths. These tests fill those gaps. + * + * Note: archive_entry_acl_reset(ae, TYPE_ACCESS) always returns the count + * of extended ACL entries PLUS 3 synthesized base entries (USER_OBJ, + * GROUP_OBJ, OTHER) derived from the mode bits. Tests below account for + * this by adding 3 to the expected count and skipping those 3 entries + * before iterating over the named/mask entries of interest. + */ + +/* ACCESS-only ACL including a mask entry. */ +static const char *posix1e_access = + "user::rwx\n" + "group::r-x\n" + "other::r-x\n" + "user:alice:r-x\n" + "group:staff:rwx\n" + "mask::r-x"; + +/* Combined ACCESS + DEFAULT ACL, with mask in both sections. */ +static const char *posix1e_full = + "user::rwx\n" + "group::r-x\n" + "other::r-x\n" + "user:alice:r-x\n" + "group:staff:rwx\n" + "mask::r-x\n" + "default:user::r-x\n" + "default:group::r-x\n" + "default:other::---\n" + "default:user:alice:r-x\n" + "default:group:staff:--x\n" + "default:mask::r-x"; + +/* posix1e_full with numeric IDs appended to named user/group entries. */ +static const char *posix1e_extra_id = + "user::rwx\n" + "group::r-x\n" + "other::r-x\n" + "user:alice:r-x:77\n" + "group:staff:rwx:78\n" + "mask::r-x\n" + "default:user::r-x\n" + "default:group::r-x\n" + "default:other::---\n" + "default:user:alice:r-x:77\n" + "default:group:staff:--x:78\n" + "default:mask::r-x"; + +/* + * Solaris-style ACCESS ACL: mask and other use one colon (no empty name + * field between tag and permission string). + */ +static const char *posix1e_solaris = + "user::rwx\n" + "group::r-x\n" + "other:r-x\n" + "user:alice:r-x\n" + "mask:r-x"; + +static wchar_t * +s_to_ws(const char *s) +{ + size_t len = strlen(s) + 1; + wchar_t *ws = malloc(len * sizeof(wchar_t)); + assert(ws != NULL); + assert(mbstowcs(ws, s, len) != (size_t)-1); + return (ws); +} + +/* + * Skip the three base entries (USER_OBJ, GROUP_OBJ, OTHER) that + * archive_entry_acl_reset() synthesises from mode bits and that + * archive_entry_acl_next() always returns first for ACCESS ACLs. + */ +static void +skip_base_entries(struct archive_entry *ae) +{ + int type, permset, tag, qual; + const char *name; + int i; + + for (i = 0; i < 3; i++) + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name); +} + +/* + * Round-trip: parse POSIX.1e text → serialize → compare. + * Covers ACCESS-only, combined ACCESS+DEFAULT, and the EXTRA_ID style, + * for both the narrow and wide serializers. + */ +DEFINE_TEST(test_acl_posix1e_text_roundtrip) +{ + struct archive_entry *ae; + char *text; + wchar_t *wtext, *ws; + ssize_t len; + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* ACCESS-only with mask entry */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, posix1e_access, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + assertEqualString(posix1e_access, text); + free(text); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Combined ACCESS + DEFAULT — serializer auto-adds MARK_DEFAULT */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, posix1e_full, + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)); + text = archive_entry_acl_to_text(ae, &len, 0); + assertEqualString(posix1e_full, text); + free(text); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* EXTRA_ID format */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, posix1e_extra_id, + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)); + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID); + assertEqualString(posix1e_extra_id, text); + free(text); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Wide: ACCESS-only round-trip */ + ws = s_to_ws(posix1e_access); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text_w(ae, ws, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + wtext = archive_entry_acl_to_text_w(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + assertEqualWString(ws, wtext); + free(wtext); + free(ws); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Wide: combined ACCESS + DEFAULT */ + ws = s_to_ws(posix1e_full); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text_w(ae, ws, + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)); + wtext = archive_entry_acl_to_text_w(ae, &len, 0); + assertEqualWString(ws, wtext); + free(wtext); + free(ws); + + archive_entry_free(ae); +} + +/* + * Solaris two-field format: "mask:rwx" and "other:rwx" omit the empty + * name field, so each has only two colon-separated tokens instead of three. + * The parser recognises this form; the serializer reproduces it when + * ARCHIVE_ENTRY_ACL_STYLE_SOLARIS is set. + */ +DEFINE_TEST(test_acl_posix1e_text_solaris) +{ + struct archive_entry *ae; + char *text; + int type, permset, tag, qual; + const char *name; + ssize_t len; + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* + * Parse Solaris-format text. Extended entries are: named user alice + * and mask — 2 extended + 3 base = 5 total. + */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, posix1e_solaris, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(5, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + skip_base_entries(ae); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(ARCHIVE_ENTRY_ACL_USER, tag); + assertEqualString("alice", name); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(ARCHIVE_ENTRY_ACL_MASK, tag); + assertEqualInt(ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_EXECUTE, + permset); + + /* Serialize with STYLE_SOLARIS and compare */ + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS | ARCHIVE_ENTRY_ACL_STYLE_SOLARIS); + assertEqualString(posix1e_solaris, text); + free(text); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Solaris style with non-empty name on other field → ARCHIVE_WARN */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user::rwx\ngroup::r-x\nother:nobody:r-x\n", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + + archive_entry_free(ae); +} + +/* + * ismode() accepts uppercase R, W, X as well as lowercase; the serializer + * always emits lowercase. Both narrow and wide parsers share this + * behaviour. + */ +DEFINE_TEST(test_acl_posix1e_text_ismode) +{ + struct archive_entry *ae; + char *text; + int type, permset, tag, qual; + const char *name; + ssize_t len; + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* + * Uppercase R/W/X treated identically to r/w/x. + * 1 extended entry (alice) + 3 base = 4 total. + */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, + "user::RWX\ngroup::R-X\nother::---\nuser:alice:RwX", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(4, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + skip_base_entries(ae); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(ARCHIVE_ENTRY_ACL_USER, tag); + assertEqualString("alice", name); + assertEqualInt( + ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_WRITE | + ARCHIVE_ENTRY_ACL_EXECUTE, permset); + + /* Serializer always emits lowercase */ + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + assertEqualString( + "user::rwx\ngroup::r-x\nother::---\nuser:alice:rwx", text); + free(text); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Same via the wide parser */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text_w(ae, + L"user::RWX\ngroup::R-X\nother::---\nuser:alice:RwX", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(4, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + skip_base_entries(ae); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt( + ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_WRITE | + ARCHIVE_ENTRY_ACL_EXECUTE, permset); + + archive_entry_free(ae); +} + +/* + * Numeric IDs in the name field and the extra-ID override field, + * including the isint() overflow boundary now enforced on the POSIX path. + */ +DEFINE_TEST(test_acl_posix1e_text_numeric_id) +{ + struct archive_entry *ae; + char *text; + ssize_t len; + int type, permset, tag, qual; + const char *name; + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* 1. Numeric-only name → id derived from name field */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, + "user::rwx\ngroup::r-x\nother::r-x\nuser:1000:rwx", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + /* 1 extended + 3 base = 4 */ + assertEqualInt(4, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + skip_base_entries(ae); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(1000, qual); + assertEqualString("1000", name); + /* Without EXTRA_ID the id is carried by the name string */ + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + assert(strstr(text, "user:1000:rwx") != NULL); + free(text); + /* With EXTRA_ID the id is also appended */ + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS | ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID); + assert(strstr(text, "user:1000:rwx:1000") != NULL); + free(text); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* 2. Trailing extra-ID field overrides name-derived id */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, + "user::rwx\ngroup::r-x\nother::r-x\nuser:alice:r-x:42", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(4, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + skip_base_entries(ae); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(42, qual); + assertEqualString("alice", name); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* 3. Overflow in extra-ID field → extended entry rejected, no ext entries */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user::rwx\ngroup::r-x\nother::r-x\nuser:alice:r-x:99999999999", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* 4. INT_MAX (2147483647) in the extra-ID field → also rejected */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user::rwx\ngroup::r-x\nother::r-x\nuser:alice:r-x:2147483647", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* 5. INT_MAX - 1 (2147483646) is the largest accepted id */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, + "user::rwx\ngroup::r-x\nother::r-x\nuser:alice:r-x:2147483646", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(4, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + skip_base_entries(ae); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(2147483646, qual); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* 6. Overflow in the name field (all-digit name too large) → rejected */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user::rwx\ngroup::r-x\nother::r-x\nuser:99999999999:r-x", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + + archive_entry_free(ae); +} + +/* + * Malformed POSIX.1e ACL entries — each should return ARCHIVE_WARN without + * crashing and without storing invalid data. + */ +DEFINE_TEST(test_acl_posix1e_text_invalid) +{ + struct archive_entry *ae; + int type, permset, tag, qual; + const char *name; + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Invalid character in permission field */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user:alice:rqx", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Unknown tag */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "bogus:alice:rwx", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* NFSv4 "everyone@" tag is not recognised by the POSIX parser */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "everyone@:r-----a-R-c--s:-------:allow", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Bare tag with no colon-separated fields */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, "user", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* + * Valid entry followed by invalid — valid entry must be stored. + * 1 extended (alice) + 3 base = 4 total. + */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user::rwx\ngroup::r-x\nother::r-x\n" + "user:alice:r-x\n" + "bogus:bob:rwx", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(4, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + skip_base_entries(ae); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(ARCHIVE_ENTRY_ACL_USER, tag); + assertEqualString("alice", name); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Wide parser: invalid permission character */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text_w(ae, + L"user:alice:rqx", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Wide parser: unknown tag */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text_w(ae, + L"bogus:alice:rwx", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Wide parser: NFSv4 tag rejected by POSIX parser */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text_w(ae, + L"everyone@:r-----a-R-c--s:-------:allow", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + + archive_entry_free(ae); +} diff --git a/contrib/libarchive/libarchive/test/test_archive_match_path.c b/contrib/libarchive/libarchive/test/test_archive_match_path.c index ce48263f76..527413db79 100644 --- a/contrib/libarchive/libarchive/test/test_archive_match_path.c +++ b/contrib/libarchive/libarchive/test/test_archive_match_path.c @@ -233,8 +233,8 @@ test_inclusion_mbs(void) return; } - /* Test for pattern "^aa*" */ - assertEqualIntA(m, 0, archive_match_include_pattern(m, "^aa*")); + /* Test for pattern "aa*" */ + assertEqualIntA(m, 0, archive_match_include_pattern(m, "aa*")); /* Test with 'aa1234', which should not be excluded. */ archive_entry_copy_pathname(ae, "aa1234"); @@ -282,8 +282,8 @@ test_inclusion_wcs(void) return; } - /* Test for pattern "^aa*" */ - assertEqualIntA(m, 0, archive_match_include_pattern_w(m, L"^aa*")); + /* Test for pattern "aa*" */ + assertEqualIntA(m, 0, archive_match_include_pattern_w(m, L"aa*")); /* Test with 'aa1234', which should not be excluded. */ archive_entry_copy_pathname(ae, "aa1234"); @@ -383,8 +383,8 @@ test_exclusion_and_inclusion(void) } assertEqualIntA(m, 0, archive_match_exclude_pattern(m, "^aaa*")); - assertEqualIntA(m, 0, archive_match_include_pattern_w(m, L"^aa*")); - assertEqualIntA(m, 0, archive_match_include_pattern(m, "^a1*")); + assertEqualIntA(m, 0, archive_match_include_pattern_w(m, L"aa*")); + assertEqualIntA(m, 0, archive_match_include_pattern(m, "a1*")); /* Test with 'aa1234', which should not be excluded. */ archive_entry_copy_pathname(ae, "aa1234"); @@ -413,13 +413,13 @@ test_exclusion_and_inclusion(void) /* Verify unmatched inclusion patterns. */ assertEqualIntA(m, ARCHIVE_OK, archive_match_path_unmatched_inclusions_next(m, &mp)); - assertEqualString("^a1*", mp); + assertEqualString("a1*", mp); assertEqualIntA(m, ARCHIVE_EOF, archive_match_path_unmatched_inclusions_next(m, &mp)); /* Verify unmatched inclusion patterns again in Wide-Char. */ assertEqualIntA(m, ARCHIVE_OK, archive_match_path_unmatched_inclusions_next_w(m, &wp)); - assertEqualWString(L"^a1*", wp); + assertEqualWString(L"a1*", wp); assertEqualIntA(m, ARCHIVE_EOF, archive_match_path_unmatched_inclusions_next_w(m, &wp)); diff --git a/contrib/libarchive/libarchive/test/test_archive_parse_date.c b/contrib/libarchive/libarchive/test/test_archive_parse_date.c index 5251b33939..03e6289136 100644 --- a/contrib/libarchive/libarchive/test/test_archive_parse_date.c +++ b/contrib/libarchive/libarchive/test/test_archive_parse_date.c @@ -35,65 +35,72 @@ DEFINE_TEST(test_archive_parse_date) { time_t now = time(NULL); + long long expected; - assertEqualInt(get_date(now, "Jan 1, 1970 UTC"), 0); - assertEqualInt(get_date(now, "7:12:18-0530 4 May 1983"), 420900138); - assertEqualInt(get_date(now, "2004/01/29 513 mest"), 1075345980); - assertEqualInt(get_date(now, "2038-06-01 00:01:02 UTC"), + assertEqualInt(archive_parse_date(now, "Jan 1, 1970 UTC"), 0); + assertEqualInt(archive_parse_date(now, "7:12:18-0530 4 May 1983"), 420900138); + assertEqualInt(archive_parse_date(now, "2004/01/29 513 mest"), 1075345980); + assertEqualInt(archive_parse_date(now, "2038-06-01 00:01:02 UTC"), sizeof(time_t) <= 4 ? -1 : 2158963262); - assertEqualInt(get_date(now, "99/02/17 7pm utc"), 919278000); - assertEqualInt(get_date(now, "02/17/99 7:11am est"), 919253460); - assertEqualInt(get_date(now, "now - 2 hours"), - get_date(now, "2 hours ago")); - assertEqualInt(get_date(now, "2 hours ago"), - get_date(now, "+2 hours ago")); - assertEqualInt(get_date(now, "now - 2 hours"), - get_date(now, "-2 hours")); + assertEqualInt(archive_parse_date(now, "99/02/17 7pm utc"), 919278000); + assertEqualInt(archive_parse_date(now, "02/17/99 7:11am est"), 919253460); + assertEqualInt(archive_parse_date(now, "now - 2 hours"), + archive_parse_date(now, "2 hours ago")); + assertEqualInt(archive_parse_date(now, "2 hours ago"), + archive_parse_date(now, "+2 hours ago")); + assertEqualInt(archive_parse_date(now, "now - 2 hours"), + archive_parse_date(now, "-2 hours")); /* It's important that we handle ctime() format. */ - assertEqualInt(get_date(now, "Sun Feb 22 17:38:26 PST 2009"), + assertEqualInt(archive_parse_date(now, "Sun Feb 22 17:38:26 PST 2009"), 1235353106); /* Basic relative offsets. */ /* If we use the actual current time as the reference, then * these tests break around DST changes, so it's actually * important to use a specific reference time here. */ - assertEqualInt(get_date(0, "tomorrow"), 24 * 60 * 60); - assertEqualInt(get_date(0, "yesterday"), - 24 * 60 * 60); - assertEqualInt(get_date(0, "now + 1 hour"), 60 * 60); - assertEqualInt(get_date(0, "now + 1 hour + 1 minute"), 60 * 60 + 60); + assertEqualInt(archive_parse_date(0, "tomorrow"), 24 * 60 * 60); + assertEqualInt(archive_parse_date(0, "yesterday"), - 24 * 60 * 60); + assertEqualInt(archive_parse_date(0, "now + 1 hour"), 60 * 60); + assertEqualInt(archive_parse_date(0, "now + 1 hour + 1 minute"), 60 * 60 + 60); /* Repeat the above for a different start time. */ now = 1231113600; /* Jan 5, 2009 00:00 UTC */ - assertEqualInt(get_date(0, "Jan 5, 2009 00:00 UTC"), now); - assertEqualInt(get_date(now, "tomorrow"), now + 24 * 60 * 60); - assertEqualInt(get_date(now, "yesterday"), now - 24 * 60 * 60); - assertEqualInt(get_date(now, "now + 1 hour"), now + 60 * 60); - assertEqualInt(get_date(now, "now + 1 hour + 1 minute"), + assertEqualInt(archive_parse_date(0, "Jan 5, 2009 00:00 UTC"), now); + assertEqualInt(archive_parse_date(now, "tomorrow"), now + 24 * 60 * 60); + assertEqualInt(archive_parse_date(now, "yesterday"), now - 24 * 60 * 60); + assertEqualInt(archive_parse_date(now, "now + 1 hour"), now + 60 * 60); + assertEqualInt(archive_parse_date(now, "now + 1 hour + 1 minute"), now + 60 * 60 + 60); - assertEqualInt(get_date(now, "tomorrow 5:16am UTC"), + assertEqualInt(archive_parse_date(now, "tomorrow 5:16am UTC"), now + 24 * 60 * 60 + 5 * 60 * 60 + 16 * 60); - assertEqualInt(get_date(now, "UTC 5:16am tomorrow"), + assertEqualInt(archive_parse_date(now, "UTC 5:16am tomorrow"), now + 24 * 60 * 60 + 5 * 60 * 60 + 16 * 60); /* Jan 5, 2009 was a Monday. */ - assertEqualInt(get_date(now, "monday UTC"), now); - assertEqualInt(get_date(now, "sunday UTC"), now + 6 * 24 * 60 * 60); - assertEqualInt(get_date(now, "tuesday UTC"), now + 24 * 60 * 60); + assertEqualInt(archive_parse_date(now, "monday UTC"), now); + assertEqualInt(archive_parse_date(now, "sunday UTC"), now + 6 * 24 * 60 * 60); + assertEqualInt(archive_parse_date(now, "tuesday UTC"), now + 24 * 60 * 60); /* "next tuesday" is one week after "tuesday" */ - assertEqualInt(get_date(now, "UTC next tuesday"), + assertEqualInt(archive_parse_date(now, "UTC next tuesday"), now + 8 * 24 * 60 * 60); /* "last tuesday" is one week before "tuesday" */ - assertEqualInt(get_date(now, "last tuesday UTC"), + assertEqualInt(archive_parse_date(now, "last tuesday UTC"), now - 6 * 24 * 60 * 60); /* Unix epoch timestamps */ - assertEqualInt(get_date(now, "@0"), 0); - assertEqualInt(get_date(now, "@100"), 100); - assertEqualInt(get_date(now, "@+100"), 100); + assertEqualInt(archive_parse_date(now, "@0"), 0); + assertEqualInt(archive_parse_date(now, "@100"), 100); + assertEqualInt(archive_parse_date(now, "@1000000000"), 1000000000); + assertEqualInt(archive_parse_date(now, "@+100"), 100); - assertEqualInt(get_date(now, "@"), -1); - assertEqualInt(get_date(now, "@-"), -1); - assertEqualInt(get_date(now, "@+"), -1); - assertEqualInt(get_date(now, "@tenth"), -1); - assertEqualInt(get_date(now, "@100 tomorrow"), -1); + assertEqualInt(archive_parse_date(now, "@"), -1); + assertEqualInt(archive_parse_date(now, "@-"), -1); + assertEqualInt(archive_parse_date(now, "@+"), -1); + assertEqualInt(archive_parse_date(now, "@tenth"), -1); + assertEqualInt(archive_parse_date(now, "@100 tomorrow"), -1); - /* TODO: Lots more tests here. */ + /* Verify handling of overlarge numbers */ + expected = sizeof(time_t) == 4 ? -1 : 253375948800LL; + assertEqualInt(archive_parse_date(now, "Jan 1, 9999 UTC"), expected); + assertEqualInt(archive_parse_date(now, "Jan 1, 10000 UTC"), -1); + assertEqualInt(archive_parse_date(now, "Jan 1, 99999 UTC"), -1); + assertEqualInt(archive_parse_date(time(NULL), "2147483647-01-01 00:00:00"), -1); } diff --git a/contrib/libarchive/libarchive/test/test_archive_pathmatch.c b/contrib/libarchive/libarchive/test/test_archive_pathmatch.c index 3b212aca9d..ea75851dbe 100644 --- a/contrib/libarchive/libarchive/test/test_archive_pathmatch.c +++ b/contrib/libarchive/libarchive/test/test_archive_pathmatch.c @@ -56,6 +56,10 @@ DEFINE_TEST(test_archive_pathmatch) assertEqualInt(0, archive_pathmatch_w(L"a/b/c", NULL, 0)); /* Empty pattern only matches empty string. */ + assertEqualInt(1, archive_pathmatch(NULL,NULL, 0)); + assertEqualInt(1, archive_pathmatch(NULL,"", 0)); + assertEqualInt(0, archive_pathmatch(NULL,"a", 0)); + assertEqualInt(1, archive_pathmatch("",NULL, 0)); assertEqualInt(1, archive_pathmatch("","", 0)); assertEqualInt(0, archive_pathmatch("","a", 0)); assertEqualInt(1, archive_pathmatch("*","", 0)); @@ -76,11 +80,15 @@ DEFINE_TEST(test_archive_pathmatch) assertEqualInt(0, archive_pathmatch("a", "ab", 0)); assertEqualInt(0, archive_pathmatch("a", "ab", 0)); assertEqualInt(1, archive_pathmatch("a?c", "abc", 0)); + assertEqualInt(1, archive_pathmatch("*a", "/a", 0)); + assertEqualInt(1, archive_pathmatch("*a", "a", 0)); /* SUSv2: ? matches / */ assertEqualInt(1, archive_pathmatch("a?c", "a/c", 0)); assertEqualInt(1, archive_pathmatch("a?*c*", "a/c", 0)); assertEqualInt(1, archive_pathmatch("*a*", "a/c", 0)); assertEqualInt(1, archive_pathmatch("*a*", "/a/c", 0)); + assertEqualInt(0, archive_pathmatch("*a", "/a/c", 0)); + assertEqualInt(0, archive_pathmatch("*a", "a/c", 0)); assertEqualInt(1, archive_pathmatch("*a*", "defaaaaaaa", 0)); assertEqualInt(0, archive_pathmatch("a*", "defghi", 0)); assertEqualInt(0, archive_pathmatch("*a*", "defghi", 0)); @@ -201,6 +209,14 @@ DEFINE_TEST(test_archive_pathmatch) failure("Trailing '/.' is still the same directory."); assertEqualInt(1, archive_pathmatch("./abc*/./def", "abc/def/.", 0)); + /* Anchor characters without flags not special. */ + assertEqualInt(0, archive_pathmatch("^abc", "abc", 0)); + assertEqualInt(1, archive_pathmatch("^abc", "^abc", 0)); + assertEqualInt(0, archive_pathmatch("abc$", "abc", 0)); + assertEqualInt(1, archive_pathmatch("abc$", "abc$", 0)); + assertEqualInt(0, archive_pathmatch("^abc$", "abc", 0)); + assertEqualInt(1, archive_pathmatch("^abc$", "^abc$", 0)); + /* Matches not anchored at beginning. */ assertEqualInt(0, archive_pathmatch("bcd", "abcd", PATHMATCH_NO_ANCHOR_START)); diff --git a/contrib/libarchive/libarchive/test/test_archive_pathmatch_oob.c b/contrib/libarchive/libarchive/test/test_archive_pathmatch_oob.c new file mode 100644 index 0000000000..fc8f4a5ca1 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_archive_pathmatch_oob.c @@ -0,0 +1,117 @@ +/*- + * Copyright (c) 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 +#include + +/* + * Regression test: malformed bracket expressions in patterns caused + * heap-buffer-overflow reads in pm() (BUG-003) and strchr OOB via + * archive_match (BUG-007). + * + * To reproduce under ASan, we must allocate tight heap buffers for the + * pattern and string (just like the fuzzer does), so that ASan's + * redzones detect overreads. + */ + +/* Declare the internal function we want to test. */ +int __archive_pathmatch(const char *pattern, const char *string, int flags); + +/* + * Replay a fuzzer repro file through __archive_pathmatch(). + * Format: byte 0 = flags, then rest is split at first '\0' into + * pattern and string, each copied into tight malloc'd buffers. + */ +static void +replay_pathmatch_repro(const char *refname) +{ + FILE *f; + unsigned char buf[4096]; + size_t size, split, rest_len, str_start, str_len; + const unsigned char *rest; + char *pattern, *string; + int flags; + size_t i; + + extract_reference_file(refname); + + f = fopen(refname, "rb"); + if (!assert(f != NULL)) + return; + size = fread(buf, 1, sizeof(buf), f); + fclose(f); + if (!assert(size >= 4)) + return; + + flags = buf[0] % 8; + rest = buf + 1; + rest_len = size - 1; + + /* Find split point (first null byte in rest). */ + split = 0; + for (i = 0; i < rest_len; i++) { + if (rest[i] == 0) { + split = i; + break; + } + } + if (split == 0) + split = rest_len / 2; + + /* Allocate tight buffers so ASan can detect overreads. */ + pattern = (char *)malloc(split + 1); + if (!assert(pattern != NULL)) + return; + memcpy(pattern, rest, split); + pattern[split] = '\0'; + + str_start = (split < rest_len && rest[split] == 0) + ? split + 1 : split; + str_len = rest_len - str_start; + string = (char *)malloc(str_len + 1); + if (!assert(string != NULL)) { + free(pattern); + return; + } + memcpy(string, rest + str_start, str_len); + string[str_len] = '\0'; + + /* This must not read past the allocated buffers. */ + __archive_pathmatch(pattern, string, flags); + + free(pattern); + free(string); +} + +DEFINE_TEST(test_archive_pathmatch_oob_bracket) +{ + replay_pathmatch_repro("test_archive_pathmatch_oob_bracket.bin"); +} + +DEFINE_TEST(test_archive_pathmatch_oob_strchr) +{ + replay_pathmatch_repro("test_archive_pathmatch_oob_strchr.bin"); +} diff --git a/contrib/libarchive/libarchive/test/test_archive_pathmatch_oob_bracket.bin.uu b/contrib/libarchive/libarchive/test/test_archive_pathmatch_oob_bracket.bin.uu new file mode 100644 index 0000000000..5984a0d34c --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_archive_pathmatch_oob_bracket.bin.uu @@ -0,0 +1,4 @@ +begin 644 test_archive_pathmatch_oob_bracket.bin +,6ULAC"&,*HPJ73\` +` +end diff --git a/contrib/libarchive/libarchive/test/test_archive_pathmatch_oob_strchr.bin.uu b/contrib/libarchive/libarchive/test/test_archive_pathmatch_oob_strchr.bin.uu new file mode 100644 index 0000000000..b961b0a088 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_archive_pathmatch_oob_strchr.bin.uu @@ -0,0 +1,8 @@ +begin 644 test_archive_pathmatch_oob_strchr.bin +M`2H_*C];(0(M7%@K,`+;725S871U5SX*@`!*ELI+2]=`0!A$``!9(`! +M*BI;(0(J72KEY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7E +MY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>4``0@"`0`0&@``*@`J*BH` +M`2HJ*@``)```&P`!*"HJ``$`"#\D```J`"JJ``(`T@(J*@`#`"H``2HJ*@`! +'*@"3`5L``@`` +` +end diff --git a/contrib/libarchive/libarchive/test/test_archive_read_close_twice.c b/contrib/libarchive/libarchive/test/test_archive_read_close_twice.c index 2f5ee77f11..4320ae6705 100644 --- a/contrib/libarchive/libarchive/test/test_archive_read_close_twice.c +++ b/contrib/libarchive/libarchive/test/test_archive_read_close_twice.c @@ -29,11 +29,11 @@ DEFINE_TEST(test_archive_read_close_twice) { struct archive* a = archive_read_new(); - assertEqualInt(0, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); - assertEqualInt(0, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); diff --git a/contrib/libarchive/libarchive/test/test_archive_read_close_twice_open_fd.c b/contrib/libarchive/libarchive/test/test_archive_read_close_twice_open_fd.c index 62a6a90df1..852038dde3 100644 --- a/contrib/libarchive/libarchive/test/test_archive_read_close_twice_open_fd.c +++ b/contrib/libarchive/libarchive/test/test_archive_read_close_twice_open_fd.c @@ -34,11 +34,11 @@ DEFINE_TEST(test_archive_read_close_twice_open_fd) assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); diff --git a/contrib/libarchive/libarchive/test/test_archive_read_close_twice_open_filename.c b/contrib/libarchive/libarchive/test/test_archive_read_close_twice_open_filename.c index 4824319b42..0be64091d7 100644 --- a/contrib/libarchive/libarchive/test/test_archive_read_close_twice_open_filename.c +++ b/contrib/libarchive/libarchive/test/test_archive_read_close_twice_open_filename.c @@ -36,11 +36,11 @@ DEFINE_TEST(test_archive_read_close_twice_open_filename) assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); diff --git a/contrib/libarchive/libarchive/test/test_archive_string.c b/contrib/libarchive/libarchive/test/test_archive_string.c index bf822c0d5e..c9c5c195a9 100644 --- a/contrib/libarchive/libarchive/test/test_archive_string.c +++ b/contrib/libarchive/libarchive/test/test_archive_string.c @@ -388,6 +388,7 @@ test_archive_string_dirname(void) archive_string_dirname(&s); assertEqualString(pair->exp, s.s); } + archive_string_free(&s); } DEFINE_TEST(test_archive_string) diff --git a/contrib/libarchive/libarchive/test/test_archive_string_conversion.c b/contrib/libarchive/libarchive/test/test_archive_string_conversion.c index ecc39dffea..4bf17185cc 100644 --- a/contrib/libarchive/libarchive/test/test_archive_string_conversion.c +++ b/contrib/libarchive/libarchive/test/test_archive_string_conversion.c @@ -338,13 +338,13 @@ test_archive_string_normalization_nfc(const char *testdata) nfd[sizeof(nfd)-1] = '\0'; /* - * Get an NFC patterns. + * Get an NFC pattern. */ scan_unicode_pattern(utf8_nfc, wc_nfc, utf16be_nfc, utf16le_nfc, nfc, 0); /* - * Get an NFD patterns. + * Get an NFD pattern. */ scan_unicode_pattern(utf8_nfd, wc_nfd, utf16be_nfd, utf16le_nfd, nfd, 0); @@ -550,7 +550,7 @@ test_archive_string_normalization_mac_nfd(const char *testdata) nfd[sizeof(nfd)-1] = '\0'; /* - * Get an NFC patterns. + * Get an NFC pattern. */ should_be_nfc = scan_unicode_pattern(utf8_nfc, wc_nfc, utf16be_nfc, utf16le_nfc, nfc, 1); @@ -966,6 +966,10 @@ test_archive_string_conversion_fail_utf8_mbs(struct archive *a, DEFINE_TEST(test_archive_string_conversion_fail_c) { struct archive *a; +#if defined(__sun) + skipping("Solaris iconv substitutes unrepresentable UTF-8 characters"); + return; +#endif /* Test the C locale by not calling setlocale. */ @@ -983,6 +987,10 @@ DEFINE_TEST(test_archive_string_conversion_fail_latin1) { struct archive *a; struct archive_string_conv *sconv; +#if defined(__sun) + skipping("Solaris iconv substitutes unrepresentable UTF-8 characters"); + return; +#endif /* Test a Latin-1 locale. */ if ( diff --git a/contrib/libarchive/libarchive/test/test_archive_write_add_filter.c b/contrib/libarchive/libarchive/test/test_archive_write_add_filter.c new file mode 100644 index 0000000000..3a549d5723 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_archive_write_add_filter.c @@ -0,0 +1,208 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * Copyright (c) 2026 i1011 + * 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" + +static void +test_add_filter_by_code(int filter_code, + int (*can_filter_prog)(void)) +{ + struct archive_entry *ae; + struct archive *a; + size_t used; + size_t buffsize = 1024 * 128; + char *buff; + int r; + + assert((buff = calloc(buffsize, sizeof(*buff))) != NULL); + if (buff == NULL) + return; + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + r = archive_write_add_filter(a, filter_code); + if (r == ARCHIVE_WARN) { + if (!can_filter_prog()) { + skipping("Filter code \"%d\" not supported on this platform", + filter_code); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + return; + } + } else if (r == ARCHIVE_FATAL && + (strcmp(archive_error_string(a), + "lzma compression not supported on this platform") == 0 || + strcmp(archive_error_string(a), + "xz compression not supported on this platform") == 0)) { + skipping("Filter code \"%d\" not supported on this platform", + filter_code); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + return; + } else { + if (!assertEqualIntA(a, ARCHIVE_OK, r)) { + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + return; + } + } + if (filter_code == ARCHIVE_FILTER_LRZIP) + { + /* + * There's a bug in lrzip (as of release 0.612) where 2nd stage + * compression can't be performed on smaller files. Set lrzip to + * use no 2nd stage compression. + */ + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "lrzip:compression=none")); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 0); + assertEqualInt(1, archive_entry_mtime(ae)); + archive_entry_set_ctime(ae, 1, 0); + assertEqualInt(1, archive_entry_ctime(ae)); + archive_entry_set_atime(ae, 1, 0); + assertEqualInt(1, archive_entry_atime(ae)); + archive_entry_copy_pathname(ae, "file"); + assertEqualString("file", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, AE_IFREG | 0755); + assertEqualInt((AE_IFREG | 0755), archive_entry_mode(ae)); + archive_entry_set_size(ae, 8); + assertEqualInt(0, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(8, archive_write_data(a, "12345678", 8)); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Now, read the data back. + */ + 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_memory(a, buff, used)); + + /* + * Read and verify the file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(8, archive_entry_size(ae)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, filter_code, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + free(buff); +} + +static int +canAlways(void) +{ + return 1; +} + +DEFINE_TEST(test_archive_write_add_filter_none) +{ + test_add_filter_by_code(ARCHIVE_FILTER_NONE, canAlways); +} + +DEFINE_TEST(test_archive_write_add_filter_gzip) +{ + test_add_filter_by_code(ARCHIVE_FILTER_GZIP, canGzip); +} + +DEFINE_TEST(test_archive_write_add_filter_bzip2) +{ + test_add_filter_by_code(ARCHIVE_FILTER_BZIP2, canBzip2); +} + +DEFINE_TEST(test_archive_write_add_filter_compress) +{ + test_add_filter_by_code(ARCHIVE_FILTER_COMPRESS, canAlways); +} + +DEFINE_TEST(test_archive_write_add_filter_grzip) +{ + test_add_filter_by_code(ARCHIVE_FILTER_GRZIP, canGrzip); +} + +DEFINE_TEST(test_archive_write_add_filter_lrzip) +{ + test_add_filter_by_code(ARCHIVE_FILTER_LRZIP, canLrzip); +} + +DEFINE_TEST(test_archive_write_add_filter_lz4) +{ + test_add_filter_by_code(ARCHIVE_FILTER_LZ4, canLz4); +} + +DEFINE_TEST(test_archive_write_add_filter_lzip) +{ + test_add_filter_by_code(ARCHIVE_FILTER_LZIP, canLzip); +} + +DEFINE_TEST(test_archive_write_add_filter_lzma) +{ + test_add_filter_by_code(ARCHIVE_FILTER_LZMA, canLzma); +} + +DEFINE_TEST(test_archive_write_add_filter_lzop) +{ + test_add_filter_by_code(ARCHIVE_FILTER_LZOP, canLzop); +} + +DEFINE_TEST(test_archive_write_add_filter_uuencode) +{ + test_add_filter_by_code(ARCHIVE_FILTER_UU, canAlways); +} + +DEFINE_TEST(test_archive_write_add_filter_xz) +{ + test_add_filter_by_code(ARCHIVE_FILTER_XZ, canXz); +} + +DEFINE_TEST(test_archive_write_add_filter_zstd) +{ + test_add_filter_by_code(ARCHIVE_FILTER_ZSTD, canZstd); +} diff --git a/contrib/libarchive/libarchive/test/test_archive_write_add_filter_by_name.c b/contrib/libarchive/libarchive/test/test_archive_write_add_filter_by_name.c index 9d7e58d6f6..f078520303 100644 --- a/contrib/libarchive/libarchive/test/test_archive_write_add_filter_by_name.c +++ b/contrib/libarchive/libarchive/test/test_archive_write_add_filter_by_name.c @@ -129,7 +129,7 @@ test_filter_by_name(const char *filter_name, int filter_code, assertEqualIntA(a, filter_code, archive_filter_code(a, 0)); assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); } diff --git a/contrib/libarchive/libarchive/test/test_archive_write_set_format_by_name.c b/contrib/libarchive/libarchive/test/test_archive_write_set_format_by_name.c index 07942f6bff..f8ca04db36 100644 --- a/contrib/libarchive/libarchive/test/test_archive_write_set_format_by_name.c +++ b/contrib/libarchive/libarchive/test/test_archive_write_set_format_by_name.c @@ -130,7 +130,7 @@ test_format_by_name(const char *format_name, const char *compression_type, archive_filter_code(a, 0)); assertEqualIntA(a, format_id, archive_format(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } free(buff); diff --git a/contrib/libarchive/libarchive/test/test_archive_write_set_format_filter_by_ext.c b/contrib/libarchive/libarchive/test/test_archive_write_set_format_filter_by_ext.c index fe6c350e48..849a9c5a07 100644 --- a/contrib/libarchive/libarchive/test/test_archive_write_set_format_filter_by_ext.c +++ b/contrib/libarchive/libarchive/test/test_archive_write_set_format_filter_by_ext.c @@ -137,7 +137,7 @@ test_format_filter_by_ext(const char *output_file, archive_filter_code(a, 0)); assertEqualIntA(a, format_id, archive_format(a) & ARCHIVE_FORMAT_BASE_MASK ); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } free(buff); diff --git a/contrib/libarchive/libarchive/test/test_compat_bzip2.c b/contrib/libarchive/libarchive/test/test_compat_bzip2.c index e126e6f7d3..8fd04a7dad 100644 --- a/contrib/libarchive/libarchive/test/test_compat_bzip2.c +++ b/contrib/libarchive/libarchive/test/test_compat_bzip2.c @@ -48,6 +48,7 @@ compat_bzip2(const char *name) assert((a = archive_read_new()) != NULL); if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { skipping("Unsupported bzip2"); + archive_read_free(a); return; } assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); diff --git a/contrib/libarchive/libarchive/test/test_compat_cpio.c b/contrib/libarchive/libarchive/test/test_compat_cpio.c index 1251288111..1c139c77f9 100644 --- a/contrib/libarchive/libarchive/test/test_compat_cpio.c +++ b/contrib/libarchive/libarchive/test/test_compat_cpio.c @@ -92,7 +92,7 @@ test_compat_cpio_1(void) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_SVR4_NOCRC); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_compat_gtar.c b/contrib/libarchive/libarchive/test/test_compat_gtar.c index ba42e726cf..fe3cfec907 100644 --- a/contrib/libarchive/libarchive/test/test_compat_gtar.c +++ b/contrib/libarchive/libarchive/test/test_compat_gtar.c @@ -101,7 +101,7 @@ test_compat_gtar_1(void) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -141,7 +141,7 @@ test_compat_gtar_2(void) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_compat_gtar_large.c b/contrib/libarchive/libarchive/test/test_compat_gtar_large.c index 633b20c0a9..b9a467b1c9 100644 --- a/contrib/libarchive/libarchive/test/test_compat_gtar_large.c +++ b/contrib/libarchive/libarchive/test/test_compat_gtar_large.c @@ -218,7 +218,7 @@ DEFINE_TEST(test_compat_gtar_large) /* Verify that the reader actually read to the end of data */ assertEqualInt(reader.zero_blocks_remaining, 0); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(reader.zero_block); } diff --git a/contrib/libarchive/libarchive/test/test_compat_gzip.c b/contrib/libarchive/libarchive/test/test_compat_gzip.c index 20fce7af43..475c136745 100644 --- a/contrib/libarchive/libarchive/test/test_compat_gzip.c +++ b/contrib/libarchive/libarchive/test/test_compat_gzip.c @@ -77,7 +77,7 @@ verify(const char *name) assertEqualString(archive_filter_name(a, 0), "gzip"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_compat_lz4.c b/contrib/libarchive/libarchive/test/test_compat_lz4.c index 8ab9208b09..d053155694 100644 --- a/contrib/libarchive/libarchive/test/test_compat_lz4.c +++ b/contrib/libarchive/libarchive/test/test_compat_lz4.c @@ -31,7 +31,7 @@ * In particular: * * lz4 -d will read multiple lz4 streams, concatenating the output * * lz4 -d will stop at the end of a stream if the following data - * doesn't start with a lz4 signature. + * doesn't start with an lz4 signature. */ /* @@ -78,7 +78,7 @@ verify(const char *name, const char *n[]) assertEqualString(archive_filter_name(a, 0), "lz4"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_compat_lzip.c b/contrib/libarchive/libarchive/test/test_compat_lzip.c index cd246b943b..9a8196f61d 100644 --- a/contrib/libarchive/libarchive/test/test_compat_lzip.c +++ b/contrib/libarchive/libarchive/test/test_compat_lzip.c @@ -124,7 +124,7 @@ compat_lzip(const char *name) assertEqualString(archive_filter_name(a, 0), "lzip"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -165,7 +165,7 @@ compat_lzip_3(const char *name) assertEqualString(archive_filter_name(a, 0), "lzip"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_RAW); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -202,7 +202,7 @@ compat_lzip_4(const char *name) assertEqualString(archive_filter_name(a, 0), "lzip"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_compat_lzma.c b/contrib/libarchive/libarchive/test/test_compat_lzma.c index b9cad55514..af988e1f2b 100644 --- a/contrib/libarchive/libarchive/test/test_compat_lzma.c +++ b/contrib/libarchive/libarchive/test/test_compat_lzma.c @@ -133,7 +133,7 @@ compat_lzma(const char *name) assertEqualString(archive_filter_name(a, 0), "lzma"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_compat_lzop.c b/contrib/libarchive/libarchive/test/test_compat_lzop.c index 2da4e8eb6d..a70d658244 100644 --- a/contrib/libarchive/libarchive/test/test_compat_lzop.c +++ b/contrib/libarchive/libarchive/test/test_compat_lzop.c @@ -70,7 +70,7 @@ DEFINE_TEST(test_compat_lzop) assertEqualString(archive_filter_name(a, 0), "lzop"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* @@ -101,7 +101,7 @@ DEFINE_TEST(test_compat_lzop) assertEqualString(archive_filter_name(a, 0), "lzop"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* @@ -125,6 +125,6 @@ DEFINE_TEST(test_compat_lzop) assertEqualString(archive_filter_name(a, 0), "lzop"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_compat_mac.c b/contrib/libarchive/libarchive/test/test_compat_mac.c index 976f04a473..9532d079af 100644 --- a/contrib/libarchive/libarchive/test/test_compat_mac.c +++ b/contrib/libarchive/libarchive/test/test_compat_mac.c @@ -130,7 +130,7 @@ test_compat_mac_1(void) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -201,7 +201,7 @@ test_compat_mac_2(void) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_compat_perl_archive_tar.c b/contrib/libarchive/libarchive/test/test_compat_perl_archive_tar.c index 94abe3f056..1574f7bc8f 100644 --- a/contrib/libarchive/libarchive/test/test_compat_perl_archive_tar.c +++ b/contrib/libarchive/libarchive/test/test_compat_perl_archive_tar.c @@ -60,6 +60,6 @@ DEFINE_TEST(test_compat_perl_archive_tar) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_compat_plexus_archiver_tar.c b/contrib/libarchive/libarchive/test/test_compat_plexus_archiver_tar.c index 419e84b1c4..8346fb555e 100644 --- a/contrib/libarchive/libarchive/test/test_compat_plexus_archiver_tar.c +++ b/contrib/libarchive/libarchive/test/test_compat_plexus_archiver_tar.c @@ -63,6 +63,6 @@ DEFINE_TEST(test_compat_plexus_archiver_tar) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_compat_solaris_pax_sparse.c b/contrib/libarchive/libarchive/test/test_compat_solaris_pax_sparse.c index 94e3e9189b..1d3c2beb55 100644 --- a/contrib/libarchive/libarchive/test/test_compat_solaris_pax_sparse.c +++ b/contrib/libarchive/libarchive/test/test_compat_solaris_pax_sparse.c @@ -100,7 +100,7 @@ test_compat_solaris_pax_sparse_1(void) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -172,7 +172,7 @@ test_compat_solaris_pax_sparse_2(void) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_compat_tar_directory.c b/contrib/libarchive/libarchive/test/test_compat_tar_directory.c index 3d086f1da7..92278fdc6c 100644 --- a/contrib/libarchive/libarchive/test/test_compat_tar_directory.c +++ b/contrib/libarchive/libarchive/test/test_compat_tar_directory.c @@ -64,7 +64,7 @@ test_compat_tar_directory_1(void) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_compat_tar_hardlink.c b/contrib/libarchive/libarchive/test/test_compat_tar_hardlink.c index b8517440ae..4f4c8904ac 100644 --- a/contrib/libarchive/libarchive/test/test_compat_tar_hardlink.c +++ b/contrib/libarchive/libarchive/test/test_compat_tar_hardlink.c @@ -91,7 +91,7 @@ test_compat_tar_hardlink_1(void) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_compat_xz.c b/contrib/libarchive/libarchive/test/test_compat_xz.c index f904583782..3170b149c6 100644 --- a/contrib/libarchive/libarchive/test/test_compat_xz.c +++ b/contrib/libarchive/libarchive/test/test_compat_xz.c @@ -72,7 +72,7 @@ compat_xz(const char *name) assertEqualString(archive_filter_name(a, 0), "xz"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_compat_zip.c b/contrib/libarchive/libarchive/test/test_compat_zip.c index e2d41cc9b4..1f120692ec 100644 --- a/contrib/libarchive/libarchive/test/test_compat_zip.c +++ b/contrib/libarchive/libarchive/test/test_compat_zip.c @@ -58,7 +58,7 @@ DEFINE_TEST(test_compat_zip_1) assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ZIP); finish: - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -89,7 +89,7 @@ DEFINE_TEST(test_compat_zip_2) assertEqualString("file2", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -140,7 +140,7 @@ DEFINE_TEST(test_compat_zip_3) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } /** @@ -188,7 +188,7 @@ DEFINE_TEST(test_compat_zip_4) assertEqualInt(0644, archive_entry_perm(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* Try reading without seek support and watch it fail. */ assert((a = archive_read_new()) != NULL); @@ -196,7 +196,7 @@ DEFINE_TEST(test_compat_zip_4) assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_FATAL, read_open_memory(a, p, s, 3)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } /** @@ -273,7 +273,7 @@ DEFINE_TEST(test_compat_zip_5) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* Try reading without seek support. */ assert((a = archive_read_new()) != NULL); @@ -332,7 +332,7 @@ DEFINE_TEST(test_compat_zip_5) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } @@ -376,14 +376,14 @@ DEFINE_TEST(test_compat_zip_6) assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 7)); compat_zip_6_verify(a); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(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)); assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 7)); compat_zip_6_verify(a); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } @@ -417,7 +417,7 @@ DEFINE_TEST(test_compat_zip_7) assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } free(p); } @@ -444,6 +444,6 @@ DEFINE_TEST(test_compat_zip_8) assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); /* This file is in the archive as arc\test */ assertEqualString("arc/test", archive_entry_pathname(ae)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/contrib/libarchive/libarchive/test/test_compat_zstd.c b/contrib/libarchive/libarchive/test/test_compat_zstd.c index 34b8edeb92..8785aa39e2 100644 --- a/contrib/libarchive/libarchive/test/test_compat_zstd.c +++ b/contrib/libarchive/libarchive/test/test_compat_zstd.c @@ -67,7 +67,7 @@ compat_zstd(const char *name) assertEqualString(archive_filter_name(a, 0), "zstd"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_fuzz_consumer.h b/contrib/libarchive/libarchive/test/test_fuzz_consumer.h new file mode 100644 index 0000000000..4033253e7a --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_fuzz_consumer.h @@ -0,0 +1,143 @@ +/*- + * Copyright (c) 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. + */ + +/* + * C99 equivalent of the DataConsumer class used by the C++ fuzzers. + * Consumes bytes sequentially from a buffer, matching the fuzzer protocol. + * Not all consumers use every function, so suppress unused warnings. + */ +#ifndef TEST_FUZZ_CONSUMER_H +#define TEST_FUZZ_CONSUMER_H + +#include +#include +#include + +#if defined(__GNUC__) || defined(__clang__) +#define FUZZ_UNUSED __attribute__((unused)) +#else +#define FUZZ_UNUSED +#endif + +struct fuzz_consumer { + const uint8_t *data; + size_t size; + size_t pos; + char string_buf[512]; +}; + +FUZZ_UNUSED static void +fuzz_consumer_init(struct fuzz_consumer *c, const uint8_t *data, size_t size) +{ + c->data = data; + c->size = size; + c->pos = 0; +} + +FUZZ_UNUSED static size_t +fuzz_consumer_remaining(const struct fuzz_consumer *c) +{ + return c->size - c->pos; +} + +FUZZ_UNUSED static uint8_t +fuzz_consume_byte(struct fuzz_consumer *c) +{ + if (c->pos >= c->size) + return 0; + return c->data[c->pos++]; +} + +FUZZ_UNUSED static uint16_t +fuzz_consume_u16(struct fuzz_consumer *c) +{ + uint16_t val = 0; + if (c->pos + 2 <= c->size) { + val = (uint16_t)c->data[c->pos] + | ((uint16_t)c->data[c->pos + 1] << 8); + c->pos += 2; + } + return val; +} + +FUZZ_UNUSED static uint32_t +fuzz_consume_u32(struct fuzz_consumer *c) +{ + uint32_t val = 0; + if (c->pos + 4 <= c->size) { + val = (uint32_t)c->data[c->pos] + | ((uint32_t)c->data[c->pos + 1] << 8) + | ((uint32_t)c->data[c->pos + 2] << 16) + | ((uint32_t)c->data[c->pos + 3] << 24); + c->pos += 4; + } + return val; +} + +FUZZ_UNUSED static int64_t +fuzz_consume_i64(struct fuzz_consumer *c) +{ + int64_t val = 0; + if (c->pos + 8 <= c->size) { + int i; + for (i = 0; i < 8; i++) + val |= (int64_t)c->data[c->pos + i] << (8 * i); + c->pos += 8; + } + return val; +} + +FUZZ_UNUSED static const char * +fuzz_consume_string(struct fuzz_consumer *c, size_t max_len) +{ + size_t avail, len, actual_len; + if (max_len > sizeof(c->string_buf) - 1) + max_len = sizeof(c->string_buf) - 1; + avail = c->size - c->pos; + len = (avail < max_len) ? avail : max_len; + actual_len = 0; + while (actual_len < len && c->pos < c->size) { + char ch = (char)c->data[c->pos++]; + if (ch == '\0') + break; + c->string_buf[actual_len++] = ch; + } + c->string_buf[actual_len] = '\0'; + return c->string_buf; +} + +FUZZ_UNUSED static size_t +fuzz_consume_bytes(struct fuzz_consumer *c, void *out, size_t len) +{ + size_t avail = c->size - c->pos; + size_t to_copy = (avail < len) ? avail : len; + if (to_copy > 0) { + memcpy(out, c->data + c->pos, to_copy); + c->pos += to_copy; + } + return to_copy; +} + +#endif /* TEST_FUZZ_CONSUMER_H */ diff --git a/contrib/libarchive/libarchive/test/test_open_filename.c b/contrib/libarchive/libarchive/test/test_open_filename.c index 09a83690be..41e0ff0ee3 100644 --- a/contrib/libarchive/libarchive/test/test_open_filename.c +++ b/contrib/libarchive/libarchive/test/test_open_filename.c @@ -24,6 +24,8 @@ */ #include "test.h" +#include + static void test_open_filename_mbs(void) { @@ -197,3 +199,24 @@ DEFINE_TEST(test_open_filename) test_open_filename_mbs(); test_open_filename_wcs(); } + +DEFINE_TEST(test_open_filename_wcs_oob) +{ + struct archive *a; + + /* Continue even if not available for best test coverage. */ + setlocale(LC_ALL, "en_US.UTF-8"); + + /* + * Try to open file with filename which might use more bytes in + * MBS representation than in wchar_t if platform uses 16 bit wchar_t, + * e.g. Cygwin (3 times a Euro sign, i.e. 3*2+2=8 vs 3*3+1=10 bytes). + */ + 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_FATAL, + archive_read_open_filename_w(a, L"\u20AC\u20AC\u20AC", 512)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/contrib/libarchive/libarchive/test/test_pax_xattr_header.c b/contrib/libarchive/libarchive/test/test_pax_xattr_header.c index 8af81079ea..ce002b3171 100644 --- a/contrib/libarchive/libarchive/test/test_pax_xattr_header.c +++ b/contrib/libarchive/libarchive/test/test_pax_xattr_header.c @@ -67,7 +67,7 @@ DEFINE_TEST(test_pax_xattr_header) assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assertEqualFile("test1.tar","test_pax_xattr_header_all.tar"); @@ -86,7 +86,7 @@ DEFINE_TEST(test_pax_xattr_header) assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assertEqualFile("test2.tar","test_pax_xattr_header_schily.tar"); @@ -105,7 +105,7 @@ DEFINE_TEST(test_pax_xattr_header) assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assertEqualFile("test3.tar","test_pax_xattr_header_libarchive.tar"); @@ -123,7 +123,7 @@ DEFINE_TEST(test_pax_xattr_header) assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assertEqualFile("test4.tar","test_pax_xattr_header_all.tar"); } diff --git a/contrib/libarchive/libarchive/test/test_read_disk_directory_traversals.c b/contrib/libarchive/libarchive/test/test_read_disk_directory_traversals.c index 7597f4b6f6..718818c36b 100644 --- a/contrib/libarchive/libarchive/test/test_read_disk_directory_traversals.c +++ b/contrib/libarchive/libarchive/test/test_read_disk_directory_traversals.c @@ -230,7 +230,7 @@ test_basic(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Test that call archive_read_disk_open_w, wchar_t version. @@ -358,7 +358,7 @@ test_basic(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Test that call archive_read_disk_open with a regular file. @@ -381,7 +381,7 @@ test_basic(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); #if defined(_WIN32) && !defined(__CYGWIN__) @@ -427,7 +427,7 @@ test_basic(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Test for a full-path beginning with "//?/" @@ -458,7 +458,7 @@ test_basic(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); free(fullpath); /* @@ -515,7 +515,7 @@ test_basic(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); free(fullpath); #endif @@ -658,7 +658,7 @@ test_symlink_hybrid(void) /* There is no entry. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Specified file is a directory and it has symbolic files. @@ -722,7 +722,7 @@ test_symlink_hybrid(void) /* There is no entry. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* Destroy the disk object. */ assertEqualInt(ARCHIVE_OK, archive_read_free(a)); archive_entry_free(ae); @@ -827,7 +827,7 @@ test_symlink_logical(void) /* There is no entry. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Specified file is a directory and it has symbolic files. @@ -953,7 +953,7 @@ test_symlink_logical(void) /* There is no entry. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* Destroy the disk object. */ assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -1131,7 +1131,7 @@ test_restore_atime(void) assertFileAtime("at/fe", 886611, 0); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Test2: Traversals with archive_read_disk_set_atime_restored(). @@ -1197,7 +1197,7 @@ test_restore_atime(void) assertFileAtime("at/fe", 886611, 0); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Test3: Traversals with archive_read_disk_set_atime_restored() but @@ -1254,7 +1254,7 @@ test_restore_atime(void) } /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Test4: Traversals with ARCHIVE_READDISK_RESTORE_ATIME and @@ -1406,7 +1406,7 @@ test_callbacks(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* Reset name filter */ assertEqualIntA(a, ARCHIVE_OK, @@ -1539,7 +1539,7 @@ test_nodump(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Test2: Traversals with ARCHIVE_READDISK_HONOR_NODUMP @@ -1671,7 +1671,7 @@ test_parent(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertChdir("../.."); @@ -1720,7 +1720,7 @@ test_parent(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Test3: Traverse lock/dir1/. @@ -1767,7 +1767,7 @@ test_parent(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Test4: Traverse lock/lock2/dir1 from inside lock. @@ -1842,7 +1842,7 @@ test_parent(void) archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); } assertChdir(".."); diff --git a/contrib/libarchive/libarchive/test/test_read_files_compressed.c b/contrib/libarchive/libarchive/test/test_read_files_compressed.c new file mode 100644 index 0000000000..4795d750ba --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_files_compressed.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2026 Tobias Stoeckmann + * 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_files_compressed) +{ + const char *reffiles[] = + { + "test_read_files_compressed.part01", + "test_read_files_compressed.part02", + NULL + }; + + struct archive *a; + struct archive_entry *entry = NULL; + + extract_reference_files(reffiles); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filenames(a, reffiles, 10240)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &entry)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/contrib/libarchive/libarchive/test/test_read_files_compressed.part01.uu b/contrib/libarchive/libarchive/test/test_read_files_compressed.part01.uu new file mode 100644 index 0000000000..346545a0dc --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_files_compressed.part01.uu @@ -0,0 +1,4 @@ +begin 644 test_read_files_compressed.part01 +"'YT` +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_files_compressed.part02.uu b/contrib/libarchive/libarchive/test/test_read_files_compressed.part02.uu new file mode 100644 index 0000000000..41e440391a --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_files_compressed.part02.uu @@ -0,0 +1,4 @@ +begin 644 test_read_files_compressed.part02 +!```` +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_filter_compress.c b/contrib/libarchive/libarchive/test/test_read_filter_compress.c index 03a1d5fbe9..d03fdc9d63 100644 --- a/contrib/libarchive/libarchive/test/test_read_filter_compress.c +++ b/contrib/libarchive/libarchive/test/test_read_filter_compress.c @@ -35,7 +35,7 @@ DEFINE_TEST(test_read_filter_compress_truncated) assertEqualIntA(a, ARCHIVE_FATAL, archive_read_open_memory(a, data, sizeof(data))); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -59,7 +59,7 @@ DEFINE_TEST(test_read_filter_compress_empty2) assertEqualString(archive_filter_name(a, 0), "compress (.Z)"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_EMPTY); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -75,6 +75,6 @@ DEFINE_TEST(test_read_filter_compress_invalid) assertEqualIntA(a, ARCHIVE_FATAL, archive_read_open_memory(a, data, sizeof(data))); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_filter_grzip.c b/contrib/libarchive/libarchive/test/test_read_filter_grzip.c index 43bd5bca26..7e58a62100 100644 --- a/contrib/libarchive/libarchive/test/test_read_filter_grzip.c +++ b/contrib/libarchive/libarchive/test/test_read_filter_grzip.c @@ -62,6 +62,6 @@ DEFINE_TEST(test_read_filter_grzip) assertEqualString(archive_filter_name(a, 0), "grzip"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_filter_gzip_recursive.c b/contrib/libarchive/libarchive/test/test_read_filter_gzip_recursive.c index 51b614b6c0..56889820e6 100644 --- a/contrib/libarchive/libarchive/test/test_read_filter_gzip_recursive.c +++ b/contrib/libarchive/libarchive/test/test_read_filter_gzip_recursive.c @@ -45,6 +45,6 @@ DEFINE_TEST(test_read_filter_gzip_recursive) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_GZIP); assertEqualString(archive_filter_name(a, 0), "gzip"); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_filter_lrzip.c b/contrib/libarchive/libarchive/test/test_read_filter_lrzip.c index 47388da0fb..5caeb0fe57 100644 --- a/contrib/libarchive/libarchive/test/test_read_filter_lrzip.c +++ b/contrib/libarchive/libarchive/test/test_read_filter_lrzip.c @@ -62,6 +62,6 @@ DEFINE_TEST(test_read_filter_lrzip) assertEqualString(archive_filter_name(a, 0), "lrzip"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_filter_lz4_raw.c b/contrib/libarchive/libarchive/test/test_read_filter_lz4_raw.c new file mode 100644 index 0000000000..9cbb561e57 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_filter_lz4_raw.c @@ -0,0 +1,40 @@ +/*- + * Copyright (c) 2026 Tobias Stoeckmann + * 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_filter_lz4_raw_skip) +{ + struct archive *a; + + const char *name = "test_read_filter_lz4_raw_skip"; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_raw(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_FATAL, + archive_read_open_filename(a, name, 200)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/contrib/libarchive/libarchive/test/test_read_filter_lz4_raw_skip.uu b/contrib/libarchive/libarchive/test/test_read_filter_lz4_raw_skip.uu new file mode 100644 index 0000000000..aaff306b80 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_filter_lz4_raw_skip.uu @@ -0,0 +1,4 @@ +begin 644 test_read_filter_lz4_raw_skip.uu +'AX>'AX>'AX>'A +MX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'A +MX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'A +MX>'AX>'AX>'AX0$.`8`/`8`1#0!E`&T`<`!T`'D````4"@$`@-9``*BRG0$5 +)!@$`(("D@0`` +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_format_7zip_entries_oom.c b/contrib/libarchive/libarchive/test/test_read_format_7zip_entries_oom.c new file mode 100644 index 0000000000..8c7a779924 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_7zip_entries_oom.c @@ -0,0 +1,56 @@ +/*- + * 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" + +/* + * A 7z archive whose FilesInfo section declares far more files than the + * remaining header bytes can structurally support previously caused + * libarchive to attempt a ~2.5 GiB calloc(). The fix rejects the file + * count before allocating: empty-file entries require a kEmptyStream + * bitmap of ceil(numFiles/8) bytes, so numFiles beyond the known stream + * count cannot exceed 8 * header_bytes_remaining. + */ +DEFINE_TEST(test_read_format_7zip_entries_oom) +{ + const char *refname = "test_read_format_7zip_entries_oom.7z"; + struct archive *a; + struct archive_entry *ae; + + 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_OK, + archive_read_open_filename(a, refname, 10240)); + + /* + * Header parsing must fail gracefully rather than attempting a + * multi-gigabyte allocation for the entry array. + */ + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/contrib/libarchive/libarchive/test/test_read_format_7zip_issue2765.c b/contrib/libarchive/libarchive/test/test_read_format_7zip_issue2765.c index 7c45c313b3..3232a87ef9 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_7zip_issue2765.c +++ b/contrib/libarchive/libarchive/test/test_read_format_7zip_issue2765.c @@ -46,6 +46,6 @@ DEFINE_TEST(test_read_format_7zip_issue2765) assertEqualInt(0, archive_file_count(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_7zip_malformed.c b/contrib/libarchive/libarchive/test/test_read_format_7zip_malformed.c index bd3452c00a..22c258fd03 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_7zip_malformed.c +++ b/contrib/libarchive/libarchive/test/test_read_format_7zip_malformed.c @@ -39,7 +39,7 @@ test_malformed1(void) assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } static void @@ -56,7 +56,7 @@ test_malformed2(void) assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -72,7 +72,42 @@ test_malformed3(void) 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)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + +static void +test_malformed4(void) +{ + const char *refname = "test_read_format_7zip_malformed4.7z"; + struct archive *a; + struct archive_entry *ae; + + 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_OK, archive_read_open_filename(a, refname, 10240)); + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_malformed_numfiles_oom(void) +{ + const char *refname = "test_read_format_7zip_malformed_numfiles_oom.7z"; + struct archive *a; + struct archive_entry *ae; + + 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_OK, archive_read_open_filename(a, refname, 10240)); + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_7zip_malformed) @@ -80,4 +115,6 @@ DEFINE_TEST(test_read_format_7zip_malformed) test_malformed1(); test_malformed2(); test_malformed3(); + test_malformed4(); + test_malformed_numfiles_oom(); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_7zip_malformed4.7z.uu b/contrib/libarchive/libarchive/test/test_read_format_7zip_malformed4.7z.uu new file mode 100644 index 0000000000..45597aa13a --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_7zip_malformed4.7z.uu @@ -0,0 +1,5 @@ +begin 644 test_read_format_7zip_malformed4.7z +M-WJ\KR<<``0N^]EU```````````9`````````&WKXL4!!`8``0D```<+`0`! +,`0`,```(#0(````` +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_format_7zip_malformed_numfiles_oom.7z.uu b/contrib/libarchive/libarchive/test/test_read_format_7zip_malformed_numfiles_oom.7z.uu new file mode 100644 index 0000000000..bb1f75efa1 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_7zip_malformed_numfiles_oom.7z.uu @@ -0,0 +1,5 @@ +begin 644 test_read_format_7zip_malformed_numfiles_oom.7z +M-WJ\KR<<``,%;\HA```````````N`````````,Z^!W,!!>,.`8`/`8`1#0!E +A`&T`<`!T`'D````4"@$`@-9``*BRG0$5!@$`(("D@0`` +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_format_7zip_packinfo_digests.c b/contrib/libarchive/libarchive/test/test_read_format_7zip_packinfo_digests.c index e46a17b3b1..75f90f2df8 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_7zip_packinfo_digests.c +++ b/contrib/libarchive/libarchive/test/test_read_format_7zip_packinfo_digests.c @@ -82,7 +82,7 @@ DEFINE_TEST(test_read_format_7zip_packinfo_digests) archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); } assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_cab.c b/contrib/libarchive/libarchive/test/test_read_format_cab.c index f5ce21cbf1..0adf24c7c6 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_cab.c +++ b/contrib/libarchive/libarchive/test/test_read_format_cab.c @@ -266,7 +266,7 @@ verify(const char *refname, enum comp_type comp) /* Close the archive. */ finish: - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -332,7 +332,7 @@ verify2(const char *refname, enum comp_type comp) assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -387,7 +387,7 @@ verify3(const char *refname, enum comp_type comp) assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_cab_filename.c b/contrib/libarchive/libarchive/test/test_read_format_cab_filename.c index efab3ccd69..8c0d170428 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_cab_filename.c +++ b/contrib/libarchive/libarchive/test/test_read_format_cab_filename.c @@ -79,7 +79,7 @@ test_read_format_cab_filename_CP932_eucJP(const char *refname) /* Close the archive. */ cleanup: - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -157,7 +157,7 @@ test_read_format_cab_filename_CP932_UTF8(const char *refname) /* Close the archive. */ cleanup: - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_cab_mszip_oob.c b/contrib/libarchive/libarchive/test/test_read_format_cab_mszip_oob.c new file mode 100644 index 0000000000..da98a96b2f --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_cab_mszip_oob.c @@ -0,0 +1,93 @@ +#include "test.h" + +/* + * Regression test for OOB read/write in the CAB MSZIP decoder. + * + * A crafted CFDATA block carries a stored-block deflate header whose LEN + * field (0x9000) is larger than the actual compressed payload. Without the + * fix, the decoder reads one byte past the end of the input buffer on the + * second archive_read_next_header() call (after the first call returns + * ARCHIVE_FATAL due to the truncated payload). + */ +DEFINE_TEST(test_read_format_cab_mszip_oob) +{ + const uint16_t LEN = 0x9000; + const uint16_t NLEN = (uint16_t)~LEN; + const uint8_t first = 0xFF; + + /* + * cbData and cbUncomp are chosen so that the two-byte sequences they + * occupy inside the CFDATA header also form a valid deflate stored-block + * length / complement pair when the decoder's read pointer is positioned + * one field early. + */ + const uint16_t cbData = (LEN >> 8) | ((NLEN & 0xff) << 8); + const uint16_t cbUncomp = (NLEN >> 8) | ((uint16_t)first << 8); + + const size_t payload = (size_t)LEN - 1; /* one byte short of LEN */ + const size_t total = 36 + 8 + 18 + 8 + payload; + + uint8_t *b = (uint8_t *)calloc(1, total); + assert(b != NULL); + + /* CFHEADER (36 bytes) */ + memcpy(b, "MSCF", 4); + b[8] = (uint8_t)(total); + b[9] = (uint8_t)(total >> 8); + b[10] = (uint8_t)(total >> 16); + b[11] = (uint8_t)(total >> 24); + b[16] = 44; /* coffFiles: first CFFILE at offset 44 */ + b[24] = 3; b[25] = 1; /* version 1.3 */ + b[26] = 1; /* cFolders = 1 */ + b[28] = 1; /* cFiles = 1 */ + + /* CFFOLDER (8 bytes at offset 36) */ + b[36] = 62; /* coffCabStart: first CFDATA at offset 62 */ + b[40] = 1; /* cCFData = 1 */ + b[42] = 0x01; /* typeCompress = MSZIP */ + + /* CFFILE (18 bytes at offset 44) */ + b[44] = 0x00; b[45] = 0x01; /* cbFile = 0x100 */ + b[54] = 0x21; /* date low */ + b[58] = 0x20; /* attribs low */ + b[60] = 'a'; b[61] = 0; /* szName "a" */ + + /* CFDATA header (8 bytes at offset 62) */ + b[62] = 0x43; b[63] = 0x4B; /* checksum bytes (also MSZIP "CK" marker) */ + b[64] = 0x01; + b[65] = (uint8_t)(LEN & 0xff); + b[66] = (uint8_t)(cbData); + b[67] = (uint8_t)(cbData >> 8); + b[68] = (uint8_t)(cbUncomp); + b[69] = (uint8_t)(cbUncomp >> 8); + + /* Compressed payload: one byte short of what the stored-block LEN claims */ + memset(b + 70, first, payload); + + /* Open the crafted archive from memory */ + struct archive *a = archive_read_new(); + assert(a != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_cab(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, b, total)); + + struct archive_entry *ae; + char buf[4096]; + + /* The single CFFILE header is well-formed and should read cleanly. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("a", archive_entry_pathname(ae)); + + /* + * Reading data must fail: cbUncomp (0xFF6F) exceeds the decoder's + * uncompressed buffer (0x8000), so the bounds check returns FATAL + * rather than writing past the buffer end. + */ + assertEqualInt(ARCHIVE_FATAL, archive_read_data(a, buf, sizeof(buf))); + + /* The archive is in FATAL state and should remain that way. */ + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + free(b); +} diff --git a/contrib/libarchive/libarchive/test/test_read_format_cab_multi.c b/contrib/libarchive/libarchive/test/test_read_format_cab_multi.c new file mode 100644 index 0000000000..f911f2187a --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_cab_multi.c @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 2026 Tobias Stoeckmann + * 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_cab_multi) +{ + /* Reference to multi volume CAB files */ + const char *refname1 = "test_read_format_cab_multi.p1.cab"; + const char *refname2 = "test_read_format_cab_multi.p2.cab"; + struct archive *a; + struct archive_entry *ae; + + /* Extract the reference files into the test sandbox */ + extract_reference_file(refname1); + extract_reference_file(refname2); + + /* Initialize the archive reader for first part */ + 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, refname1, 10)); + + /* Read entry */ + assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "ones"); + assertEqualInt(archive_entry_size(ae), 512); + + /* Clean up reader */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* Initialize the archive reader for second part */ + 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, refname2, 10)); + + /* Read entry */ + assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "ones"); + assertEqualInt(archive_entry_size(ae), 512); + + /* Clean up reader */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} \ No newline at end of file diff --git a/contrib/libarchive/libarchive/test/test_read_format_cab_multi.p1.cab.uu b/contrib/libarchive/libarchive/test/test_read_format_cab_multi.p1.cab.uu new file mode 100644 index 0000000000..babd7a330d --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_cab_multi.p1.cab.uu @@ -0,0 +1,15 @@ +begin 644 test_read_format_cab_multi.p1.cab +M35-#1@```````@```````$\``````````P$!``$``@"U`0``=&5S=%]R96%D +M7V9O(`&@```````!H`"``````(`'P!`0`````"```!```! +MP`!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!% +M`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4` +M10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!% +M`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4` +M10!%`$4`10!%`$4`10`````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````"(`&@```````!H`"``````(`'P!`0`````"```!```! +M`0`B`!D````````9``@`````"`!\`0$``````@```0```0$!)``````````` +M````````````?`$!``````````$```$"`$8````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +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/contrib/libarchive/libarchive/test/test_read_format_iso_rockridge_ce_loop.iso.Z.uu b/contrib/libarchive/libarchive/test/test_read_format_iso_rockridge_ce_loop.iso.Z.uu new file mode 100644 index 0000000000..20e08d3569 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_iso_rockridge_ce_loop.iso.Z.uu @@ -0,0 +1,61 @@ +begin 644 test_read_format_iso_rockridge_ce_loop.iso.Z +M'YV0``(*'$BPH,&#"!,J7,BPH<.'$"-*G$BQHL6+&#-JW,BQH\>/($.*'$FR +MI,F3*%.J7,FRIO8,.*'4NVK-FS:-.J7//JW/'D"-+GDRYLN7+F#-KWLRY +ML^?/H$.+'DVZM.G3J%.K7LVZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +MO?OW\./+GT^_OOW[^//KW\^_O_^_`0Q!!`PPQ!```$;(44890DQ!!`@01BCA +MA!1***`43S11X88<1GC0+06!Z-&!``1`XH$((`"`!059,$%"%0PD`@`7%%2C +MB@*I:$0``B10(@D"!'3B@1T6:>212":IY)),-NGDDU!&*>645%9I991-+)'$ +M%$\8,04(6SX!0@XVV`##"TAX"8(123!1Q!193$%%$1H*446;1!0A!0@F@'!A +M$4,\(<6#`K8@Q0M$6$&H%$4$086@(*`P1`H@Q)!##C.`4(0+63Q1A1-'$!&$ +MFY%.6NFE-X"@A`M0-"H%ETZ\L.H40R#1)A-)@'KEKKSN*@.!.<10H`PQR%## +MKV;"0,*O,`0[;+''PI`L"016:^VU!`+`K+/%0HLL@200V>NXY)9K[KGHIJON +MNNRVZ^Z2_\6[V#\"$FB@O/CFJ^^^_/9;799)@-#$&VZ`\,08=%0J@\(Z'*N# +MM"!LJX`,+A18<0QAV)"IH2"T4$<:9%3:\1D@1PR""RB_D,8<;_CK\LLPQRSS +MS&G=0L^!-0HIT```9"#0@40D(07-1!=M]-%()ZWTTDPW[?334+]&8D`UDLBS +M0#X'$/3047?M]==@ARWVV&27;?;9:"<-"8TV`H!C0#KRZ&,`0.I,&VP3=.%#EQSHAT0^3IKJL!'X2\"!YI"'-L3`CH@+Q4!"T0X_ +MFJ@@/"J(`"(Y24G"8PI,$(.)`K`%*_KREV'`(@3I41!Z=*$@77CD.VHI2;\9 +MY)+KTV06FD"Q^=4/E$T0)0!(V089H+(=JA0(*UWI2D`"0`#+9.8[<*E+$_42 +MF/"4HC`)@L/(!<\+!?'"(]W!S'^XPY)IQ*0TFS`#3PH.F]KDY@R^&JCK'*7R]SFBDU/K50`%0Z1 +MVR1`X0N6"I:CD%`$$&!H"$OP;A*(<(3NYFI.4JA5$$#572A@Z%&!8@((W/L$ +M*XSW32"80A6@``5!46%-D.KO%)*`A36UJ;MPDA.=\DNG]5(A"4/(FYN",(7N +M!LH)5`C"$/X;-%K-MPI"P-44N+LG(T`J;X!*`IN&X*@D/,$)^?54>C<%H0JW +M%\0B)C&8\H1A%2=!3V""L7N3T(0@2"$+(+#"$YA0A29T-T^TDH)U'U5B2%TX +MPQL.LHFE4.0'O]@%S@VSF,=,9OV@H0QL8,,;*E6#&2B@S'".LYSG3.,ZSGM]SYC2O.0;'>O.>!TWH0AOZT(A.M*(7S>A&>Z7/:F9S#`3MZ$I;^M*8 +MSK2F-\WI3GOZTZ`.M:A'3>I2F_K4J$ZUJE?-ZE:[^M6PCK6L9TWK6MOZUKC. +MM:YWS>M>^_K7P`ZVL(=-[&(;^]C(3K:RE\WL9CO[V=".MK2G3>UJ6_O:V,ZV +MMK?-[6Y[^]O@#K>XQTWNYVN_O=\(ZWO.=-[WK;^][XSK>^ +M]\WO?OO[WP`/N,`'3O""&_S@"$^XPA?.\(8[_.$0C[C$)T[QBEO\XAC/N,8W +MSO&.>_SC(`^YR$=.\I*;_.0H3[G*5\[REKO\Y3"/NI8S[K6M\[U +MKGO]ZV`/N]C'3O:RF_WL:$^[VM?.]K:[_>UPC[O^ +M^_WO@`^\X`=/^,(;_O"(3[SB%\_XQCO^\9"/O.0G3_G*6_[RF,^\YC?/^I7S_K6N_[UL(^][&=/^]K;_O:XS[WN=\_[WOO^ +M]\`/OO"'3_SB&__XR$^^\I?/_.8[__G0C[[TIT_]ZEO_^MC/OO:WS_WN>__[ +MX`^_^,=/_O*;__SH3[_ZU\_^]KO__?"/O_SG3__ZV__^^,^__O?/__[[__\` +M&(`".(`$6(`&>(`(F(`*N(`,V(`.^(`0&($2.($46($6>($8F($:N($ +M^($@&((B.((D6((F>((HF((JN((LV((N^((P&(,R.(,T6(,V>(,XF(,ZN(,\ +MV(,^^(-`&(1".(1$6(1&>(1(F(1*N(1,V(1.^(10&(52.(546(56>(58F(5: +MN(5^(5@&(9B.(9D6(9F>(9HF(9JN(9LV(9N^(9P&(=R.(=T6(=V>(=X +MF(=ZN(=\V(=^^(>`&(B".(B$6(B&>(B(F(B*N(B,V(B.^(B0&(F2.(F46(F6 +*>(F8F(F:N(D_`0`` +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_format_isorr_ce_loop.c b/contrib/libarchive/libarchive/test/test_read_format_isorr_ce_loop.c new file mode 100644 index 0000000000..b1cdd6e82a --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_isorr_ce_loop.c @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2026 Zhihan Zheng + * 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" + +/* + * A malformed Rock Ridge ISO whose first CE continuation area contains + * another CE entry that points back to the same area. The parser should + * reject this self-referential continuation chain with ARCHIVE_FATAL + * instead of looping while reading headers. + */ + +DEFINE_TEST(test_read_format_isorr_ce_loop) +{ + const char *refname = "test_read_format_iso_rockridge_ce_loop.iso.Z"; + struct archive *a; + struct archive_entry *ae; + int r; + + 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_OK, archive_read_open_filename(a, refname, 10240)); + + /* Read entries until the self-referential CE is reached. */ + while ((r = archive_read_next_header(a, &ae)) == ARCHIVE_OK) + archive_read_data_skip(a); + + /* The parser should reject the self-referential CE with ARCHIVE_FATAL. */ + assertEqualIntA(a, ARCHIVE_FATAL, r); + assert(archive_errno(a) != 0); + assert(archive_error_string(a) != NULL); + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/contrib/libarchive/libarchive/test/test_read_format_lha.c b/contrib/libarchive/libarchive/test/test_read_format_lha.c index 93e79183e5..b323cb3c86 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_lha.c +++ b/contrib/libarchive/libarchive/test/test_read_format_lha.c @@ -266,7 +266,7 @@ verify(const char *refname, int posix) assertEqualIntA(a, ARCHIVE_FORMAT_LHA, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_lha_bugfix_0.c b/contrib/libarchive/libarchive/test/test_read_format_lha_bugfix_0.c index bbdcb81569..342dd1ef3c 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_lha_bugfix_0.c +++ b/contrib/libarchive/libarchive/test/test_read_format_lha_bugfix_0.c @@ -69,7 +69,7 @@ DEFINE_TEST(test_read_format_lha_bugfix_0) assertEqualIntA(a, ARCHIVE_FORMAT_LHA, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_lha_filename.c b/contrib/libarchive/libarchive/test/test_read_format_lha_filename.c index d726f6245d..22c303aa4b 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_lha_filename.c +++ b/contrib/libarchive/libarchive/test/test_read_format_lha_filename.c @@ -85,7 +85,7 @@ test_read_format_lha_filename_CP932_eucJP(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_LHA, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -145,7 +145,7 @@ test_read_format_lha_filename_CP932_UTF8(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_LHA, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -195,7 +195,7 @@ test_read_format_lha_filename_CP932_Windows(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_LHA, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } #else diff --git a/contrib/libarchive/libarchive/test/test_read_format_lha_filename_utf16.c b/contrib/libarchive/libarchive/test/test_read_format_lha_filename_utf16.c index d0710799bb..f700ec3c3e 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_lha_filename_utf16.c +++ b/contrib/libarchive/libarchive/test/test_read_format_lha_filename_utf16.c @@ -127,7 +127,7 @@ test_read_format_lha_filename_UTF16_UTF8(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_LHA, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_mtree.c b/contrib/libarchive/libarchive/test/test_read_format_mtree.c index b4463298dd..e95bdabc39 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_mtree.c +++ b/contrib/libarchive/libarchive/test/test_read_format_mtree.c @@ -269,7 +269,7 @@ test_read_format_mtree1(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(30, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -299,7 +299,7 @@ test_read_format_mtree2(void) assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(1, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -348,7 +348,7 @@ test_read_format_mtree3(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(3, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); assertChdir(".."); @@ -418,7 +418,7 @@ DEFINE_TEST(test_read_format_mtree_filenames_only) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(6, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -477,7 +477,7 @@ DEFINE_TEST(test_read_format_mtree_nochange) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(3, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* @@ -518,7 +518,7 @@ DEFINE_TEST(test_read_format_mtree_nochange) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(3, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -620,7 +620,7 @@ DEFINE_TEST(test_read_format_mtree_nomagic_v1_form) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(12, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -687,7 +687,7 @@ DEFINE_TEST(test_read_format_mtree_nomagic_v2_form) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(6, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -754,7 +754,7 @@ DEFINE_TEST(test_read_format_mtree_nomagic_v2_netbsd_form) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(6, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -785,7 +785,7 @@ DEFINE_TEST(test_read_format_mtree_nonexistent_contents_file) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(1, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -811,7 +811,7 @@ DEFINE_TEST(test_read_format_mtree_noprint) assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); assertEqualString("Can't parse line 3", archive_error_string(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -840,6 +840,41 @@ DEFINE_TEST(test_read_format_mtree_tab) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(1, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_mtree_nano) +{ + static char archive[] = + "#mtree\n" + "a type=file time=1234567890.1000000000000 contents=nonexistent_file\n" + "b type=file time=1234567899.-1000000000000 contents=nonexistent_file\n"; + 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)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "a"); + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualIntA(a, archive_entry_mtime(ae), 1234567890); + assertEqualIntA(a, archive_entry_mtime_nsec(ae), 999999999); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "b"); + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualIntA(a, archive_entry_mtime(ae), 1234567899); + assertEqualIntA(a, archive_entry_mtime_nsec(ae), 0); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_pax_bz2.c b/contrib/libarchive/libarchive/test/test_read_format_pax_bz2.c index 4f11137b9c..1e3cb07919 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_pax_bz2.c +++ b/contrib/libarchive/libarchive/test/test_read_format_pax_bz2.c @@ -48,8 +48,8 @@ DEFINE_TEST(test_read_format_pax_bz2) assert((a = archive_read_new()) != NULL); r = archive_read_support_filter_bzip2(a); if (r != ARCHIVE_OK) { - archive_read_close(a); skipping("Bzip2 unavailable"); + archive_read_free(a); return; } assertEqualIntA(a,ARCHIVE_OK, archive_read_support_format_all(a)); diff --git a/contrib/libarchive/libarchive/test/test_read_format_rar.c b/contrib/libarchive/libarchive/test/test_read_format_rar.c index 59e83846c8..f8e4b324fc 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_rar.c +++ b/contrib/libarchive/libarchive/test/test_read_format_rar.c @@ -592,6 +592,42 @@ DEFINE_TEST(test_read_format_rar_multi_lzss_blocks) assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } +DEFINE_TEST(test_read_format_rar3_lowdist_reset) +{ + const char reffile[] = "test_read_format_rar3_lowdist_reset.rar"; + const unsigned char expected[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x0d, 0x0e, + 0x0f, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, + 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 + }; + unsigned char buff[sizeof(expected)]; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_rar(a)); + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("lowdist-reset.bin", archive_entry_pathname(ae)); + assertEqualInt(sizeof(expected), archive_entry_size(ae)); + assertEqualIntA(a, sizeof(expected), + archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, expected, sizeof(expected)); + + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + DEFINE_TEST(test_read_format_rar_compress_best) { const char reffile[] = "test_read_format_rar_compress_best.rar"; @@ -3807,7 +3843,7 @@ DEFINE_TEST(test_read_format_rar_multivolume_uncompressed_files) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, 16, archive_file_count(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_rar_endarc_huge) @@ -3906,6 +3942,54 @@ DEFINE_TEST(test_read_format_rar_newsub_huge) #endif } +DEFINE_TEST(test_read_format_rar_newsub_rr_over_1m) +{ + const char* reffile = "test_read_format_rar_newsub_rr_over_1m.rar"; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_rar(a)); + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + + failure("RAR NEWSUB RR records larger than 1 MiB should be skipped"); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_rar_newsub_huge64) +{ + static const unsigned char archive[] = { + 'R', 'a', 'r', '!', 0x1a, 0x07, 0x00, + 0x23, 0x25, 0x7a, 0x00, 0x01, 0x28, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0x00, 0x00, 0x00 + }; + struct archive_entry *ae; + struct archive *a; + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_rar(a)); + assertA(0 == archive_read_open_memory(a, archive, sizeof(archive))); + + failure("Malformed RAR NEWSUB header should be rejected if its " + "extended data is missing"); + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + assertEqualString("Invalid RAR file: Cannot read extended header data", + archive_error_string(a)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + DEFINE_TEST(test_read_format_rar_symlink_huge) { #if SIZE_MAX == UINT64_MAX @@ -3929,3 +4013,24 @@ DEFINE_TEST(test_read_format_rar_symlink_huge) assertEqualInt(ARCHIVE_OK, archive_read_free(a)); #endif } + +DEFINE_TEST(test_read_format_rar_unbound_staticdata) +{ + const char* reffile = "test_read_format_rar_unbound_staticdata.rar"; + + struct archive_entry *ae; + struct archive *a; + char buf[64]; + + 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, 1024)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_FAILED, archive_read_data(a, buf, 64)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/contrib/libarchive/libarchive/test/test_read_format_rar3_lowdist_reset.rar.uu b/contrib/libarchive/libarchive/test/test_read_format_rar3_lowdist_reset.rar.uu new file mode 100644 index 0000000000..3bb7ed9cbf --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_rar3_lowdist_reset.rar.uu @@ -0,0 +1,16 @@ +begin 644 test_read_format_rar3_lowdist_reset.rar +M4F%R(1H' ,^0

file.bytes_remaining in process_block(). A malformed RAR5 + * archive whose compressed-block to_skip value exceeds the declared + * remaining file data drives bytes_remaining negative; the negative + * ssize_t later reaches read_ahead() and is implicitly converted to + * a near-SIZE_MAX malloc request (CWE-122). + * + * The patched reader must reject the malformed archive with + * ARCHIVE_FATAL before the negative value is reached. */ + + char buf[4096]; + la_ssize_t r; + PROLOGUE("test_read_format_rar5_bytes_remaining_underflow.rar"); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("poc.txt", archive_entry_pathname(ae)); + + do { + r = archive_read_data(a, buf, sizeof(buf)); + } while (r > 0); + + assertEqualIntA(a, ARCHIVE_FATAL, r); + assertA(archive_error_string(a) != NULL); + + EPILOGUE(); +} diff --git a/contrib/libarchive/libarchive/test/test_read_format_rar5_bad_filter.c b/contrib/libarchive/libarchive/test/test_read_format_rar5_bad_filter.c new file mode 100644 index 0000000000..6f24bc7436 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_rar5_bad_filter.c @@ -0,0 +1,130 @@ +/*- + * Copyright (c) 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" + +/* + * Two-entry RAR5 archive. Entry 1 ("bad.txt") is compressed with a filter + * of unsupported type 4 (FILTER_AUDIO). Entry 2 ("ok.txt") is stored. + * + * Tests that an unsupported filter type in do_uncompress_file returns + * ARCHIVE_FAILED (not ARCHIVE_FATAL), so the archive is not aborted and + * the second entry is still readable. + * + * RAR5 outer block format: 4-byte LE CRC32 of (vint(hdr_size)+hdr_body), + * then vint(hdr_size), then hdr_body, then optional data area. + * Integers are vint: 7 bits per byte, LSB first, high bit = more follows. + */ +DEFINE_TEST(test_read_format_rar5_bad_filter) +{ + static const uint8_t data[] = { + /* RAR5 signature */ + 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0x00, + + /* Main archive header block (type=1): + * CRC32, vint(body_size=3), type=1, block_flags=0, + * archive_flags=0 */ + 0xC5, 0x1A, 0x33, 0x32, 0x03, 0x01, 0x00, 0x00, + + /* File header block for "bad.txt" (type=2, HFL_DATA flag set): + * CRC32, vint(body_size=17), type=2, HFL_DATA, + * packed_size=23, file_flags=0, unpacked_size=4, + * file_attr=0, compression_info=512 (method=GOOD, + * version=0, window_factor=0), host_os=1, + * name_len=7, "bad.txt" */ + 0x88, 0xEC, 0xB0, 0x99, 0x11, 0x02, 0x02, 0x17, + 0x00, 0x04, 0x00, 0x80, 0x04, 0x01, 0x07, 0x62, + 0x61, 0x64, 0x2E, 0x74, 0x78, 0x74, + + /* Compressed data block for "bad.txt" (23 bytes): + * + * Compressed block header (3 bytes): + * block_flags=0xC2: is_table_present, is_last_block, + * bf_bit_size=2 (block ends when + * in_addr==last_byte && bit_addr>=3) + * checksum=0x8C, block_size=20 */ + 0xC2, 0x8C, 0x14, + + /* Huffman meta-table (20 nibbles packed in 10 bytes): + * nibble[2]=1, nibble[19]=1, all others 0. + * Two 1-bit meta-symbols: + * code 0 -> sym 2 (store bit-length 2 for next entry) + * code 1 -> sym 19 (fill N+11 zeros, N in next 7 bits) */ + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, + + /* Huffman main table + compressed data (MSB-first bitstream): + * + * Main table (ld[], 430 entries, 42 bits total): + * skip 97 zeros (sym19, n=86), ld[97]=2 (sym2, 'a'), + * skip 138 zeros, skip 20 zeros, + * ld[256]=2 (sym2, filter token), skip 138+35 zeros. + * Canonical codes: 00->sym97('a'), 01->sym256(filter). + * + * Compressed data (33 bits): + * 01 filter token (sym 256) + * 00,00000000 block_start: count=0->1 byte, value=0 + * 00,00000100 block_length: count=0->1 byte, value=4 + * 100 filter_type=4 (FILTER_AUDIO, unsupported; + * top 3 bits of a 16-bit read, 3 bits consumed) + * 00,00,00,00 four 'a' literals (sym 97, code 00 each) */ + 0xD6, 0x7F, 0xC4, 0xBF, 0xE6, 0x10, 0x00, 0x04, + 0x80, 0x00, + + /* File header block for "ok.txt" (type=2, HFL_DATA flag set): + * CRC32, vint(body_size=15), type=2, HFL_DATA, + * packed_size=3, file_flags=0, unpacked_size=3, + * file_attr=0, compression_info=0 (STORE), + * host_os=1, name_len=6, "ok.txt", data "ok\n" */ + 0xB1, 0xC3, 0x30, 0x14, 0x0F, 0x02, 0x02, 0x03, + 0x00, 0x03, 0x00, 0x00, 0x01, 0x06, 0x6F, 0x6B, + 0x2E, 0x74, 0x78, 0x74, 0x6F, 0x6B, 0x0A, + + /* End of archive block (type=5): + * CRC32, vint(body_size=2), type=5, block_flags=0 */ + 0x39, 0xF9, 0xB2, 0x81, 0x02, 0x05, 0x00, + }; + + struct archive_entry *ae; + struct archive *a; + char buf[256]; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_rar5(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, data, sizeof(data))); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("bad.txt", archive_entry_pathname(ae)); + assertA(archive_read_data(a, buf, sizeof(buf)) < 0); + assertA(archive_error_string(a) != NULL && + strstr(archive_error_string(a), "Unsupported filter type") != NULL); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ok.txt", archive_entry_pathname(ae)); + assertEqualIntA(a, 3, archive_read_data(a, buf, sizeof(buf))); + assertEqualMem(buf, "ok\n", 3); + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/contrib/libarchive/libarchive/test/test_read_format_rar5_bad_tables.c b/contrib/libarchive/libarchive/test/test_read_format_rar5_bad_tables.c new file mode 100644 index 0000000000..cb64face63 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_rar5_bad_tables.c @@ -0,0 +1,59 @@ +/*- + * 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" + +/* + * The reference archive contains one compressed entry whose HUFF_BC + * meta-table has all 20 nibbles set to bit-length 1. This is an + * over-subscribed Huffman table (Kraft sum = 10 >> 1), which + * create_decode_tables() must reject. Reading the entry data must + * therefore fail, not succeed. + */ +DEFINE_TEST(test_read_format_rar5_bad_tables) +{ + const char *reffile = "test_read_format_rar5_bad_tables.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)); + + /* The file header is valid; the bad data is in the compressed block. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + + /* Reading must fail because the meta-table is over-subscribed. */ + assertEqualIntA(a, ARCHIVE_FAILED, + archive_read_data_block(a, &buf, &size, &offset)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_free(a)); +} diff --git a/contrib/libarchive/libarchive/test/test_read_format_rar5_bad_tables.rar.uu b/contrib/libarchive/libarchive/test/test_read_format_rar5_bad_tables.rar.uu new file mode 100644 index 0000000000..eca915f753 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_rar5_bad_tables.rar.uu @@ -0,0 +1,8 @@ +begin 644 test_read_format_rar5_bad_tables.rar +M4F%R(1H'`0#%&C,R`P$``(C&P1@9`@*$`0!``(`$`0YB861?=&%B;&5S+G1X +M=,@2@``1$1$1$1$1$1$1```````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````````#GY +%LH$"!0`` +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_format_rar5_block_hdr_fail_loop.c b/contrib/libarchive/libarchive/test/test_read_format_rar5_block_hdr_fail_loop.c new file mode 100644 index 0000000000..e447a2a8bc --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_rar5_block_hdr_fail_loop.c @@ -0,0 +1,37 @@ +#include "test.h" + +/* + * Regression test for infinite loop when parse_block_header() returns + * ARCHIVE_FAILED inside do_uncompress_file()'s while(1) loop. + * + * The loop only exited on ARCHIVE_EOF or ARCHIVE_FATAL. After converting + * per-entry block header errors from ARCHIVE_FATAL to ARCHIVE_FAILED, a + * malformed block header caused the loop to spin forever. + * + * Fuzzer-generated reproducer (37 bytes). + */ +DEFINE_TEST(test_read_format_rar5_block_hdr_fail_loop) +{ + /* RAR5 archive with a malformed compressed block header */ + static const uint8_t data[] = { + 0x52,0x61,0x72,0x21,0x1a,0x07,0x01,0x00, + 0x86,0x7e,0xfa,0xe7,0x03,0x02,0x56,0x20, + 0x00,0x20,0x15,0xae,0x21,0x00,0x01,0x08, + 0x00,0x00,0x01,0x00,0x00,0x15,0x00,0xbe, + 0xc0,0x80,0x00,0xff,0xf4 + }; + + struct archive *a = archive_read_new(); + assert(a != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_rar5(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, + data, sizeof(data))); + + struct archive_entry *ae; + char buf[4096]; + while (archive_read_next_header(a, &ae) == ARCHIVE_OK) + while (archive_read_data(a, buf, sizeof(buf)) > 0) + ; + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/contrib/libarchive/libarchive/test/test_read_format_rar5_bytes_remaining_underflow.rar.uu b/contrib/libarchive/libarchive/test/test_read_format_rar5_bytes_remaining_underflow.rar.uu new file mode 100644 index 0000000000..2ea589d338 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_rar5_bytes_remaining_underflow.rar.uu @@ -0,0 +1,5 @@ +begin 644 test_read_format_rar5_bytes_remaining_underflow.rar +M4F%R(1H' 0!3*C1% P$ =ANJWT1 A(! H @ $!!W!O8RYT>'1 '@0Y^;*! +# @4 + +end diff --git a/contrib/libarchive/libarchive/test/test_read_format_rar5_main_block_extra_bytes.rar.uu b/contrib/libarchive/libarchive/test/test_read_format_rar5_main_block_extra_bytes.rar.uu new file mode 100644 index 0000000000..81533e4fd6 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_rar5_main_block_extra_bytes.rar.uu @@ -0,0 +1,6 @@ +begin 644 test_read_format_rar5_main_block_extra_bytes.rar +M4F%R(1H' 0 $ .>F$@$%!@ % 0& @ #@P!F,L @,+G0 $G0"D +M@P*T0Z"5@ !#FAE;&QO=V]R;&0N='AT"@,3?@ZK6U;I#AIH96QL;R!L:6)A +;W0@`"L`-P````0````#'-]$(0`````= +M,0L`I($``'!O8U]B-S8N='AT`$```````````&V?]4_(#3#0``B.IW.YK)_P +C`````````````````````````)5`M\R`2$`0``2P>P``!P`` +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_format_tar_acl_oob_read.c b/contrib/libarchive/libarchive/test/test_read_format_tar_acl_oob_read.c new file mode 100644 index 0000000000..13c2bb78b0 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_tar_acl_oob_read.c @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 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" + +/* + * Regression test: a crafted TAR file with malformed PAX ACL attributes + * triggered an out-of-bounds read in next_field() when the remaining + * length was zero. + */ +DEFINE_TEST(test_read_format_tar_acl_oob_read) +{ + const char *refname = "test_read_format_tar_acl_oob_read.tar"; + struct archive *a; + struct archive_entry *ae; + + extract_reference_file(refname); + + 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)); + + /* Read all headers; must not crash on ACL parsing. */ + while (archive_read_next_header(a, &ae) == ARCHIVE_OK) { + /* Just iterate through entries. */ + } + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/contrib/libarchive/libarchive/test/test_read_format_tar_acl_oob_read.tar.uu b/contrib/libarchive/libarchive/test/test_read_format_tar_acl_oob_read.tar.uu new file mode 100644 index 0000000000..bbf9511aa8 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_tar_acl_oob_read.tar.uu @@ -0,0 +1,129 @@ +begin 644 test_read_format_tar_acl_oob_read.tar +M4&%X2&5A9&5R+V9I;&4````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!U``````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````!U#HZ9&5N>3HW."QG3HW."QE=F5R>6]N94`Z`````````````````````````!N```` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!U&%R(0`<``$````````!'`````````(E`````7BND-P4*L8HRPB4*_OO;RJ"I5\65G9V`CA.NV-6`%XW1#R!KY[8MSBL"7H'L- +M]%K9`Y&-&WLK,U2N%:C1+IPB1M8N(PBOY10ADG+0#8@HR5C*7CE=78PT<),\1+);1=TNZB8]CYMJ +MQ4C7_^PV?BO2_-.M85^JF^B)3/W*JB>RZC@1]6ORAZ9X:4[Q[C\>T9S6NQCE +E6U?LW?LN'2[LH:]/A`0)%$!XG'U1RVZ#,!"\YRLL[M2&`*7(.``` +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip.c b/contrib/libarchive/libarchive/test/test_read_format_zip.c index 90d00474ba..2c18387bd4 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip.c @@ -305,7 +305,7 @@ verify_extract_length_at_end(struct archive *a, int seek_checks) } assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } static void @@ -368,7 +368,7 @@ test_symlink(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } @@ -398,7 +398,7 @@ DEFINE_TEST(test_read_format_zip_ppmd_one_file) assertEqualIntA(a, 0, extract_one(a, ae, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_ppmd_one_file_blockread) @@ -418,7 +418,7 @@ DEFINE_TEST(test_read_format_zip_ppmd_one_file_blockread) assertEqualIntA(a, 0, extract_one_using_blocks(a, 13, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_ppmd_multi) @@ -450,7 +450,7 @@ DEFINE_TEST(test_read_format_zip_ppmd_multi) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_ppmd_multi_blockread) @@ -482,7 +482,7 @@ DEFINE_TEST(test_read_format_zip_ppmd_multi_blockread) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_lzma_one_file) @@ -507,7 +507,7 @@ DEFINE_TEST(test_read_format_zip_lzma_one_file) assertEqualIntA(a, 0, extract_one(a, ae, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_lzma_one_file_blockread) @@ -532,7 +532,7 @@ DEFINE_TEST(test_read_format_zip_lzma_one_file_blockread) assertEqualIntA(a, 0, extract_one_using_blocks(a, 13, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_lzma_multi) @@ -569,7 +569,7 @@ DEFINE_TEST(test_read_format_zip_lzma_multi) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_lzma_multi_blockread) @@ -606,7 +606,7 @@ DEFINE_TEST(test_read_format_zip_lzma_multi_blockread) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -619,7 +619,7 @@ DEFINE_TEST(test_read_format_zip_bzip2_one_file) assert((a = archive_read_new()) != NULL); if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { skipping("bzip2 is not fully supported on this platform"); - archive_read_close(a); + archive_read_free(a); return; } extract_reference_file(refname); @@ -632,7 +632,7 @@ DEFINE_TEST(test_read_format_zip_bzip2_one_file) assertEqualIntA(a, 0, extract_one(a, ae, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_bzip2_one_file_blockread) @@ -644,7 +644,7 @@ DEFINE_TEST(test_read_format_zip_bzip2_one_file_blockread) assert((a = archive_read_new()) != NULL); if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { skipping("bzip2 is not fully supported on this platform"); - archive_read_close(a); + archive_read_free(a); return; } extract_reference_file(refname); @@ -657,7 +657,7 @@ DEFINE_TEST(test_read_format_zip_bzip2_one_file_blockread) assertEqualIntA(a, 0, extract_one_using_blocks(a, 13, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_bzip2_multi) @@ -669,7 +669,7 @@ DEFINE_TEST(test_read_format_zip_bzip2_multi) assert((a = archive_read_new()) != NULL); if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { skipping("bzip2 is not fully supported on this platform"); - archive_read_close(a); + archive_read_free(a); return; } extract_reference_file(refname); @@ -694,7 +694,7 @@ DEFINE_TEST(test_read_format_zip_bzip2_multi) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_bzip2_multi_blockread) @@ -706,7 +706,7 @@ DEFINE_TEST(test_read_format_zip_bzip2_multi_blockread) assert((a = archive_read_new()) != NULL); if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { skipping("bzip2 is not fully supported on this platform"); - archive_read_close(a); + archive_read_free(a); return; } extract_reference_file(refname); @@ -731,7 +731,7 @@ DEFINE_TEST(test_read_format_zip_bzip2_multi_blockread) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_zstd_one_file) @@ -757,7 +757,7 @@ DEFINE_TEST(test_read_format_zip_zstd_one_file) assertEqualIntA(a, 0, extract_one(a, ae, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_zstd_one_file_blockread) @@ -783,7 +783,7 @@ DEFINE_TEST(test_read_format_zip_zstd_one_file_blockread) assertEqualIntA(a, 0, extract_one_using_blocks(a, 13, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_zstd_multi) @@ -821,7 +821,7 @@ DEFINE_TEST(test_read_format_zip_zstd_multi) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_zstd_multi_blockread) @@ -859,7 +859,7 @@ DEFINE_TEST(test_read_format_zip_zstd_multi_blockread) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_xz_multi) @@ -896,7 +896,7 @@ DEFINE_TEST(test_read_format_zip_xz_multi) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_xz_multi_blockread) @@ -933,7 +933,7 @@ DEFINE_TEST(test_read_format_zip_xz_multi_blockread) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_ppmd8_crash_1) @@ -955,7 +955,7 @@ DEFINE_TEST(test_read_format_zip_ppmd8_crash_1) * proper fix, the unpacker was entering an unlimited loop. */ assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buf, 1)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_bz2_hang_on_invalid) @@ -968,7 +968,7 @@ DEFINE_TEST(test_read_format_zip_bz2_hang_on_invalid) assert((a = archive_read_new()) != NULL); if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { skipping("bzip2 is not fully supported on this platform"); - archive_read_close(a); + archive_read_free(a); return; } extract_reference_file(refname); @@ -981,7 +981,7 @@ DEFINE_TEST(test_read_format_zip_bz2_hang_on_invalid) * But it shouldn't crash. */ assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buf, 64)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_ppmd8_crash_2) @@ -1002,7 +1002,7 @@ DEFINE_TEST(test_read_format_zip_ppmd8_crash_2) * But it shouldn't crash. */ assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buf, 64)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_lzma_alone_leak) @@ -1037,7 +1037,7 @@ DEFINE_TEST(test_read_format_zip_lzma_alone_leak) assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buf, sizeof(buf))); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* This testcase shouldn't produce any memory leaks. When running test * suite under Valgrind or ASan, the test runner won't return with @@ -1066,7 +1066,7 @@ DEFINE_TEST(test_read_format_zip_lzma_stream_end) assertEqualIntA(a, 0, extract_one(a, ae, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_lzma_stream_end_blockread) @@ -1091,7 +1091,7 @@ DEFINE_TEST(test_read_format_zip_lzma_stream_end_blockread) assertEqualIntA(a, 0, extract_one_using_blocks(a, 13, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_7z_lzma) @@ -1123,7 +1123,7 @@ DEFINE_TEST(test_read_format_zip_7z_lzma) "/src/abc_measurement_analysis_sample.py", archive_entry_symlink(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_7z_deflate) @@ -1169,5 +1169,5 @@ DEFINE_TEST(test_read_format_zip_7z_deflate) } assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_7075_utf8_paths.c b/contrib/libarchive/libarchive/test/test_read_format_zip_7075_utf8_paths.c index fefcc82881..66650030e4 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip_7075_utf8_paths.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_7075_utf8_paths.c @@ -86,7 +86,7 @@ DEFINE_TEST(test_read_format_zip_utf8_paths) assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); verify(a); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* Verify with streaming reader. */ p = slurpfile(&s, "%s", refname); diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_comment_stored.c b/contrib/libarchive/libarchive/test/test_read_format_zip_comment_stored.c index 39f83a8210..feab4b5ee2 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip_comment_stored.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_comment_stored.c @@ -61,7 +61,7 @@ verify(const char *refname) assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); assertEqualInt(archive_entry_is_encrypted(ae), 0); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_encryption_data.c b/contrib/libarchive/libarchive/test/test_read_format_zip_encryption_data.c index 4a6502b9bf..2a94b2cd3d 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip_encryption_data.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_encryption_data.c @@ -72,7 +72,7 @@ DEFINE_TEST(test_read_format_zip_encryption_data) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_encryption_header.c b/contrib/libarchive/libarchive/test/test_read_format_zip_encryption_header.c index fb19c14219..6c190c435d 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip_encryption_header.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_encryption_header.c @@ -65,6 +65,6 @@ DEFINE_TEST(test_read_format_zip_encryption_header) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_encryption_partially.c b/contrib/libarchive/libarchive/test/test_read_format_zip_encryption_partially.c index cd5d2103ea..70241aed17 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip_encryption_partially.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_encryption_partially.c @@ -73,6 +73,6 @@ DEFINE_TEST(test_read_format_zip_encryption_partially) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_filename.c b/contrib/libarchive/libarchive/test/test_read_format_zip_filename.c index b673344738..21702d2f62 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip_filename.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_filename.c @@ -81,7 +81,7 @@ DEFINE_TEST(test_read_format_zip_filename_CP932_eucJP) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -159,7 +159,7 @@ DEFINE_TEST(test_read_format_zip_filename_CP932_UTF8) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -234,7 +234,7 @@ DEFINE_TEST(test_read_format_zip_filename_UTF8_eucJP) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -329,7 +329,7 @@ DEFINE_TEST(test_read_format_zip_filename_UTF8_UTF8) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -385,7 +385,7 @@ DEFINE_TEST(test_read_format_zip_filename_CP866_KOI8R) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -441,7 +441,7 @@ DEFINE_TEST(test_read_format_zip_filename_CP866_UTF8) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -498,7 +498,7 @@ DEFINE_TEST(test_read_format_zip_filename_KOI8R_CP866) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -554,7 +554,7 @@ DEFINE_TEST(test_read_format_zip_filename_KOI8R_UTF8) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -616,7 +616,7 @@ DEFINE_TEST(test_read_format_zip_filename_UTF8_KOI8R) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -681,7 +681,7 @@ DEFINE_TEST(test_read_format_zip_filename_UTF8_CP866) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -734,7 +734,7 @@ DEFINE_TEST(test_read_format_zip_filename_UTF8_UTF8_ru) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -792,7 +792,7 @@ DEFINE_TEST(test_read_format_zip_filename_CP932_CP932) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -869,7 +869,7 @@ DEFINE_TEST(test_read_format_zip_filename_UTF8_CP932) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -926,7 +926,7 @@ DEFINE_TEST(test_read_format_zip_filename_CP866_CP1251) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -983,7 +983,7 @@ DEFINE_TEST(test_read_format_zip_filename_CP866_CP1251_win) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -1039,7 +1039,7 @@ DEFINE_TEST(test_read_format_zip_filename_KOI8R_CP1251) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -1103,7 +1103,7 @@ DEFINE_TEST(test_read_format_zip_filename_UTF8_CP1251) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -1173,7 +1173,7 @@ DEFINE_TEST(test_read_format_zip_filename_KOI8R_UTF8_2) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); next_test: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); @@ -1223,7 +1223,7 @@ DEFINE_TEST(test_read_format_zip_filename_KOI8R_UTF8_2) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); #endif } diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_jar.c b/contrib/libarchive/libarchive/test/test_read_format_zip_jar.c index 75ea3eb9b8..0b18e3175a 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip_jar.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_jar.c @@ -53,6 +53,6 @@ DEFINE_TEST(test_read_format_zip_jar) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_mac_metadata.c b/contrib/libarchive/libarchive/test/test_read_format_zip_mac_metadata.c index 9f7c35e1df..dea5df9c64 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip_mac_metadata.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_mac_metadata.c @@ -110,7 +110,7 @@ DEFINE_TEST(test_read_format_zip_mac_metadata) } assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_malformed.c b/contrib/libarchive/libarchive/test/test_read_format_zip_malformed.c index 7e46abd8a4..4f3b0e182a 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip_malformed.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_malformed.c @@ -42,7 +42,7 @@ test_malformed1(void) assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* Verify with streaming reader. */ p = slurpfile(&s, "%s", refname); @@ -51,7 +51,7 @@ test_malformed1(void) assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 31)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_nested.c b/contrib/libarchive/libarchive/test/test_read_format_zip_nested.c index b32e4bb942..73222f9e60 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip_nested.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_nested.c @@ -62,7 +62,7 @@ DEFINE_TEST(test_read_format_zip_nested) /* Close outer Zip */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); @@ -80,7 +80,7 @@ DEFINE_TEST(test_read_format_zip_nested) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(inner); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_nofiletype.c b/contrib/libarchive/libarchive/test/test_read_format_zip_nofiletype.c index d2798b2831..04728d25ef 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip_nofiletype.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_nofiletype.c @@ -60,6 +60,6 @@ DEFINE_TEST(test_read_format_zip_nofiletype) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_padded.c b/contrib/libarchive/libarchive/test/test_read_format_zip_padded.c index dcbf3406e8..af996a7314 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip_padded.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_padded.c @@ -51,7 +51,7 @@ verify_padded_archive(const char *refname) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_sfx.c b/contrib/libarchive/libarchive/test/test_read_format_zip_sfx.c index dad0a270d7..7b672fe079 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip_sfx.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_sfx.c @@ -58,7 +58,7 @@ DEFINE_TEST(test_read_format_zip_sfx) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_traditional_encryption_data.c b/contrib/libarchive/libarchive/test/test_read_format_zip_traditional_encryption_data.c index 0cf2d0a157..423197032f 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip_traditional_encryption_data.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_traditional_encryption_data.c @@ -92,7 +92,7 @@ DEFINE_TEST(test_read_format_zip_traditional_encryption_data) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); @@ -161,7 +161,7 @@ DEFINE_TEST(test_read_format_zip_traditional_encryption_data) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes.c b/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes.c index 9b609b4f29..064244395a 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes.c @@ -78,7 +78,7 @@ test_winzip_aes(const char *refname, int need_libz) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); @@ -128,7 +128,7 @@ test_winzip_aes(const char *refname, int need_libz) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes256_large_bzip2.zip.uu b/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes256_large_bzip2.zip.uu new file mode 100644 index 0000000000..f7f3cedb7b --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes256_large_bzip2.zip.uu @@ -0,0 +1,1616 @@ +begin 644 test_read_format_zip_winzip_aes256_large_bzip2.zip +M4$L#!#,``0!C`/BN(T4`````A]0``&LZ%@`(``L`36%K969I;&4!F0<``@!! +M10,,`':3MFR@Z]K3DUA%-ZAA0_^+)`=$&R=!5HZ/@!8[87=`V;"!#=6&?I64.;Y5PIANF#>Z6QD],#@+_>R:,H +M:0N3:0@(8?"!H8,5NZ(WC\+@_*&N<,;?0[[\N%J3,9TCSKNJ4!(M:[92ZJ;N +M+Z1%@4@YNB.[>Y'YW+)G_A3/S[213^U4>QL;)S>DA^"HXI;Y7"T=0583XP(S +M7$/9>(*U)O2&!`^YF,)NGJZ`>#WR&"7OMI+LEUS +M?#]SL8I*WTDE9+-,>^8O#0/'=O[?^ZT;C!=LH"K".&OZ@.HEBKP'-0_Z<(UG +M@V2[R7VXTLS0H5+SN.`YK9I\ME:LGA?VQ[>`!8%?&))P`]S;"'HM9E"Q/O#P +MVU0\,`CM$\U`)*-MW=I+,>_S.N+GG5R'?"R"Q,ID$4]1GL*V1.[.V#`6D\\6 +MIEIGQO3.76/'MJG@QQ,W.]H1XP\T6&-RM02FFRI?_\N\_G\P];2VT@3!&=%\ +M,.DL:W*'`50!67KRMR)BRSJ(Y3RU/@\Y^DV1WL4-)Y?M8P)J(D&(@^ +M`9XR%/9E[LR3J%.LM*(E`!PA_^DA7&V5`[`V"-MOZ,1,MN@6B9Z3RB&F4(SW +M3O;^-'[B'(8[^QA_@^OJA-Y>@<_C0;CCKO=Q +MX.2MQQ()4O66^K:7)(&M'=,T4O#3^9][`9XA"T7JOUJ^0:TC;3N71H:U+->J +ME%8*Y]?G!MPO>T(R56B4(9_)$AZ*M:=!W^,(8PT<>F_+[M&CR)4RW^B\>9BV +MP?"3SH2'%))D#:3Y[,6\'$6T6I^:[D+!HXCI<:$[WC&S(JD@2M('O1S>ZZB6 +MZ($P-071RDT*:@K(V[;/H-@4[_\SH!:^-EK-/*N8%'._@")>VWQ6]A._#Y>3 +M]RP8DAA>YZR[<(+NPESZFDY71+?:QN'&[NN1^XY@+R&XWE(I40)%X#XL!9@- +M['Q@7=ZY@6)@M7GBQOF%M-W3*/L4.A^_S`=C2P')IVT/P;.M^W\$B0P7E#1` +MLU)S$,EMG<04"43BQI)P)!$ZW\,<(U)RGMOC-6U*=+3*HB:!DSH(5W`BL(!Y +M`<)8%9E3$^/)ZXP&#^?L9T16%[:OT@&SA4YF[#QPT2(C@NI;G-.K0];OI(?WK@=HS*=FBCES]Z%GP/C15 +M>_-YH+VIW"DP;CV+_'7`P=+6*U)P^]5+WJ9JQ(!DQ#1%O?('#MCJE]BS1L'C +M)Y&T'H]>\KTU.\*YL'M#XX>(,TM='%\IUV1(PK_1QF"!C;)F\4,1(GBSGR3^ +M(#Z8#4_)MY(1*JYV"@[]8IYEYM#ZR`IB +M6KF]D!-8?`Q$.^]`.]0Y#@YE!5-WZU#O7JU`@+[$,/_A*89 +M>K)9%+_,]"9"IJA*)KJY&$Z^7XQY(H'[>N)B>DMV52_/YC'L^KTHA]AUX-VU +MQ_[']ZVL$%=DBG_:[QXNO[(:1\5Y3R@6Q%PI#N,25?L'[E3.:65/%9W2`&H` +MV>B3.IC#BYGF1K,_ZVXY>S20:W!]`AR=W]NU[4MG?V4.CDQ-F=<<(,>I<>V1 +MA%)_`ZXI=!J?CM[GT%D`6.%LEHR&!QV;"@E_)DX5$.,/0#D'D%DFF@T\O?Y> +M@R2F$VH)&>3\+=RLP]+P45V;BTO+CKN1SI0M3B&TK;F/AN@:_*X9:F)'Z<9W +M-#[BY)KJ-GXDD*I_H\LM"!/4W<<3-@8S/).7',;+!5OT>GDR%W<9K"/HTV.Z&7$_VHHO'X'VBVQ^]'[3N,!0JNUX^:NWZDFY +MB2$%\ILORV#UL*`UB-)K932CO"0RO\/\E8Y1(UK>A`=ZW2NSRK,D#'RSYLPE +ME\,7E^HHE^Q<3\H?Z@@0[+1'LM0"$>1_W/%AGT@6IN=CCTGBUV*7L82U9N+, +M=J>N#Y\Q_O<*!:X"D!(`_IO0"$PN-*F`J!"2L!8 +M[9W4FC5C]VQ]AXL\A3NA\#4K#;F#X'5F86$I+U.O=/:50NEQ1LNK8#_G5=X) +M\U*0]4EBG2E_\`S+GQUGMJL7UCK;0`Y;((D:NAP)*S;BP(S@.91]PREZ&8J1 +M:A0Y(*HBQY73L8SKB=L4GR;5[Q:-) +M'88!SRCH'@QZTM$"]$ZBX1AB3I9F3R#()8:I)(MUDGQ&QFL4S'J])[,.9"B% +MGA%4=PK735<>%VLYO5(S4'05">JU07+F9!=/X]_/Y +M#1S].KLZXE9[?&<['#IGWA_0R1E@+VMASTJP1_^M-9KV12E,(+'G9P$,_;^@ +MD`[>J2LT(HNWN'72WM=*M9,7F%2HDO%;,%FWQ2Y,(%PU=+<:N[Z +M#>X!WG/]&6%,K'VF3#V@(;S>QPQ;A9\EJ=`BP.>4>1"RN\\IZQ4$ME),.RM_ +M")"76&'@.BXR_/@-D.#;X=@\Z%P<\-"=M0T75QW'T>\#)0&S;@HONG.8X]^3 +M=(!*R%-7!>&:/RI==UZ9]7D9K[*E$E,PV1*GJ0FF=A["XKLG)5 +M8?:<^]1A?^>E"MIP^;WY:W^#)I*(@<-C`"@]P^2W[$97#KFT::.8E#14Q#WM +M.FS5?8@QQ@9H\.2LH$QYA/<0)S4!W:F?#Z0;[)2?1P,Y@9U("&J$M[?2GW\X +M;[K!Q+FELD437Y._`R=BS-8K!N2;.`R))`?-FDZ'3AS?Y/2*=F!BWUF^`X3- +M1P3#908PCJJ,Y!=QZL@UQ@Q*G3M0`;.(^^^`'T5HCN9QM\F%?VV;#B=;-/.' +M-T#+6`:*@[U>L:[5/M-S$O#5QGF:*B-C->/,M2WPQJ_BQ2:_@H\[-@8^0K/UKHWD6I8#U_;CW8.#CHH[MM[:$0;Y1 +MQ%*#;WCT4COOJ3`:DUEE)CK+WW8[,I*G0[*7#%%C<6]![:+V_:S"WW%=AT_N +M.XNP8$+Y-9/S?/3V*$M[$K4H!%F915$J]`WE^OGF1?-[ZC" +MO-JK`80-E$6F.&_I=KZY[CXU%[^\:V\P8,B^!K"MK\LI>&M)*]Z^([*G8.S" +M(S13FCP<%.';8T??Y"RX_N^3W;N+1I(5@^>:9D\,A?(7$[G\\"]XTXDZD+RE +MWZCJ$Q7..KO9AY"0*SU>-E:/]TZRN+_G=O*FBM6>3G'+Z37\6-E7KB9%VZZ' +MFZMA):1@*C5D/US6,`,L\'098G@*)-)%%3=9@.9O:Z*9""*DP93J9^A3O[S` +MAK#B5(F*865TS@,S30!:^+Z6R3R_>KS-!,R%22?6O2L2T5[DO@G6;E#QB5>C +MNA(4#*[9!X"0L^M,Q^^7K+VE'`2 +MF-(PPV)H58+TD)U)`V2QNSGLHQ?OBB4#LX?!*>1-G=]?..?<&UJVB8 +M70,=2QA'K:__LM/-2[B%VD`/PL/M>")GD17*`BQR+:#60Y1;>_D7"O+E[\O0N?#S2Q/8&6&SD(_QR24.KL +M&Y?1[F&DP`C,AM=M:PDYM_`#_,-SD7C8W7H"DE!BG]F%DS2[\H$/S]/G=&!F +M+D[`&(9&N^!@HIQBY6=.''YC?0*?Y8?8<*+_H^'0;UL174A<\"\=*DIK][@V +M>_ELS=`+DU=MWR?Z'+F>F-1<[(S9Z.-&6;/D$-`&-I"^SI>+P:0QQ+:8[O;; +ME2LB;L,3'Q+6@"\S:F/;#_=E?ZV:KM`NQ!!6VH-N6PK>AI'6:]G)\Y@CF8L( +M?*2*84XE[3N["]:H&)<4BR>$"->5>Y5A56P/Y_)\QT=WWZ^`P>XK\![E"*4/ +M.:=[JT,I:W]A/@@=1@E_E(8LY$*N%'4+:`#&TS5Z#$>,(5M;2TTR^2WQ,%@5 +M;53)-%G7F/+?O4J:0[X10UR^'_!@ARTB]2&!"Z5,8A4#[42FZ\CW?_5=N,P. +M,@YQ3V_&UY)M`VOEV:W'4,1C#/N63J(Q4:XKM"68HR]9'^3;:`L1M3:ID49% +M-&E(L:DNS!QG"19C_TJA7CPGI"ZWK6!:OD=EV-:Q',AM4ADJ90-X^O:+OOEI +M@_#QQRNPO#<7;SX7N^%$EDDM+:ZA7ESC!#KN7F@EWWW1QCLUA9%S'?,S5H,K +MF$-+'(?L/!:%X44#"BL%S=`&.=]/4N%8XBQD +M"SSV#Y#/-"O]M@8#II^JYI_-#E$$"_!N+4QH6B*I@[8KV(ABUF#!UIU3N2+7 +M5%0194!(QB6DK!`W"@Z+D!AD7\TV;!CVY+;@YKU\BQ;.S+_XBON5#%6D:/&, +M%Z!@@JE+(A8^>"BJPE'M1'N__A3\?RXKU%X''S9OTEGHJU@38TK0]6<=BYGV +M8M(H(CL&:8T/H(7;'\R#'P;2Z-6!T]_=-P^5UK]+U?X[N2_+Y1@FBO]+'&CB +M\7S_]-I:#37!N\%+0U!PJ>XM1#G#L-#3X&0<.5B`?8D[5P9-4&Y:303"K<(! +M1+^G\B/=$H1]S7'=E-J#!`@1'V]**KIV:'D0<#!=Y5*'ZNN"/J07,%/GZE/N +MM;H9\;3)3+1V]R83*$LFK9`?O)Z#GP9C1$%Q#7G/`J<"M>GIP9Z;[(BET=I4 +M`GVP90^$8$[Z\!!_D9K_.B?T^_#7,U#94(F3:K_B.=^>]V)'(&B-#I,>EPA2 +MY)2(?]H[QF;;V+O->C\/QK0&3IR1+SZ`-+: +M3A`%&V4.]R.A5&.N_P=TQW*TRVH%]3TR#=Q*;U5DPI:9W\4?@[)MJA>8\`=E +MND[M/Z8BV1.[L!^K]G[Q]X%<_/<[Z=QYK%4+0<>%E@B9MQP8L9+.OUJO]=]P^E +MX9-[@>Y$]1G%P:YI$.]T4_LP/\ZP3Q'G,$Z +M.1"+N)2C#(F%Q3SF&6A8$IU,:>BD!XR9T]LWT6_W)P81YO"QT_&/_CP^_QQ3 +M*(OPXNWL"#0-Z(:1=U)&1G3MJBO&S*+*+=>33U+Q'U$^1F),K+*_7SA8=C03 +M2=58-H?R6>1)Y'H$"^3?:/D.5]>6&DY&;Q?,#,+70[(6%3.Y7#E +MM8JLMU8MP/!G7*VV*HSZLDU:(,8/<<*TCJ^">,ARS +M(WI@LHW29%=3*=GHKUZVD*:ZPZ!J/./:]I#_QKU+GX%87+8%R$DT]C#J/:W04LLNX^ +M$YG4$@L\:82/(TH?KIX`E3Y"4N@P%(YA)B]I0#;ZV^K/TRX(LTW'2I5H-FZZ +M.9*<"<=Z,^F$8K2(0.C8=Q6(D^,V%@H8BX[)"5^&\J^WHB!\D1O%FXWW8H*G$5P0&J]&"K_ +M(@[EL.P6R9#,;W8(R;XF3#N=PK?@NB/C:,G6-30$)68: +MORF/F\+,3X%Q?O)&D`4H3`Q]'<_-(GXQST9,R(-PFTL^-'+5W,WKF&:15%^.5'R%S3K7_'#:[A6]PA]G1T'%6M[(NBWF1H[MLFA+2'2KIWC4TZ_KWG:+S@HFRQ27 +M'`CPRAN"B/8O&OQ#"T1"_DLE +MSAD10[J@,20*N(2&?/9Y?@PN*AD2Q[=4>`2I'@Q0EF6SRQO15, +MHW46@"?]<8#D^O@0OH`_@..X1?)PAH;W6RJ,=NQMBMW!OUCQ=D#7F<=;/.MX +MGL:'2==R*T0MQIO^SF<#*?@!O=%62:/^(I#JDJO>BF&7^'RX7GS+/V&I!=.K^D< +M'/&SPU%;9*?%8,7M.=2O5ZWO?80223=U&RJQ#^Y&"W$'AS1[FC)\&"(P2X=F +MT[)US;8Q\77ZMQ147EC%<0#Y3`%,_LTDWE8(YDM)I0MJZND\OT`G=W6$ZMBT +MFGA$V'23<:C!\B,#,-)]AH3A+#D_G)O->=\V<2Q*8#%1*U%M)@U/6WN=%ZN! +M[>81\K)=A4BP4>V)YB\@!IS&,0XQ/1!_MJ`^]TU.T'(I!WM/Q&A5_H-OF)?A +MEOPN[W +M=Z<+\?15=8F\TW(,HI.NG=5$V<1+[.VQ7WUGK46C6Q$LJ_@'QIL>"CS&:8#' +M9]'3GQM$31NUQ0(4QJ\=G6V&`%N//TG5J85W+I&M>QK"Y00%4,73D@S('UZ=,EXST4/2HG/S`N$?:IBFOZP +M2YHG"K7`N5M[O@B<0\@+`Y20V=V%Y4*C!B +M_STU6`JZ.+UOD7JV1P,120_U?;:UYOUV99/_+Z5H9G3EP#>7;]GZ>A>E#(-" +MU`C#%*[DA=L=B7.I)<&B>^UD2&;]9BT/]8AS3)'OBSH*SF83>JS^4S@ +MZ>R+W&%IMUO&7ODG`F.R^3IY,U+(=Y]XHT?$];.,J6C4@@J!$8DPZ14EX)>RRS&W/5!V=!7FV!LKUL/^2*[[G44?1$A9O>5(VHMBN-3#N +M*@'I/X1Q-C1$Y!QR`7[7'4`BX.O@%F)!_WGTNH8`A#W2O#\_\=^3'PSV,@<0 +MX.DRG_,C^?'BVZ*6WBFL?W'HI^^R:%J5T`4-QZH+PN*MXTI$JA9G.)D>Z0Z+ +M2ARWVGPZF-O+!*9[5I-:#3#MMIQ4Z%N35VR\A.76#N8.F-KRZ@?7:U#-V$[! +M-87`1]D"'_(G"?K#!\O18C;-TY[QX.G_D>ZP^L/`!ZTBV03[9Z\[)OOI9IC6 +M@QI%V'5)#1[^KD>GKS0UFYDT+@:QX`QFG5*_=0ES5?RBC!K;9I[D099$M$X0 +M$;L6+[=LM8!':,>`'I29.Q\GVVS-M,]^:P%MT_;!AJG@PCZR,02E[N/[`^%D +MIS\#W2%.4AG:E0;_.1-?3^JA6XJF,_))\S>OXC`STOFMT6@3TRF)3 +M?/5/<`&VZNU'21_<5AS5N=P7RSL'EDN9!K;>=E:(=CVRZ=SR2GT-4P/^`'1' +MN\3)5G-@O5$8;ME[2S0\_G`/SUG7QY5=NU;GGT#3S(H\$\NPM*D"X(4ZXPS2 +MXN&$Z+D*'7!SF.S!J7GO6A-A#05Y$__'#H36KI1YC]9W`MLGWI2S +M#68V"4!Z\3C70:#"*;>OY.?.49SS'L)QL>W%08'XT'3-WJG+=E><([7\^7'Z +M]20]9+1H;7=!X(`$.R+/HU.3YJ/:`EG\60-/(*7B7ATZE%V4!WN++5D:X<*Q +M?ST^*$:!,6.]1)3SB%LA\!U94D&=1Y"2SP#4J;\@C@#79#A6PIN[I7FBT4`' +MN@#A=X>Z[ML=&6:/_!W-XC.&$Q'DS!YX@J:4="7=A^LJ!, +M;DDQPO9>%OT<'J24L(NC4F?%E][E.NQ+&5ISE'?'I>H'T(NFKZ^CAO`[65U2 +MVUTYRTNRNU!=BK?[VM\&[V@%,N'-7E=MYJM,PV=%#WTR_.#Y%3L>Z2R%7W]G +M16X6_4'1.S*3`)3>[=B@J,K-/'SH^?Y8EN/-0DWP*JB.QD +M);N8_:LB/=6Q#E'8\-P!7;\V%%4ZC>14G_Q>>A6,Z*EH4`?L(2[_=>&A8M&> +M^V7\"!U"!7;VSP-,8XZX]J08'IH;]:F`*-KMJN>U?J:+?X]_USF[V72F7Y\!IF5W&&OYMX06,J7)9$UVC..!/.6$6C9RG(!+5VS&V,(X;5H1D, +M>W&ZS+M_M>RVK?.5\"QB3`Q$=19)&2GCXJJ9FXJPN>WN1HB+!8A0DG(M4_(2 +M`(*BF0B]]A58';K?.,C00S"6L0;TC'0?&E_OQG:'ANJ.9MW@9X@UM/QL?E.1 +M)%!>![/VJLP:)CN!]S$,PC)H"`4-[O)O5?=%LKU54-/[B?\S]XM/`UR:VK:@ +M"=$XMAP`(V;;CM@`\5/G#4W87$LNO.9DLQEO0+:R2H!`7,%J]CN*Z#J+Y>`. +M5J.ZYD%!8"'H'^(`X:N>^RJCN/RI&EW7EU..?-@?PHV-^?[2T$2;N_*V_X&@ +M;AK:,B++.+<;AM*CEE0F:-*KW817/ZE`:P50]>4$JYZCNG>OY^:5;'?,WQ'H +MQ8S]K"2V?YVT?0(MAK^-AROUC/P&-%4`=OK&MBJG>4*>@W7&2/O46)T]6B^V +M^W1X%P-.M-W`4GS<-;459Z&*X5[=.I(,TGI/;?1B?@P0VQ'11MN#_BG[P;") +M%=GM*TWA-5,NSN=7A/^6P^7TW1C\;;-G>)I]7^3TS,6)]\O?@)-W&3A3F +MOL"Z[7PL$,:^U"V0Y9]U6ES)4$GSU?,[R,-C;H%QSRNZ5!SP;7Y"AZR>G2[1 +M2P8(UQ2V"8^9.]<5$>G11"8E(G,>L+2)JO5A>EYK`_`5R'B$&[)Z-RD7Z>J: +MSC0?S`F\V59ICW1'FZJ#[8T_#*GG%[>#.XLDA.$%II-@,9?>S.!15!?7F]:^ +MQHKJ&*W_F*S+HA/*#J7-`"F@N]?[@B>I&V?E(JO??B7WTU*.,FT]UZW6J-0* +M"`QIFBGS;++0O[G"-/HMBP%LFL?>ZPBQZ%)_:S^T"$E$/P^![:`ICT42$;FK +M]&HN\[<6J"QSJ#J6&W/RKV:SB2":W5?B%).1U[S/H6?)=S"X7`V'%V.,I"!;EA;-NKG#L_FFR(84E\>$JIQGF?EA5 +M#&K*VUEKCWIWF!SLK;),[!L3\XUI'3@XA7-H.%H0T?7.CS$@E0PZ(`&]DKGI]X\W5V\0\F/,8%EN +M-[:4_=``BY_RZ4<9;8`3`(0B;[*,K?R-V7L74U=E95'7 +M_4[L`98.M3>?JL-C(B%(.>P:N$3#9`$`S7U!M26NHLX*\!&X<@-WPP'6%($R +MZ8SYPXJY;)SI1Z#& +M1H/-U*8EP"/FY:E^`^]_Z*G>1`WY*Q7[A#5.&0!NB4>WT&CS_FH.MK`/C"-![E(DNSUJERU;Y<>/Q">X1@5"U2TM1-8HS*(+Y8>'P0N"VA9*I<`UZU9%#-VGIHT$))#^D#`4,#')Q7_$@` +M"C2]DB6(DP]<&B/GXM(R_CQQAM=!-;)V.?T@7+D[27;NUQIR+,WW4#^*XD#L +M^YDD?%5!FYGD^&D!>B.RY=!R>2_U?[QE%EZ%-Q+0ET\WV@?Q:X$8\IMTU>[H +MO75@(,'6&)?L(" +MK5287(#EQM.IGY[\DK/&&]P-%-L&!$!_(W>FRJ_XX"KL@/E%8%MRMD9Z*J +M6`50LIYF^[UOF8`/FP_K(^*25( +MD3?_]JBL>17<$__A]G?);TT38I,O6U:5LGG6!-*`%ML3&*06%!F-::F8&J6T +MK:-16C%7ZQX&N008$6N.CV-3^CC)+YC\$9H!LH9*:0_WL@L +MN5C2T0W2"^%OC7;=D;$98[G1/=15IA-ONG8?H?^PD@CKY1+C:,. +MET=^P;?`%6+5^P2PV9,V> +MOM5*Z`Z>I<1D*=[$1W&T:\6TZ@8F<%+V.H?D7;M)XQV9Q1%$?),#^#Z'@KSU +MJ;[XE#3#&`L;W-(S5'=3$]-BM,D.NDL2;4JL;=&*:!SPK2BB*,=HAAABCW/8 +M;&!LMI\ETDC=GY&`I2OW9`O]?!G;4!\*#W(1LMY&XQE5DB\8?/D/,%7:F4[W +M02VG844X%#\;:G`&PJ#K1I*ZEQ3,Z8'2?1-TME=V:9'76#%TNC9OLD;.ADM(&-@:`,%/YUN3I&_:@#<;61O53$" +M%Z>YDFT3&JV157BO=JPJUXI8;0Y:/^5^*E,,1YK@T]]Y1E6L`3:Q6-<-[VA+ +MQKD/WM3I?+H<#PP^?7L"T2#WXO6`I`/.BY2^\OPJ7YQ&2TBK^7VP$#BZ+V8^ +MKZ[V/,6T"R?,?06V1+\,MJYQ@B>-.3D":3->PM[A3?GW7V<_3>M_DM;2"G53C +MBB/4?52[*Q^7?1)?`>MS,4\2A185?%7#D27$$+`K2V'Y@[\#Y:,3ZA"'_B!9 +M*N');/[*3!*#MKX=VK_%PZW+.LCI:YPK+Q2@6OHKBCJ?!O9*2CYT&5RE;7ZP +M=H-&-L?#,ATOJ@,:RKR3@'6YJP3WU_:TMBF-\YM`?CJN]S*8Z&XHB4 +MWO;EK5S0-H+M0A>IWT$G+@F/QJ[9W*[=2*2G"A1<%E&S%M`GELZ`-`G+A*;7 +M/G&VVT_P6?OQJW^)`V;-K,CE&<5:O9FST!>N/'W?A%$;.,JJJ``&$ZWV2!0Q +M[^7`58JC'5Z+R8^0ZO0`7?V%7S+-4T(,N\5.87ZQ]9&>%O2DA<%7@%'OQWOS +M^>M+4N#"(18L1@@X4[D6MO`KB:,`P^AKL-JW;R\OPZ\@H:,4@A6%3%GJOL,FI:&%J"80`>2HX#,II* +MG!V1ZG``Z1`#D?ONX.=P/W*;PY-9E>OX^"\[)[(RZGSS]%68E`7[8`9 +MEWWCL=CO4[2&'71MH+@$(9?"M144)^LTG$8-B`:Y#L55< +MC>N3)E1ZN1M8>J6["ZX4[F%&=&AKR4QVR$6$SU3YS!]S*[(98Z(VLH7G0ON, +M.&STB2U-J5@)`=QM]_!Y'R>:`0/*8=_)4R[/C2U4[ +MI2&)4[R$].*ESBX_OJ:]!7\U<1VL8P5M'H=9^3*$ZNEO,TK>9V.,=6$1J.!* +M9"`%9GV2;=Y)8VH!Z.B%4(ROR)^P#C<2I]27L9B-*;"C1& +M5]Q@&@#4;OV3*5L=E:6@=BG'EB`+LI&[5[=D`U/W8-O=LF_[.\35_\M$-%N]-2H.H5"YUX +M0LZ2L%34#B='"LO)I__3XF_\;U3&"!>?"\BOW8A*8)A/L +M^MS-P!F;!D88QF%M[K5SB/0B.$*-2:7;?&MAM:(8HCX\?4=XN+5Z,>A3#91+ +M+J`"I*S23'H?*)=[(/4%LB+^&4]C\"[`Z`A#4V48;R1!\*(.WJ_>9T9[XV2Q +MN*/9*$X="7L)-3BMV:"SZ"UBI025GS]$A.QDF1;7]H"U64!@ADF\/,GI)>A/ +M01O9?UHQCT$1JR,6U8(R\)N=$Y*#2[LC_M4QN5195AQ?&-K"2`8GX`$B^_`% +M]C^6K_;2[TI51JI'AJ]7?<1ORGP]L1>8L3_&^WI=;\5&`71\'`G`/ZRWO5,S +M^MM$Z.ZQ`[^:,P2-FB*#?^9UB:=&H=Q[U4CC'Q8DD,R7WRX0%Z0+FAS=WT3B +MHJ,2;"]J8KT$H>,F'J-IB_R!U4/,-+ZIIFV?'*(@TD?,W0727I1H\#2]/L8C&30XGVR=(H$I4YCGP`3G5@&\^T8B+EJ3,\Y/2C' +M4SF^G8FGAN\ +MF?SA'U^,"LS*P9:9#G\&26#3]!5E/C]>=6%/\];H]ODV<2%=; +MR\+,)%O`JYH'AF$1'!>P^IA"+TGK@'H&%WQ:((GNF)^O5BF7>8$=%>\)\;JD +MZ*%[UD.K3,:2ABI+'39,LJXTF&`HKM#WL&.*^>E`>'*CK\.K`'<&=FPHDA$7 +M$,MBI5BR.PJ)<[,AG9G]Q.H>/&CL.RUR@^?XFA*I&!4SD\/ZLL'!@"L#?@FC +MJK?33H]ZV)KC/(4!&.A'_#9-^YV2G3[2S?16DL.*W_LT+/6,&<*E%<#%P%\C +M^I>GAN0,4!?N.[^@@6#>?O(_T_:=F0,6M:H#'X)S#4,9IE5;[`=BOK +M3V1/RW%/QL5$P3;S_$EJ/<''[75V)P"QMH>D*(@_"5)%LAVA16FU3TPW=F64 +MT]W34DNB3'GC6@Z5/OK`AJ@L">M&8]-FNI\^N,Z05F*C!LUBTVLV\38KMQCY +MOJ$FWLIW%=C-FU[>?,`S\/$&B:-MH*4AH=]?:K4Q/4UYN^?1_E;(Z1TU&!MX +MA)>0HR0+T)U($11,X"\^=T-*OOLT]*]1[9@"OJG6W4Y3!3OMCVGVER/&( +MIPM%HSLI[P0'HS*[R;T)L[:5P369B +MCD[C/5U1]_:4ZU`LE?XJ(2S77MN6T";]&Q\=%64SO`KNG(A`Q@^$J,%Q?<-K +M-U6LDZ#?E2Z$5)/_P)?Z@9]K^HQG(;!5#/UBA6B:KI`Z,@K80;K"1A$D&6=$ +MM%I^;SE,9,>3_Y^7/6-H73LNNB3VC`/>Q]Z>&V-MG2/P_:;8[4$GXLE-G;(1 +M->PTAQ"$_3W2P4S+EVC=G/A&^#I)XVP(N"S!+EDO#KI%9W^"-_-[WAW`&VR( +M#.@?#A:W`N#/).2I_7V-\WN2*-;R#68A/>C^J>"EGIZH=#C+48N-U].^PP_U +M;[>!2[R40P%(]^.=)6>W#`EELK\(NJQ +MMC=GZE[9!EG8A0Z;P>Z)(9&!_/_2[0EF70"JAH?!!+,PY=0WDFO'[ETA^_!6 +MA8O.A+>O3L1O38MBVA(ME0D2U^S,=!!OO8B'X*-X*E^;D#,@+_5Z3>]Z +M3*4SZQ(Q*JRJG<:_YI%KFTU)^=@UDZQ[#^^4;H*/?G2X(7HJUX&T&<]<$&SD;A$O6 +MLN@Z(!#;RBOJ86-S-@90=TJQ>WM>%UQIDU=:N]J^ZBZ'B]F,S,2S^CLSG>&D +M9`=!0I6IH0$,RDX!"`I`&V`R37!X<8GC@.X>CHUHR@]Q68.5P23,!LC=]MX6 +M2E@R#SK(60](L-2!FR/[H@/D[MH);0=79N+Y:[:C2,RP&CRJV8 +M%RRE5&I"5MQ$Z,&H;,I;G)%1.AG.N(/(:%69P/;6A+,?0NIL3% +MH&:11#+L`.H9;6?7$T#D0]7X(VCL7]A`-J63%%'>^6W+D*ME';1!S[?Z!+6! +MQO*I3@HN[4/%*/NK^O6"0W8!PE7ETK*_*^S8H5U8JJ7'C7^U'GO"M.E,N?6;>[`DW'L+[6`#4#F[4^6Q'O# +MUB`) +M_NZ>+&<)-\"M,XW\#?YMJ&=$"JMFB"-)20/E:*^1)6&:=HN5X)K*EK_*MMA" +M;2]8MG+F!^XLH6^G^/I\9)YYD%7N@7PJN^4$QAL(7E'0)I*2]:]]O<;/FKR0 +M-#$O;"Y_67D%!10$"N'P8LUZ8+(B>B1EC5/&Q].<6!+!E))1AG-%L#P%R>WR +MIP5B0)I=S.)X#?97TO(7>$*EA/CPAOZS^CQO7)V9Y=.==D"[WTJ'C$UL@%\O +MB:N'BUR&9M4;N4W8OC9[8+&`A!JJ':.?M)U(]1%KI820*,:U5C'V`#'93^V_ +M[#NM@S:YC!Q?VQJ+DMJ%5HD:^F\SITA9D4QRKUBS?&ORJC;I=>[=OXZV? +M2K:O84"'-5L$4=Y)8QFA6UL2$^#GK".Z]](1\BM=MF0CRV$?1667Q51EUA-3 +M2&5+PUF*>W^*QZUP`UV_P*;G/:04"FM%9UW?4,[3 +M1Z6C_D`=P)@Z%LD_0`9@+U9[Z<.ZVL-9.64#9:\NNM%DK;4NT:$&I( +MP;[/!ZZ%AFA(@]&F$&W'/ARL3EF4TL%#\ZNMS/8:!WAHD%8X['`.O>/A>MCN +M%I7>Y5-<'3!2>P?)LTNWSBI9/55W`P"!^R%VRQW5Z$Y$TTT6`1 +M59LY5:R'JC,&E:^O,!KF6@YN(H!4Y6<$^<-?="AF!O77T]TP@B^T+#4OIL8Z +M]Z78W`X.0'3$>&1Y)99!9K6QZBG3SGBI@Z:]>FK%^T4][B?G;4Z2*"^/7:#9 +M6I?*C=%ZTW&`I\.,HMS&ZH4-/U*`_;S5HBV4_U^1C]'NR0'E2:?,WTZD^'AY +MQ[><\3,08Y:;'"%YKQ.'XCAM*_5_EF$,R%[B7M,#D7'S7%ZNBCSORWA=490! +M=5/A3J@=1M@K\Y5HA*S+22X8F#A6-!7K>`H8)I\Q2.$)D/?,<2*)3_/VYQ1M +MR[,QV#:+4$\$WS(Z1$02%@O6,H"BJ\_5A\I=MKK+P$7I#L^/1BR]C\3&4WHW +M\6N4;F%+0PG9GN)HL_D%%$3QG!R@3ID!?XD[[\1ZJ&X]M2;W^9V03RUPH[`% +MA=T(V\64DZ[03V8VFCJ!+>Y>IJ[0YZR', +M4&V;S0C.D<@?!*QMH6NI(!*@E9/0HM6+\D&MQ\XHC8O2*I9+RSBMAFBP5D/'@N2AQ\#YCV*>#C*74M.S.N@MJO#42]LSQ=#\O1KLIG]E$V&9.L= +M+`,W1C\I#@#$RTTMQ#'&KS1K%K?PPFN$&B2UE`U;X/W[^+Z>@Q@$"N-Q>NF8 +MSF3^T3.O)M]I6#'8(RZXC#"M3W]_8XTB*+`-%&OE"0^]YC!M7-[1J=TL$V:7QLD +MB%!WYYB/*G8A-Y[5=MF-!P*0?&&;+'*O6`.D?7*REAZ#%E>+[EA0#5V/GZHA +MOQ>#)WL*7DP)L\R@51E%--*G=PB+X"S,_AM;]UPL6:#]E1S13UQ[0%.V/WJ6 +MQ":D0"M!0#+7N$BU9TLJ^TO8^>8ZA4=JR=Y)@D!E^DL_5C82 +MR:'T^*=Y?[W?Q0[5I::3O+./+.WZN\XU;)=%:H8O(E60(T1(R:DFH)IUO#.: +M?HRU[(WM*;27?JZJF'3LT8<>+NB1P3Y`1Z]S(9W4_\K>=1-T>\@'W9AG;YG2 +MY-P.*PAG=M:G4($Z]9<:]57 +M,D0+>,C*_D6CYC&_Q][)S1/5O?;BX4DGF6Q,'$2?>_;1C!;4 +MU&`M3$<.C4Y>N^;->4RL25W-OB:M;%]9TH-Y[^TJCA=3^M5D/*<\ +M>VASN1__>.]TEV>A?'LM7S(NXW(%1&WDB9U;#&XS6,[:OO&2KP:4I`:A\4IZ +M?AWI)S["`0F.A2.AS:5=1HOJV#.:';B+$&E99G,7`W#]*G5-'7G>,%DGH<$Q +M>N)4:1#PKURP&XS6_UI0*YG$WC"^M*YMY??B3QK5C;,\H%B:EN#Z7+* +M=K$C"3C&Q5VN%V+WNTTN)V85YW>B)R$4BS3&-@<7MD?HOK"[2\S,K3Y]@=(O:1"FL;/_YAR:`L'.> +M%B'Y+*%`TK5B`73+Q0BS9&#"WFEK17#;^6-.\@+6>)2X98;I[8"[=._G&[3W +M89>SKYN/*'$U0`\3.8E#48;Q+1"#EX?8?).S+=1"=4%J(#I& +M2M1U5)@"J]XSI4OZ$8?@04:U@%7Q+O7>#&OLV!+'5`5^+31]BB31QLV2A&&Z +M.N84RGL\^,P?U$V@)BZ&$ACE@9I=\[ANON>DM5PVCI-6.&\N#-8CP?<9I8R] +M'>]`&?LHT;B')E\)0*7QZCPP\+_Q?G8Y::&D55^;M7YR@-TK;0P4G_%"^K[V +MD+G,RI3(UM6QF9MQ,:V$9'6-`KN*`V=8#>%]6&`O)_J546=@;O)U<-*^)6*D +ML'IAM--*-/!-LUYUO0%E'DGSFQ*_#_0>1/NRZT'Q.$<$F*>A5GZ_E')M;11` +M8_%+^<3E[FM:]!<55?XU4UN^+U;:4F>E&>L(U86*;*<9)V$BW3*1YKG0M%,# +M\K*'HD]`F[P.3EN18Y[HUVM!WHSNYS:TVM2WKN\W+CMVFZ,29<%+ARV-;B@J +M_RE,N"FGO/G`(?.K$S\P]VXY%B11Z)?N+#L-KR6EN@EP6*FI2)@U1*U8F^N2 +MMH0'`1(5_%?[GNQV:AHB5FUF/;H/]X#$L31LMH6<@67!S4+F*1<@W9^DAY%J +M];I%!8'$@"#JZL1I7OA=J7=J3(K3A^U3[#BW^*0^# +M3PG7S4JYA%!SZ=TZ&7@1WG0SBX2.#PU-V_0P9B/"S8&]:B$WOIUI09^3!BR@%^K=^( +M/<9^UR+*F.Y$DI5DA<6G+1<1Y%-S;&)_)>3#%B2#E:?5@K^)5F;<#IS.:F=8 +MQ(9$.4VU2S/"86LWM_&^VKLG]<42H*.7PS_B_&!SKH2)RNAFKO#;[#E\AM*M +M=ACQ?(41_BW(+)M][@ZFU3__5(G=ZWS`K;4.$<('O1'1P:E2?8PH/+#DOV=` +M%X]^NB4*[+_(3JK@0ZQP6#VX=X2@D4<8.9/I"?-=1MMO[1)&1`A]W^=`7@Y[ +MCD:@)+S(CBSBV*W!M_23@9X'-*?PV;AE5R=*X>MVS +MS14K2[H[PL)`8X$*O8T[^M#WAB4@?2&VTQ&"KQ"^U7%-H!6$F7"^Y'"39#'' +MG(Y9C^A2G`2U"\0E\+$AW/:HDN@[IAB$MS'%,3[`KE>]\',HMU#,I3W=4'%2 +M$XG94G?$I&P@9%-^:W%V%+Q6LVQW4#)='_NVG8XD$C4\)XMHKB"-,$3SSH*= +M7W(U27/50X=T]T"#PF5;_.<*L'/Q;:W^ED\3_P&RQ:20TC6_S]JD8:_'R[,6 +M(3E:W68/0\*^6WXVD$A#R4I+H3/6I5A2JX+ZU\_97!,2+M94,E:NLN09E'C2 +M9C6<6I:"M7<<"!:.EP#%]#GC^:'LV]%/!O%5U32AW,_PC3PMGREA?">T9JYJ +M`8>P0P#MB54=T?H")G@YU%J&^7(0US7;K51ME)RN">X3(C]KBF,$BP^D>5?@ +MWBH8S^Y4L4X87^\)(_7IR)7U?(#4]JA.A0K3L&X*?063T!L2R/Z\IFU8M7Q4 +M//X[.)YZ[!U&5H@87CS#$3*JHG0UC8H[?PZBS;.W%1P&W^771LC*+`/E61J] +MN>X_="DO02.0=>(/_*EPXLUIC>#4YBX$DWGI_ +MSTI_'F`7`TR-BHQF+MCP?8E(ZJ%.2Q0KL4A16G<2&G'<=J[$L!NA\_D9'J6KF;B%M-@*&UBNFT`6Z47_P"?^;,.4DP]F'^RAC!$=\N7JP`T +M&*+GSG;&WYYTW'N_`RBNDA0HKTD*AQHA?]H?@.0M)"\T(7O9$1$@E7S2";6> +MPN=`8&TBFYG8F567%2JC>@!6?Z*3*16SBQ)#^-IDTC9&I9!0S&XTA%YVXH\? +M/+/C$4H#W'=I`P0A0P-RJFE;*KT*MIC-R@A06/!!Y)NZ`0%,]_PSP8H5)I<[ +M;,.KGW,2?)3_9:]VQ%"91?[KC\VO^%>HF&9:VA/J.(A8NF);=K[MUN-6[N^B +M"NAM9LDD;_#\#L!UMG<"\(L<8_0>C`:Z?GB13S:"SRCX<%11VP_4V['3V'+5 +M<:-X9`JFD`TZOS3NMK&2@X=/]8'[DGQD6:-G$L`GM#^@6ZBX%U.AZD%ET)^A +M-@)!ZF-)P';<6N6)LH-FW<^$9NL[9EA$W'^$=#T)3/&IGJO34,SVF+;W`S#B +M?"EFBP89I*Y%&.QO;@L8T*R]XC*."!D$07(*(?A$K')_.XMDDX590RF(CS4U +M'3HOLSN)%\"=6DF4GM!F/I& +M@<8GS&U8S6%EP<&2E-WE"[_WT3B-&BMXDV'+]'_2^V(KVW6,X>A4%'ZG:2S^ +M/'I:2(\\7!^`(XRZXGF&>$ECF=]1G@TR1/PT#3_%PK[Z+;[$$WQA_ +M-E2_A8/O[XA&4,W8'N[YP1G@4UZ_9^9??VR0.AY05Q&>.8#1EV6^IF.,K:1Z]V`7 +M^'X2,"\:OBA>R/BM]X301P%T8@C:H$(>])/J2/VITGWA,I[K`W7G6M=DT*0A +MNM%'=6IU*3X"?ZU-FOY\DT-=?;,EO#.8T(W:*3Z:-?0(<>@ZU3ULM/8L:JI2T;9CT5("GUQM0LB[J]`]"=3HC(F5*'0#!9NISI@G0.:!D7"_@P'!0!Z/F3Y35AA396CLG7VW692]X_135/O;(&%)_G;6 +M*8,%7([M(+ML#&&(NDFUTOJ"B.:Q;F/K'%<%P?FQU4A($RLUJE/TI`_4WA*\ +M=*QM7"!6<(N>H",U+B'X$.+;E$Q;OQHUG1CO2'U//S,UJ_<,%C"A=S&P.N<+ +M('ASP>8B%^2`U$..`RP6D*=12G*2+<',P-BY'0'72(E(-&8)LVD)F[JM##Q9 +MAPLS")M"V-'.#*NL_=R)\Q5L`@,S#[->*L8(0:5K&]G)(&HR!3[*Y=4T0-Y9 +MBW/.[?+4DP`#`QEO07O+@@+QW)B.];$"+36PS7V/?0+BS&NOC+<]>V2'30$D +M;M/5%J2J$:?L!0"S9^H![*?58^S5.943-.G2:Z_:5H'XFVR4WWNG(*,"R\(\ +M(P=-C!N99.C4>Z-4%Q2*^SQQT`!6)ZZT!.4JZ&X]"08D;J:))_>"[^I9#F/Y +M>*A$ZX/G:1\+9L4ULN91%18X8Q:"L$@$-Y#!G+UCO:4BSW("FM)LQD0#.KA] +MW73#;8,I$\\XRFWA?L%"&<\]:([O(A0:GA>#@_C">8%9EE0K@6Z_]O;=S_:2 +MP).^(/.(I6_?A$$/8WH"]WOF[Z%,@R29*RCIQ'"+F%[!.Z73*NGA7V"][WD? +M;[JA$!#:N<>EIU-S_G$7:Z_V,_'YF&)\]N=/1@;&@VMHFP7`G0-2;/>1J:#E +MDF49!\G!\_ +MUY=5Q<"3=@0+HFZ"75*(G<]9UVKP*I(&`W[5AB<68WA)*VQBP.3M-=33QHA_ +MV4/)^W^8#F+#L\VBF6B,JI([GB='^J5Q7U=X\@8C=%I>YD]GZ9L(*C[*@HV(O`$G@PZYWCVPB]0?_*H +MBG++6Y]8+.^Z`2J``2\<>XC_)%[#.P7.[)PC*N=ZIOX(`-O?9W78YGJ_&/`% +M9&NR"+(7)".^@,6?%"EY+"^II)(_(#[3I9CX_\K/+/ON\H9,A`^V&X\A-&IM +M%W-]7@,RYG5*16/G,OL1FWCO'O]-?%"J8`>74Z&*@P;9QAGUVSS$!&V/4%?8 +MM9WN:K\C%,1`D5LC[YSG9&R)GN#?)Z-,`5M.(*O.3\BX6\O'QL-A!\UT.Q.Z +M/>V8$Q-;7L`$7*Y92;XN;4KOI=?6\G.3PD&U8G8OM2_;ZZ@G,3?PX0RI@5[Y +M#\6V&#LMC+,&@"^*Z-C?-./D"$+XS[CL\H&:[<);3XNZ5YG_8+,/V?.M7:RMN?(LS. +M<%:Z8.[2S_@IT"Z4D5X^"PDI4ZNAP5#V_/((?\`-FIVSELHQR6GG825].;ME;4K&:%10T+PN=L*)7'$-D\3MTO +M^3R1J]3\T;_)XCB7F"@$03#@V6FZMFW#@:SN)`G +M0TGPH$4,TPLU^*D*"$T2(YO1L5G1P@0^)H0/D4%WZO!1@"/#T&HD2+MWY1"+ +M9C"5$$N)NW#4\N%W8!`U4D-HIRZ$/R)(N]AEQRI?B%\C +M74EV0W\<3FN^`E8[LT$+A`S6\H%!?0:@EQGO0RG3E.O;?U$4O]?H]\Q5>U_0 +M1K@]G35FWD3<=I*3X?E(//1Y>3$,BM*Q.NX=/,92R?GY5E\3-E+18Q_`Y3M&1CEFI@7',1&QK"GO>OJ; +MEZFM];HB\K%=NO=TT[-<>!:P`#A=/!6P`(552([ETUCP4SM*)_XRJ;LX`.)M +MH`::^I+&5J8*!>SF[>:"9WH!O8S[F[1Y8PEZ5S^PTU[B1$H@5F8F#(+D"=0O +MW,%)^-M5P')S7/LA)S9-8I-X(;U/ZJ6$VI.68=^)A;BT:^X-H;?C;US$2]J4 +MN*<-ZS8C?\F[@%X6"8K<(J+/CA*&N3F\KX*!;GMN+-;_';;EF97=2[Z6@ZM2 +M"7$N;S$8*.>_5WB9<#)1&-16*,!\P)-QN>U`2B)7J4A3S@2XL(9I2R(TE1"% +M$.&4>1F,HG%2,[)C=BG!QB-U%+?58.23"]0!!X8`%A\C(Q8WTQEX"AQ2^.[L +MC!J%$_]GG1M-'1.('=MW-Y-XBYD9/KQTK0:_AS/.8VG60& +M\V6-V-NI*+6%)NFF&/^3DNS'LYQWBDA*C:OL@*5V&=:AT[+!1\O\2G2O?A_4 +M5BB(<1#<')GJ#V*S7-DMJ*@N6B/!O +MD$]@5;J/=VH6-%%:^D$CQ5",ZD8([BU`B@ESZOZ:TL9C4!,?]J356[NQ<\"D +MNW^Y?163@@XN]O7\AZG(*X^`[RD)!X/JC+[9'/Q1%:"C"I\"M'NSZXPFR"&P +M)N>086/`H36>>UG_MASH\ON,5@V?6:;F\P?4[Y^02+T+5*K8!A.3<*:&$Y;2 +MN*R6XLQ0K3[E'.CLRN/$:PA#%?I:1K;;(4N@#JGMY]>EF1S-_SXM/AK?V9=& +M%Y5R5D[Z;9U'!HU-O.,/=4?_M>MGSO`]`H!-*/GW2[B'1H<0 +MS^Z=HL<%W5I:.D,W:#2B5-O=(0+,RQJYTG"EHL,V+MX,?88=$7(Y!K7/MGS)>C3?>DNH@N+75@)Q? +MD.G4F+2&M#@UO>+>QU81>?IA9#($2\T?^'D9Y?DA27SCQWY`L!VH=FM6_ELN +M14BF0>=ZU&\*?"M'N3OX0+&UN[E2/MAX<3Z64V8>-PX@5/BY]2D1D!.:DT06 +M1?%GMS.A667T:DD,S5?5<+^UC*3.:ND\Y+V5WJ-+&OYP9FT+.5%\Q):;>_E$ +MFWW9N!:SZD,C:PZ%Y+MU2`R14R]G^B>RDA7,'Z\:AS+*PE^[$ROGAKQSTT*P +M<)7]RGM40]:0V2*/3Z2`&&O:]\?K0+(XZ`Q;L#8//7D$;T(1)D%^D.PW1[%X +MQY&XS%_44Y9ST(9-DCT,B](L]QY#D\(NCWW$]>%)6)3K>I89A0'2-_B1I.;( +M&YDQ!PJ++U:`D\IPK6V"&>L:V1+'P_D(7LPFK"0;YW"%T4DT(]TZ1((9W=D5 +MTXAHH@2#E]Q@K,3:A+`P>X;0+&XN?@KJXKY%4)(!83<0@\=C`;FR%'+<6F.\ +MPJ!EMVDMNCU\ZUQHL\A33#H.-@LHF`KB&E3/LLT"KU".F0Z'W8FNO81"*U+D +MU3[VMRNF6V4*\IWA:`>D5@0F30X&!JPK[(O:?6Z95N0XB@2?X=1$X&KBZ1*>[M0,U(G$#=3QE-[?:]V,&Q(_OY(T[ +M=.[S43>V1IKY[,K6$N^'QQ/GLRH/&BZ>,&?R7?C +M>:`=N&1"=Q<#LI/PA7LM +M-1;>R&[_TI_S!;G\N(]*-1^RF$%67'V7D5Q5XBN"^X$LJ3G0_+GO,0VO^W]@ +M(2=U][/LXE74!(\_-2/5BQJ.7?7+?Y;Y9FXO_4>K\-HO7OK/6%:53R(A-0F, +M'Q;MM3,%/0F5&">"2:X"?\E"6?%4\P%U[DX5 +MOB(0]B+F![9*L/V7IJ$K6+J\P@(JU7/I[T79FPX#?U(`F.F%4,762NS(;W=. +M7&5+K:G%[7>\2Z/U"U7%T&#=MV9E>!P_E6\326X."83\NG48>05G=R.BW>0U +M1_I_+Z)L'ES%*.'`B^,F'V2^,G4O%!5A*VM6]3B@@_*^-#'9>UR=VF.??^FI +MB`[AE6CW@32BBQK)W74'SINENS5L/<7\F*:JA)Z?#E$=FN@!%!6X;9S(9AP% +M[:'(-HAE;=`SW/)HK&DF41X(\VO_R_W+PB'SX\6]:VVE$FC",ZJZO-IAI^NK +M0=-%]*$8I"_E'7*^E&_@]Q'$LM_\/:UWSL:.@50Z@?1"AJQ;,&1`SC0?XDXS +MZ9`#::1;!;]),PWF,L`B-\0>,B"8[PYD&D:EH%.[ZO(BFB)GUN@HD"IU44:< +M=GM*'F64V+,FOD6\:FNL4KF&C02UGE-1U[7MLQ6LM^TTD8;P&;ED9L[E& +MU]%+@2<8RI3B2U5O7>35>9@""X.;R90PX`MTY-`,L;E.LN0S;B^&_34$@.@J +MY:'Z[JC$CHDJ?MV?1B.&JU)6&^Q\18U&#$DSJ[]MOJX5,NE&X96<7+55L*@T +M^A+7*4BM^IQC0,X7C +M-FQ^SVL%,!L;8JOSV!*S,DR;@R?W5N.L?_.TF-%26ZD,"/;5'"2ER(FZZR;, +M\!L;GF`FPIX=ZR'G+1EBNIFI'7WVJ(_H`:2LB;6W +M<>ZH/T=5&0*W0#M*7`&Y;\9+-9"#P!E.)FW37D5!J,!`;AK-M[SJJ%+&*R[&W@J=]P6@B +M9UBZ15>;[V8S&@/OU0Y?C*8TLF0?\]MOYK.,#G?:/KF3%D9A@%>DR[-2S1:" +M+?T?(<;$+ML$`\EX+Q.+K6UQT&!"AY`FY"_YUT+B]3^_SN[OS(X<^VPNB<^* +MK>?6G12T!X/A(@Z&K_PE2ANV(*&`[19?H.#]"@7Q(FL$.Y/B$VI3S=MXW8)I +M%UNS,Q8V+S.SO=YSH%YTW7,.Q#R9EQ\$U7CI`?+C%L`!)+'31[^[50\+8JT7IK$]A3>&JO61-E8;72N`:&OC7L +MPS8I6;NK#?/S090WQSZ"F2`8::":U55OLTA"[D`2^%&^!%L\4T5`/,PPF,QY +MR;6JYG1)/+^=K950#1>Z#G)&N\]Q`-:>+MEL;9'M=3^H?A-GY8!&8-*3?W&[ +M(5T&<\^-U($.7HZ7#D^<0'-T>S0)"&IJ+-,1$(B15*O=BH@$U_DE33I/B^'S +M1[0,]@B>U93YDW8"-:*88,*QX\K`UUSN\)LP!.1Q5$.S\/Y=BO#R>`5L=S%$ +M4$F*JE`X)UN%'_Y!';!6\"A:]1W2"^HRXZUZ,96>&G&-D!9-9TCEB6 +M%D)F.S"!M[\!:\U)QP,!%8&=M`,*>_*9&7"#(D##/@D3:F8@6WB]"Z*ICM0J +M!YDR%I`:B!$BJ0WH'6L#%0/FK&XZP?4CEZ9JVRM7.J9)L6$$V=$5\*TT;X`\ +MO8?T:LZ2_C?!CVPPU!7RQ`XOT`Q0E[I%B8[R4=K<8`]UJT%:PE?'WF=OG2EI +M9XC*$WMYB0J],Q@V1163_)0OVP+P'9,-(1DE3AWQH=`#[&EH0X +MBA?!R]TQKHY2SV\QO[V!Y6^?_$0U4[Q>L[G_1'2%M5GGO)'[E9>F]>D#Z??N +M,!(D'_'.64-ONK[];+LV/!OSXPR+@2)B[@$G&2G+3ZULC$B63T^>$-,(DJ3E +M[MW!62(A?PD4FR?L7961.ZK>I.YN'EH#T%]C>,5?KW-Z+'41>WW95F.F*@#I +M:$#6(&@SNLC6)A7=DA$D_61P9)]\-HV2[QOX1C%\V1X*^Z5/:5"'G1GD([:2 +MN9"8_)&DV#$E`Q7N%8:4UZX"DDZM%RJ:<899'S#16U`KI#1RU,TDK,E=6OZF +M;\:7G,Q8.97]'_N;U*)U1QJT-V.=:B&0;%^]C04#Q3]%JM)$<#E($3OEY5(O +MAGZOAU+8_M,Z8>XT!U08XBHZ19:D*FN&M#MXLSZ=`'L\)W%J?39!@STU=US; +MG.7U.`2>R9:+JJ^CYUJO>AZ##BCA.:+ARF9`?:B^CO5_[HJUL[W7R,'*Z/+Y7_U/>`(^`#F0I6$&[&W +M&IRR9KRP`>4&`?]G?3J)'K!_C-M5_(2`%,:/+ZUYY0U0CK@;CI4;/./JQB.J +M348V9*.\.$IZ9^EJ+'8\#D1H#%?I\]R/.#`$%8BH-U=7WF3GW$?F=-@V^%$* +M3TID[*V_06\>9^``RQ";'4F\>#UNF];5&/'T' +M42"+6;6VO"#ODD^VO]4_6FH9GJD:+)WYXT&=5#?$G7Y11U>9Q=U+@;5UA2!3`B\X9L&XKO09^M` +ML*M'4PKN-_U^.'B7W239?OC#A`Q7R74W\.-]!`@,%-I4BP2Z\#1$1'$P/VV?V7[ZJV!J]"B-`->>9\_)1 +MDC*X])@B@EY!KFC^G6-_(8&F;[PKW@#KS]L+Z5!O+J.4;68[>?+ER-(P1 +MH.+^DY,ARRX1I-"9>DL^QQ<],391*@YWJW5@1M0FXA4@;._0M$&MW:,U$:!J +M*WZ"?6:@.T\*C^HU(LYHL^#],_N0')(N/L<'LL'/;W58B&U3SS/7<@'XMLAX +M#6P*1;(_:[1NV2]L@@6T]DM,1"*BUQ1#<:O-/]&1U1^(X\>K/G[8L*+@1]B% +MD!_(B:8,12>9AVJLTNGH%0A;#'L-`W.`"DJE#=L3E;8SJ1^2.'7/$&RXCT\]#99QQF8T4"80$1@+/X1K: +MEQ0`FV.4#3YI)GRQ4:1)+RKL1ZK=?@_$-)"8.07'>[F<;4]-*QE/UT&X+_2J;5H+ +MHV>;#E5[\<#*[V1\]5[(+=/E0H5G]G>DR+[$)G&?<'?]( +M@'8;H,VZU?^@UB$S;J>(/D^(+/W?6@!G0JX&:?K#!PH-URI#6>X''ZN$GTVW +ME,6!*\Z'>7VZ5T[9_L`C")HJO3=?=]G.L11!@QW'CJ)B2M8Z";2?N;WLY?^; +M-N[G?:MUQPD-@`R[')9_K:3ZEQ]GTT[5_E:&-2?Q!IBU"DS5'!#M_IO[;0M3 +M+EUMZ>ZB>(ASZ\0$*BS)XO.WQ`?7%)0R!DQ3'E94D/MW`!?DGWM-G`@N=\;% +MPQ9\,H_OW+]_B,#TUQ_A).S-#DHM>GKI+BK*V5&F/1-'O78SDDJ%9%^5X-Q*-:^<245LO2"LKJ3; +M\@G`>O/ZW+41]S( +MG@C'QOC[)0X37:"@L\9$R[*>@Y'F1.6S_I6RC7W!>X]5[:,-.[OV%MLQ$@DW +MCZIOEGPZ4@*#GCUPE5(16[2<>:!7AU9R%XT&#N)0:12&F)T0Q\6B;J&O_6RJ +M=)V^'C9O1X5^H=K0P3V)."V%S%4\14OM#W]KP$P[RK,R#U+(*M7*1&W+TK\! +ML2!<_A@],=^AUZ$2.]33]FYG<#-T0&P_-X`1Z^9\[WVR2]>>((MNCZ$2D`QC +MPH]64^=ZS.\`]JM^CG(?%U'(`?`4)VG!..YO>#`FW_I73>M%C=%#"RLKRBD4 +MJ/Y%K!,-_)]&/G&E!IRS?"S$9NQ2FL8\=Z#4$,BS]7"_L4?J>O-B&@KU92@] +MY-`36YUG=V)B6N9<&(:)OUJ>$F1BMIZQF[>]"#WI-6Y@[X'_?I'_T_EF7S>Z +M@CCIATJF<78J`&O]#RV=>KJ%W4T$>GGMS._/(07O`:(P]2-X:/@33S\;_:6H +M0`MMBXI%`-I,B)9N[4\=N)X2.C"]I7\VH(.KP^68QLRS,-T+4C27-P-C[U(^ +M5!SQ.CZM,[W5/[^1[&T_+`Q"2P-61$C:Y+]O3(^*!-]Q +MWS#)(@B6"DZ/_:2%QG5R@'`/53R<*&-UF\*&:&A8F<6HVIZ$(L#RC#!;3.`G +M>@'$0;HG>P@[./@0\A1;A"PH9>+L^H"#S9E8\_3'12G\8/V(L +MBR&#X!#A+TN[N9"7Z+S7O%[Q"EB65?7:<"D\J6[(]3?-M?LGJD/29><,N;_F +M;!90+:_5FER]23<^NE.( +M=-_8]F\]"/2IO(8J#X7M81:^_9299,E"S[:EW'H6KXWN@IBF6^@`)J4Z?!@> +M34(;3.L%E4Z04$#9T.;'QJ)KV2U/9X/_EMEA"?C5K[N.HW*+W^]W`? +M%6%"2[+!:'G[4*F0J[DWE,N0CP'>7BM.G*F&16M&/0UP:3UCK2N0LQON6YTR +M.''_8$X/"K45UZK?EX7E!Z2OKK" +MIPX!_T!2%V]-'?0:9;)K3$+=28E,."DAC7C_G)=H#,U_G`+W8>23KFZ7KDN@ +M+_K1W*](6E>B8P*,6[!:\V74T@.7PO\`;D?_=,1%8`E7`T)N,AUW3'FB+G(K +MW.Z^\X`7N(7)S=)0%*^(K4'U?-&/M12A(\XEIQ3WQL'&;40"9-)K),RD1*[&Z40 +M,9&C6+`VV9G,79$I8/T(,!=2_J*[Z+=VJ>2O##`Q0/^ +M'?>@DWR!(7?B[T,^V4+1?W#V&0OA$GX8'&?SYML+Z#T#LV5`27=,[V!6NM?) +MFVP%Y&_!@+%9ET;%L7ZAD'PE7@.OZC\PB/G+62;V`M`F:C5B"6'^L^=[:*M1;\4%*#B*]3KV^JHWLED0 +M>S9PZG'"-HEW]%,#L@ +M(8>@X9I('QTA*//91`&2=[U,2G:'W[,#DC+F,)>2G0HRWKC +MUVR=SXM,?IF86@1F;GL&+YT4YOV,D)$31^T=%X +M6J8+PO9#@LF>3-`4\,8>L*P;5V'N`#^11/J\?:X2Z/'0KTR>HZ!/OYC&58K- +MU?31\:06G`CH5R#8B#>4$Z41JFTR,)'10H:7,$-&@[,,[JT8E;F`FX+#U[!C`@.FAC0 +M%37MKQ'VE2C)2\AR-K*4-S*`9("GO0?)Z6>M%6'9D9&"Q1P0<*@0QT'@\O+L$*CUWPJ +MSTFX70:EM<-VO=:VKDD0!5S5H,3FYO3!J'":;597(6QB*7C,J0+-_TS6*7$:WENQR="U"4J +M#.:,RNR(3QIS+3DB!XI8Q0-/LJJY"2R$7+]Q%I3O>O1+S- +M=1ZDM"6F?]-['Q%A`CG")S(TR-`,T6#M]Q$;"L_N!_Z\"PVGG*YC>XWQ+F#[ +M.=-NCRR">/>\&J,YN2L>+LCFI[SQE/ZI[F2^D')!0.O$])^/97`>7./W+:-: +M3Z%0#ID3)M2@I]_3O^E?C#"V8C==D1H%$>\`]"$O:\W2Y<+Y)^(%KKMXH\J[ +M]LN\T3S3&V\+.-?R1\WQ3\L=>POG&'&W)N369.`]]O#X,,^`<-(#<4V +M14D[-P_];P<[&D(%O6%$?+O95IZJ?;FLRKLE+03'C1G"*_@V1!!7$@DN:4H- +M(4",&E[U`\CBUM_9'E1N38OB<=&]L94+I^Y]8BDSS,[0WNXLU"Z=BJ+W;Q)& +MZ9]3<-@[UR/1/?8(TD_R>%GR[LEIS/3?#.[^=W+[C7WTU+RQT$BM6;A!,*48F/%&T+WOKO-#(2#.ML^OADU5_Q38 +M6ZVA$='1,::2^I5&N=82$":D.#@H30U"JPK=HWJS6!^K5K'X--8U[XNEI +MPW\,A*>)0-E5];-F6E.0R;8;#GKJ]8;*?BN%_&NRU!.?U7/987HVP$J"&&PP +M4CR+.AJL,A4M'#3XV/DY1*1D+T^IOK,XYH4R+D!9\.\>99Q[3%_8_R:/"M_P +MMCV_R?UOI*Q7O*5<-Z(A<7A%Z>4\Q=^VZ1/`\H<2_BEQ",ETB:WQBBTGJV+3 +MGSLN0]69THO\"^\Q\0UG!ALJ%@?33WD^B-PE\_>D.C"5^6:S'#(YSGS\S><@ +M!R1*843]U6N3\AG"89V-$8QDR5&@_MVC6-`%T0ZP^B._"U2RM((SO4CUMN\/ +MF^:I`2C&&X\R0L8,<8K]U7-%19Y.M;EK5%6.@N(TZP??\`CU=6KN4/*=I90> +MCF4I0T1IV-#86I\T-JL5!SMD@P+1`#P#"]H'D2_N'4"3UK&I>/TV0:;62@*X +MKK\J"^<:YU<@^!3/=T*=MEZO+(\(1D=+Y+2=>\CK.C8PD"Y0W/XIQ6X0[:=1 +M]'8C#%RJ*6!7=W4"923@NH5X?6Q$0N +M;5EW"FWEVZXS4]^@CZ0WRSBJ_H]18.@IH<[C-,A9*_HBPL3?C]R:0#(H?9." +M,HF^R;*'3ZG>'"-=)R/^M(.W#H#*O*R9>`%\F^YVX\82="HH;*[`?OEAPDB] +M>,($*'N/2;O8M(2,>#<1"-7[/7?M+E`BMP9,H-B4MX-WRR_^T;4LYSWY1RI+ +M"=04K,2RX8"]Y701RWEE=1CIN^F$'9)+UP(6?Z3Y[NBKK&D52LFC'L( +M.Z<.)KO*CH"#2F^<4"DI,_!S/+/*L<5C'_AU584QJ\(.-.(A3.[4[BHJ89ZA +MB#?\5#DN'.)$O-PMU@9CG0"Y51);4K,D"`:;^_EJJD2(T9539C%OZ5:FU3R7 +M:=.[#=RCQUV^"1OK+*$^::B#&WABVV;.AET5\"*@9(T73*;24>+*<]J\'S,@*;`9[BA8MCV$] +M1!9UCZHR/E7[P?3A`74F"I62*TNN!"N(Y^\BHG2',S\N)FO?H;XB@C- +MHH+QB069*O9EYJ#^U@]')P&2M%U&!EL)M;M.OHV5:;DA#>L8,V5>4MG>MR9F +M2F")4FN6,(3!6MO!>37J8`MJKGF"ND\Z0#]-BB^110?QXH&8Z^KN?58[B%#= +MY'E3J,K>(,)M[+%[XGT%0`D;>6QPL[4_7FZ+-B&U*OPZ]SX%-\'9;,_YRT0= +M_YC^M]9]C5&JQ42A.@\LWF];%Q]1@17LZRB0>EGF=MMR\JXVY79F!<`[\MQ< +M"CVCRL^LG4$3J2]R"`71/@`WE,*9K)JF9"?X<)]C<>C3HW['R?Y7G]CXRQKJ +M.EE_=7#PG`7K?H\1M/#LIG\7TB"[S+B7*MRNS1(B?\_RM@IM*\HK-P1U!YA9#A>(=JT2-R+22I6B/HDD]>N*/WEY#^F0HT^ +MBJ^RN*OMR[9L)68]V1C6J9]ROO\Z6LEG$R]2-T_3()-`K7>8!03M>8E[P"6( +MAR$(ZJ)=F9-K,+1LEL(ZS?"=TA_\FY:T8TT)',$C&8T"U6@S7`ML-^"AU>`D +M^^HMEDS,3[:B+LZ3ZPU.?Z[URVMGO!2)A8VPGNL51OA@"3K$E$](>3I+'Y.;;]?:D%D>XL/T_\=16FLJM$F +M$)\N5/"17S^@=_Y96:O=IZA^K0/,4@7+7?QB*Z".@[R]`"7:_5G7KK4,/VJVE=%`(D*RI/\[I.=$E4TT[-0I\X7<7LVWBON&P\RD* +M0GPEK$G[>\&NO1^O!X%?('4X!I@%>X])96YST^_J#9ODN7P0*&2T%%6NX,IL +M]J!8H7;C;'6\T@=^H?9IH"K3ZTG,"XE'0P,/QH63+B")8TJ4O70)H.%942%= +MA;[E7'61*I,@/$/FN8$T)M`$O/N?[P8#D$NN>#W3HQ;N(D,ZDRNKJ6_.+1^TH:!]2,+IIYAKX?'S4T.5VO +MVFM9;6B(?E`(S'M-7@MC!3FUA[A.NU)2AW$]19SI&G>0S+_#XDB(YKU0QZL# +M*F[8)BHU;-;4="UD*IB&DC<@]TD21B.I3IAP)110@V^?'/9Y1JY+IF0XTJ8` +M',TG.6-S2[$$%6IB\$U@K4GH:7(TEX;0U^`,3^/=992U81Q-+1B8@*^BZMHHRN_]N+[4-!)VM;BL&XE215E;4(("%@RK)+ +M0:5N-5V+4*Z@TB:7J)7B%=CWELPA:Y37*JQT8MJCD#Q#S(I0[H*??$'L-,U@ +M*M-373R3:4O[5=VMJPH!;U]X\9IJPZQV6[QY'T724@TTM)U5+&?/MA1KSHFO +ML`J!@A!#W`!/\D(BIBI]_.S?]M*]#;D^Z8R;)@:GO@@MX)!CTO)2ZI$N@LQ` +M.?VLW+F$V0,=A,:`-_H%7LGD28AQXIVF[\>BYHDQT0!Y%*W>4DS"+F;L\LM6 +MIDV7$KPYT6,^1/PF/4,.3=K`4+:=/%A)1SE[SE0JZ;C`VA1D*@5BBG[RG*'/ +MP.B%[92@S-;U\"$9D9.+N6DB4K4NPKJC[013:-!LG6C:U8BG&LY;G!^N/3F_ +M`'A')=;FZ^(*-*#=EC0W.,,&%VM[&:#.],$U!>UEO"ZC= +MU<5=`,I`D&29X+:+$*!Y@-?RV7TW*>R&T]3'&O[,?V1.>,\6#C)6H#`'5/0R +M!.SIY[GU2X'/BGSL`]OG?^*"'(RT!4:""D2'.+J14NE^-(Z'>;<*!*$.!M;U +M@8/CE]%34O@P"8F6@GZ,DWHH-`M+M8$[1Y)[I]"`##F/4YD&[@3FL%I!^Y13 +MPBU<+M$!<3GG"/FIHQHF[.?3#/Z/R!QM4Q+=9-V+&^B,G&S+_;,:6'[$LF;; +M_-:G@`/XP)KHR?X1S/L,PI6>7GC^ZJ(+5"AU(XF-%X+J1(GJ?Q\7-TUE+JP. +M?,9:1H[/NLGP28?@>=P4GMOT-*G9$[7VTMX\H11/*17?'^E=!%QU>KKEBO7B_=;--+[R(RK.LZ`^E78,(>C@;=U4&MX)0@U2 +M46SV#T?7CLL/J[M8N;CFX:`W\V5-?4(-L`5I]`DI$`AQM-$$ML&[1/_^B):] +M"Q^?OC.!YXIZ^7K*L6KJ+TMJ>B]?B[`W*?9V:E2,!'0Z&D;'=E4?#,==IWV4 +M1ZIG(U]V?791O.WPC+1;J?(QRD//&'QS>+%)W1C+2AVP%9S[.NC960J28S^! +M[`GV2SMD3U,T_L'G=O#X$L"P4;W1`[LVD9YJ%8%I#[)T0Z'V"F&Z"+<="QR- +MNP0NL#W;(@\)+KY:#]VY +M*?1K9#Q\5#'F7');(BIQ#+78339H\QLK1;]NB^S=.P='L<`GV>#%"73&+BBS +M9Q"$%B!`M5L.:-=)GD:)EW29'?X1O2%]-ND=/AAJD/"))$YWRQ::'J.[NNYZ +MJ&7PJP>MB_D,`P:HK);Y6VO,.^4T1NM(0FF+&K"O&S)YNG2C3@))MTMF:`8+ +MHB"\Y!T;]__8F=E+[$(E)N8#1?UX4"W9RM@*MN`!?341DRHCS&BM+9WRT42FRBWX#%,LDJ;FLWE8 +MV&]Y4:-U^DA*()#BM:P&R2HC'2[T(Q:Q$'PDZ<;S.7CQY+O[39NZ!S8D6DCX +M.W'6/P/XMP$34GO`F9455DN;63"6=(]B[WQ>-Z;NSY4[IL0TV5'&A9=?%+6+ +M11,AUA3QX4,]FYE9TSP+L]7G2$F&"!&!7"1+*4_CG*P!_4(69L8,;>$J59R, +M%@3VP^D8A%V3NN(9/T-C;G1X$]@5*K[YE4-B@A3PY0V967-.`,RR`RP9W'U4 +M):69,RD5EG[5B934%ZI^*IOC?F(YTECX7>B9%%'!8ZJMVWD+AKT01*A-0/"] +MNK)?SE\_*74*+J!.YI=1F,LEKP*;&BO>M42M20?/2L:M_X'*R`XWS00%ANB% +MFU)[7*O%*G"B0!)M1'"9ID.SPU=P;G?/)T%W?D&]'Z'"@%;@Q((GN^/?[C?G +M>PGP$-5?-H2O&.5AU4<:7$+7K-N=]`A53(W9/98@%N;]OUURF=I2E+-MQ/IM +MYUNM$ZB+LMI"4]Z\/.^OD,KWM'EQ-"AE"1)?_2CM?[F(B+`P*;P*)^Z9DR6S +MPAIS_#'>#>["!+[,.CT;_(X$K=+H*HS".EVD1G6"]K`4]I^;1>%4HDQ"(@"5$,^QB?ZG^GU0!4\Q1M641P* [R$VCR/H&N +M<5[3AY&;$\"RXWB%6I0/L626KTDZWS>KS?5*.AU$BF7;.VZ=^=3AFB.MM.++ +MK&Y8]`P?]I1)TNG(DC-_^R?47YB=T01&I8:G;(*O_AZ:-U(O`!0R#WT_=9YH +M>0;;.E]7$MT/RLWB[%\'YNY*') +MZD/&8*8&4&8-R4\]R?179%)4"G\F&F2'XT/JT\>)_)41!9/Y_`*>%+=\Z*1_ +MW\;LH-M%8^8'!(V1/487#[LA:R]Z$+_6]U>[\V3:`EI2MO+-;A=I2L:P`C;K +M`\W1\QI)R`;U]]2(D,V6ON?=HT-XS#!]S>>T=Y5]7+50\!U;*>'2TVQY?Y5S +M>N#3YR<2/HX2B/X'F4SC+EQG*\W,;LZ>GS$K[!R#5&JLH6+BE<59CY_20?^/ +MZ;NP3TC_QSX@C;SQD[%I[D^;5X:X? +M'T7/-"@""C:\M8U#K8 +MF7IG23R8-=%31@V#\@F2Q5@/=%&#?@?KV4X#ZCM1PS649/V2(8XZ0'-D-``' +MA8"G#%RS%'@A>[053R%/:(D!&+=,-#41O=$J"-5HR\2#;&24A^R^'D$(B=2. +MU?"T5^`\IHE)S`"LFL/Y3H&6!'34&3RG3?/3&'LE%'T&()%1J`\53L:KU\^>7C#,\600X5Z#\JVD;Y='M02#>M#&+[#OZ7"R$QV +M0A9@H@)V`$3!"C)9@C/DVXLZ!)^2I)K\<-SE2XKKG+I?8X_Z68^V/A%^KI'HJ.>T)&'C5D19!^%F-\X-T2]187]+QV +MBU>1D5@M:(VV5ZR*0@^ZN)>IY90`)?3<^PB21BPEDQ1-KZ3"P5'8VO5). +MWU,35"DIBHGLA<_'H]U`5PJOW`*]\3M"%"2ZI^S_`]3813TX6?A14^S#Z-]D#&#"2A<-=<&CEAKY8G6V/0), +MGB]*'^8@#.,AIBGH:I)L_]]*<=`$3""_F&@4$IS525JT:,>,FO*$R-[:*N4; +MR\SFJL"2=U8O9$U]!I>VQ4;ZPWN\>)]([H;EBC.-"&MEZZ9S2)8$NY3@36<[ +M5P_0;"'N"5X3'\1(ORG^8+Y8#90EG2RH$DL6D'\/R]WGC%C8VF=63#+M;O[@ +M0OP]^'W&H[-$--IW.1F)I+2 +MU[+%O(+>%-6"?F])9,Z6+S?4YFU,1N3F/@G,FYZ#*4CW.HG/&;^I6HV_W605 +M9(8PL13O-4G\:1<3S6;P^^U7:!U&W*F'P,_$&A4UQ-T0(RO!*Q7E"+>A.> +M$_=]MA)?.GF<*&'9,"8+?ANWHO28Y'MM4JF^\;^#YDY3H=H*M!)JYFJIEQ4J +M`="73#Y\>*%K#2F58NSHVI59H5S(?N]_QGFEW/$,VR^;$X/';R=ZOVW0M;EE +MG%3Y\/`_DK+'M86CLN\MMIHQ&A9ILVO/$3!E=R7-=8%>W9,)JHXJECG6_:*) +M=O@CN]P>-@L35%[A4#$&&H5Y^FPBQ>ANY_G%[Q1:>P2M)DK +MK$70>'(`L-<#L@Y+3H5YH!H@L)U@S&T'KY$8)$IL7QG[Q/S'M1GN\?',E7J0 +M11J;1'.LN;Q(I_093K*CETJ9$BI=KVZ`--2 +M!FR*9YTM4DC"6>"M-%*XEE,)HY,:@SH34-!6@:23[O5IE7?G36]K$2A@-^7V +M4U@=/KTV3X\ZG$H71*EF`OVS:KPMM><_-7E+:AG5AKB^-"5D5BT'CD'N"\#> +M"GF7RZ^![%VN<8(*X[IW535["L]YY,N<'R>X.!)&=XPL*.0Y4.WFO9*5ZD61 +M+2%P8%`F[ZK9'E8SC>L%V68S+[P/W,_D=%BX&.SH.W]1OVQGZ/W?K(8_0S?=G./*EZCA`M&0DD38R%T+X +M+7)CN=;#JH"@F/D'9!5X@.7NJ6$E"6KP3Y>+/8F'5//6(@!V3.NN\TV1CO(M +M"FC9JG9'/HOS>B=8V_?BKV*1I`R5)@D`Z__"-#7.ST?77HJ0OK,>QP&^Y\F +MV0][*O()VOH(UJCIAG!%OM&-BM'+I0$S#S_:4'PXH>5-]:1VUU.H[`NF!$&8 +M:X^E+L1BV\*V%*ZDRD +M[N*[^[V,>[*H7\J@W8?94[>"I$IRW;%Q67#`GG3+Z6JE1P7!N^TA!@ZBVWLJ*F^5&K`+P?AME&(&I_5*A4X1S9^\?)WA7D47GN./+* +ML,D_T8%\?Y5=NG90CS"[-/IR#LM)GVAOJQ`FB,18V)6$`9UI66;EN:RIOF.4 +ME&(Y6C48KL*-$F19)"`Q401"`N&CXB<[A&E`$-,2++=4Y<4AYKBUV\!'Z?2H +M1)I.5(1T3>30DD&!6A"I2MI++#^90C-A^-PWC=5J#%/M[DX3?ZD4S\Q2XQ7> +M>ZK[PJZ*2O&8J";3JGT;5`1/[VZD`^+B!X44_#"9XEWN!,DO$*(3B14C]2F. +M4$9YP/DLRV1.NU8NT_*IU\R*ABMEZ?W/S$#DT@;;I_?^KF^OEJ!GUBD_Z00$ +M>5>O&OFD\U@PZH2=DG0/V5<;_;Q?^RN_&94/=/,)2*O3NJ*:)'%4<8N%L92I&S*EIJ`:QXEDZ +MXJ:)W]FQBZ)"!FS2T$C6J7%@FH6A, +MA]7$)DOA]\JD,FL[L.Y+21I_E[J-;F6.`02X6,`Q(NT/;YXU;_4*"R;3[,K< +M0U#Q/`@8+%!'72Q;%+%OT/P!6>.J77F?-BD-^RA'">R0X0'115CBS/&]P@24 +MY[FB%#0Y[25170P01/H]' +M#^_GYSZ+K1#>PG?L\]NU%Z(V*>/>.$,ARH?UO//+&^"X+)#[[5=,FVPN4/7F +MQU$V5_R_X"&V?3<-8S3+&.'%JE15,4'?64ES44-Q/P++.*_(T-5PW!OU5L5 +MA]E31!L!K#/CWPKN';=61RE-1X6XT14X=+*TF:J4D!7*X2#T<1#6))!6X:L) +MX$_`])$2M\/![TH2#6GU@I\]TJD("'Z#G=$VRA,D]]K&0*QMS*"1)3Y3=SC8 +M@U8RBYLG[M$ZG#[#9CD'18)PS_2Z2:^ZP&P+WW#FO#DS0,TO]6Y771O41X4Z +MC*/0'`ICO^<=E;>V'RKR\F/ED#EVMHQPM?A4E0HJK]#8MH)^_^ABJ"R.=XCK +MRB9!2:LSUU;@DJ!/Y35^V^JOWYDRZFB_AY>^E:3&?M9`P`6ZCSDE]GS*>=PX +MW(K#UII[>":N0!.!:'D<^)UV*Q9[ENQJZBS@+[8&>1GT>!7G:!3BC1%8335Y +M>H&8>[]U4M;-FW(JU]>/,UY4E%JR"&^Y1.K?GL4G!^DTI?JXN&K#CK%K8V!U +MP+D05^X0[^FIU$[$$FP*>6$D +M>&C['')KYEQ0)#I1+UK'.M&5R>Q34[KQ-JG\`&AB_X#X\K!GL;CQ[5W=46@=ID&/LQ,F\-VJE +M++T/Q62XT//[$Q<&+*=*I;!LEH_Y?VPK$/.9&-`T=RIY?R<>KGPA]N^J)VPL +MD+C"DZ0O?3A@,F?IDD+(F_\PJ\"-XE2BXBA2Q-3;/_'G75H#-1>(XPT.?F/4 +M*E:K#^Z/,?+F-9Q2]64+L0;(JGO85^W6:N@<>@4]300.O>EM[U$8]URIA^%) +M5OF7FP\*PC:):N.9:?:`V>2<)1V4G644Y5X#E)H),HN7KNL179HY?R650A&! +M.WZFLWV`<"EDY"R2'QW4)GW* +MUL3+Q,">N6FS&Y%TG%47`FQ5>[@B6LM28NA1Q!^KC-KO=*6S<91,OK%@+7.B +M)KH#`U:FO&12*R_'AS1`LVU'0"\,+'6$NBN8'=>[SQ<6RE&7XL!+4K)*"V"]*A!G-YKBZ]KNC;+21Z0D,3 +M@;]#Y6R0,MMZ;LT$< +ME`?7S1<\O%8#Y#Y+H/>U1R"#E$`7^NQ8"XR6VH+\UU/9QRI;4CW>RNMR47RZ&Z2$B=AZ&6P8 +M9\RV111'O`;)P-!7X&@=L9+)#7H6/IE,S8]]0\%/C+JD[L43P60`V:A%/2TZ +MU@@(XP5SIB!&MX,/_U>3)Q$Z,^;\P)T4=VN@CH#0-_:+15O]V?0C/P*[W2W- +MZEM0PREL,"S8]YLQ%P9F9L*Z&,4YU*M$LP73ON&N@*N([>'O@9Y9R07E#Z[-/MY>N%U79BFF.2Z._/?L&)/^O)I]"9?ONA/WP +M4"Y;X>)]6\K:[B7E$0>[IM&E+-ZQ,&YEGP$8QUGI@,B^5O)RT$9?)K+E6RNP=4`>G$Z,T`RS#RG(IJ^N +M6\C%B4T`SRHJ;:;GC$0XM$ZK2/:5S;XE7)9>_N>QN3N7I=99,>]-BF^^D]$38?9YW +MNNF&[ACK`S!05P`/:CMRK;`EZ@[#;_(^'%+NUN"?&T'(&_)_C&_DWLZJ[NU@ +M_=WK]*M?+N>/DEE(.]#VZES>`7AJ7&>X.O\S!H:;=92%>V,CUNJSG"#J;P_C +MQ3J$2;FB=ZI!@.J`]M7/U,X>,":6"9E&0U#\2GKTS??Y\#3".% +M`'*BMST6<3[IWK/@MI.,C))`I,%H#DK+KO9CF6N=4)FVL&D;3*RQA&4Q-J;IP\>3FF;9I_S+Y#9VTLB6\B#IEO5YP`_%*E)EM_( +MH3HM)2BJ0"4D,@WO=.IH&65-?+'7\H.@Z>67VOEK5/89GYRC151XEA.7>L[)8=_M +MV`0D=#`M +M_-E^"OC4@H,T:?X3_A4?PM+DD^??!,3M^;812$\2X/H(7T!2Z"G7>^2\RV]_ +M3A[*'I*(S11^@T%0M%N9)8C"X9*J?TYZX:5V.CYSZ;EY9OQ,_Y?A@+S_RFDO!*Y2HP8\;!>P:2+7NO#5`'M9>"K^W'Z>N/ +M:L_IOX,TC]!&\C=82%[$-(YL)VD:Q0".2C>T0=3-W<#C'=3(`5'8&A6BIM)+ +M)<+"'?=ZTFJ2$=QU6A%Z(#2DXEV*R)008JL\7G+(LZ9+'J"=)G>"B2=AL9K< +MI`,:1+)"9XN\1?N:F$'7MD#3_L7G)$W@]Z-1SLSYYF0%YCU84F+9L:H[6:=Q +M>=(W$=07A+FYN5]\\U@1>[?'"P8``-=/;:I>%.R(NECB$<_D'R/6[=DWO3;0 +MBJ=]O>:XC\YJ('!F-@\^RQ*):W^E*%\B`T5QB-FVV9R+Y5$K"S?+R9Y,8RF4 +M`A87S:2I--%4R`K0?DK`VC?;CB:&Z*@4IUUT&O:BR,%&"I3TD@5&KX$/?T&, +M[9XG7S=*YIXO(^4X14P]^"S(ICPO:SU!3_FS.5.#/L+LC!&,P*-XD37H@C_Y +M)4!%4^X!WECS5R;0CFF7"Z3G_C`M! +M>]ER@/[A31M,T:GYE]/EBQ!-%G&G.T;W/!O@()`=O>,+YU0(M]`'0D?S1)L/ +M-](783;!8X0Q:1IP7_Y_G065I^O:5!8)S$UQV8(-&VV2'#\E/OE)S0>J#H(E +M72UZWI6=*=-4_4]:M:>_9'XZFF`RP'VK%@(HTOFI!)"XPLS>%!W378\1U\?" +M'\)R!VN[<8AF#S(-;">WKOJ?T%K)IV(C0S<*$AU-[X/%FC!9;GPU%8];0RA] +M#,L"_/JV*K3E9/G(BP(GE1:J,8*N$,_!0#Y,WNGB@$N0K^T>4!JG!D>QZ.HG;JQ(FG.T"*2 +ML>:CRM0+5%[%"<(E64E>%)82)Q!\+AT[SRE*^F3+[M'&YD6758X9?J/'!!F@ +MQ\D3P"35ZZ%:U@Q3M7L*UIM0W]7^7I&J*R#4BXF;#V,K)$+%/G;GXN*G^4!: +MO\C.+!!+?3_-<\1DY;7!FD9,XJ]A#;/#]E\#<*A*Q-X_S[V0![AVFW-!R-)=<5KBN]%91#@9*/"=&#M1` +M/!#?'5J*!/K+*MS,0""WI5,18"QRJ9ZYVXQ8?#`<.`2)N-U=]6DDH->!<6&` +MTU,A.]3C$^V.`EFPLEQ&G>-M])T*9N2@1K]/0^ZW;**1Y']Q\/6#B*>-BT"+ +MO3WDAJ.'':4B>7!MP&NJ1P5]>`T1I_#^]D@U+SGOH`CZ-TYS4YI/B"^#T9P) +M'=XA)@Y[-@G*9H:I\N?YDTY#,U6D^[Y(]=#!N_59#KR][-5WKSXA*4I^LJ!*)EP/[-41SS=,?.PEZ&E>W@P2\`T6F-*W4:F'QLFCQY_V.:7F"*U0G(= +M2>BG3QY>]]2X&0;/0'J*N766Y9!5*5,'X-XE@G$Z+^3ZAP`&^^7+1%ZJ\1/" +MGB444('W*,NC8#+``[-*#^@89PHGM7[0;$W9E7#>#=XT5NTS&]HFE^J(!!^I +M<6H1;./SR'.DM,XX/@:B%>K:2RJ@^XLNOA3XS(#8U.5$&:Z>BY;.SA]A!+'T +M74F2K]62/E!`=KJ?K7;74ON7H_.=K6R*Q&L2N^1#>#`?CSEK@Q+^ZO%";")V,.K9>O\.Y& +MKMIQS%3TM".4=WK^]<4HL"0[3E$>@?04F-0.(1U.YEO560N[>>20ALC2CTZS +MT,T?+@MN2:R[X;B$L+X@%B,<7%?V+5OI!4V89H0(S7C!K=B`*+N@FW#IJZ^( +MFZ`*GR!@Q_'Y!W$>=([Z8!\OLPDM&0"4SSEF:>"`BDVBC[1;/8+YX#8Y?'30 +M]W*D[R9)*C*X_OE?1*XD)/Q6:,?-^CV@C'A%^A[>!JDB//`/E&S5RW+*Z13O +M(68>IITGL,!R0]*-[2$QNS9T;W`S(S^`3SM7YWA?U1>,OOM$-BB-17=QDQT1 +M,F],K3`VGL9$@JD)G',0)J:GSEV2`-,MM(R&3;VK_+`%9K8#TODADO1T0"DN +MD,%S0RCG'HB*VA`10H;!5)K+;IR@:PT2=R)4V=K+[Q986_%O$8YW[B((N!"N].%O# +MY(%J@$7-=8Z?`4VE*G-)K#5Q#5\,\@YMV]0YZK[+^'19.7&("SRP[3+_Y&-\ +M-1V/$%T*FW\#V^R4Z,NQ+'&-8NTZ(J^EKA$F,4VP6QYS;.)*_=`J4$L;6[/FH7`C%JKL._<'(I4;UBG3<.7YBK`I'T//WYXT1PCH]QF^>\]F1 +MC,L-AEG3OG6EW@!#'B!R56"<_*^>Q6D8),.MT<(V.M+PZU\]T8/D-'IAK=1% +M15.M!N*6R8+\^(H?5@S5DV2ML4O*X4V2$N?>,'?\-!PJ0<#7EX06TIG##-#.0=1BF=YS_F:62>I5-."#/P55(O&1O?4;0 +MI>F`+6@W\XO2"LDW]02^D\-B:F0+?K3;H,L_;`;)$I#%\'.FO-9^Y\T1:_X` +MM0DH\>M?VO`3]-;Z0]Z*MBYX6E.2%A4J0#-E(*=3.L7(XA]<03/S^ +MJSU4NB5@#C2#97QVD(LUG.12]RL01ABZ!*:X+ +M<32+0?5U&J>*-.[J2;]\='36E9)(L:!BT*8I1N1I+)]BNW57+UD_)J*%I6?X +M?$OQ`WK:ORL_,!['^%BO!)^(7B!X^!TAJ7[+4$U(N,L!@"+`A,Q:TX`6$1\5 +M^G>:L\.?/'.V#22::*/B4X6A/#J4/9,"RG.(M/*UGO1UT-.@8CN3?\Q%1XH] +M+S.-S2,)J3:'+'6=H_2_"G.]"7T&YVR`:R"P%']3T_6XK?[#F7<7OW-&P3LD +M?1.W$`'04PMF?[!O:?]AML@/CF3*3Z9JCJ4L4":O7WU,5:?&AW;@1LQV;KV: +MU;>N^S3ED)35`@K(C+[2#U-MA_PF-YS3EOY5B\2">ZQ&QY!N@/B;,]$7O%_& +MG;DY$(P^*.&I10+[B*4)-\>1J'O)0L0,-Q3=0.54JB'DJ$(\-Q:?3L-`!8JD]E)=3L9L#O +M_;$NHU-I#,*D?OR>(_H?N9VS?RU2>RW%OL+"\ORP[QSR=3ZR:%G!O/9F]OWT +M!;'JN#]0>W$*6B&OLXE$J:4*4Y]$^#ET#'ITM#L7IB[$\&R#_S66`*22)>RO +MEBD[PUNGBT.T@$2/X)ZR0%YJPC2P0O6&BOB?SX+TF]&LD--L1$SA)1-=J]H% +M@)^\M4'-T<3!<=YG07K-*0_TR?M<&K5M,G_9P2*7L7#MG'=VWXT<[&E`I*I3 +M"6BRN($TO%P]&\+!L,Y`V:?7+TLWPO!?&I52X@-2=`76Y8SG:1'&1$S;9$9!L6`.1]0@JK +M^F(2.UJ$HKKA")B,,_R#%C+_4]R(>$(]9>4IE(?_$:1!:@EEOJ06PO#,=95)2#\ +M9RXS!1;HGV;H\OY<1UP=_]@8I0^]P0.Q^3,3E.%#S2!"][>K%T\@V4UHM=S[ +MM*EXZ;X=(`>+#\TF&*O72@O$SBPW$/IVE4;Z>*:EI^BY/AHF%5C!D5'S0UPHD+4&< +M,R)'AB?O)`>*=)"LK[AT*IBH5QZ>X45A8%@]LJ$>QEY:;*LX1#Y!L=/'VL;/ +M%YG*]0+]($\RP:B^`P6P3MT^X[%G>MRJ7X%9ZM@J7UL6G:P]O'T?OBL#$.V# +M4V]=<",0G?O_5>U%4%#!VV3G]O6#*0!]-*&3X`SK_[O&B^^4W8=_R@'L5,(. +MR[8J^+A6DD4ZB"IY$>CP!M;0>2M4#P8M*P5R-2K"JNT1T89I),TUE]H1%7*Y +MD8+XW\V[=(()!,GLWN37U4B0Q/WN\.*-9:D#7\B76)@3:3WROIP:0$LE]:+^ +MC%Z.5R6PXB+Q5U%8D,:..:A/*/\W)#X%J&1V%*"^C=^$"(((EK0KC[6D0)ZA +M/S&U9YBH.>SE!^?;G:1F#+O8XL3Z4QZW.F``]:3[3)V.)=*M>OJJ%*TZ0!39 +MYS^?UOIB]MJHX#[Q%"^5OM/QJ96=V?<2?[Z\ETB9IUAIY9XWS)L4`?Q`5'FO +M>%IWY#@P3HN7>5F3]-2C9:IG4EU\(?VY+9I-LDR3`XWW_#%BK!'."24:($-! +M'^4E:*K$]74G$_,6>4=F21GEW3Z>TV/@P$I<;W?J^MBV=/[-F,U:5[L^>(:7 +M(*.%>S.`G[@US9&ORF9RQB\P54LFZ35)IZ3!LD+8S,#6&H,Y&SVN="'C/.3? +M"8LBI#I-2CI&YUAVCR]@2'HU\+-9S1LBB#_\7>"NC;C$U=5]>5Y:@I7)H!]S +M;!J&]"#QCLR`G^CV3N0+XP;A?HBVM?E"+3XK,_*-[4T#$XRT/"WS +M,'L.HQ__W$;W2N*9M[>4/&-8,]E^-.!!H1FAF<9D%GT*91I$7:X<`?`"=\$^ +MJ*$6B%!I!-'#KAPV%L4H#8?"RV>&$_@23V551/$&-4&*1W+(RV#A/O$5J3J% +MV/;10;@1]#G2G[!<$ZUT@(R?):S._7VSH2KEA!B`'ZVR4T\\FQY/:<[(*N!^ +M(\G@N_G7J'+[M9G*GES[K_H#NEH*[HRB("H&HF8P2QW3_`6S<':2 +MITIB8H4SG=`\UE6^]+"EIS!8I*?'>I-_LT>!-@,$U"+V-_IYMT+SG@4DXMZG +M.J%%'(R>,\1L7ZJ`6DU3/33D7@)A%H&\HV@G5%]TL\8B^9I_#*9&05J,DB$) +MV%<0!\#$0K%<*_QUP'"XF@SH(.:X[,L+J!]+ +M\STR[M5Q%M.W6NOR.KF*"8)<_MQNR/I@HCX$AXF+@^^$M,6ANQ6T9.`-S0(M +M;]/>,/@3Z;W7B-WE2#]TZT=^RTVB8HYL5Q%4PS=+;7;_E+^;B.BE.%MHF?K0 +MJ'VO3!V"KC[!2WX0CCBGJ6P,!E=L21>.=V%D5>U#;4H)HU7)!8N-4A(O=Z:, +MU(3MICOV&,4Y*(D2X4CV7715ZQM1#B#V`E<"2:.F\8;TL)\>]J"TYXD +MO`QP@WS&/!>4RAV39A,;5[3^5ZF9'S`0!_VB*.>!BGUL:PLMMUB.`50PVE^; +M+V\^K0-I95]Q#`E'J'+!E%0S`I^P]3*42).1]1>(:49=V9=Z^.;(9S\+1F1> +MY.>-OZX-@A"ON2ZT-Z\EWJ]#CI74FC)I`B_F'8\GAK*?1/I_]F#>E1\FK/9I +MFY?`,,$(7=L?D!Z2[4T:FS)7(L,E&]I8G*899;@1X!<[\L6O>RL8LZ;],8OM +MEQVLI=NA9^,X<@T5Q/>(;(C>:-\V'FP@M_Y#BD:7)&=*F%:O":[X/7#>$FJ\ +MSG`'^9>QD*4@\AQK"E*RFOP%"@:ODVX +MA/Z)<'6K=N4B`$I&T%?OU%TKWJ$JG5\L:X6P?N7_Z7_;/ZA3H2_AO[1>AL.0KM +MC=M,S>F?&-3:8C9O(2'`O0P/,NYY9D'D:`6Z5,S\M^YHKQ^\MC&2MD3:[(/^ +MKA[<;%WL%R$P;=D2O,C,R[3@N:=49M\I"[#G*\:OMBMI($6$X;V?KA!H@SQX,887L:J7J-_0+E`DF>\$AD:KL_)2;("9M8P,M[NRQ)=TTD=)" +M1%6G@1J;*%I%S0E'9(]T*Q3P>?&D/^/&<_])J>9UF0GU`JWUX9?1V/#-+MR6 +MEXYZ:W5['!C3Q#>UJ9'.A!0%174<@8"_.09\#@6+=);P]3C]XUHLRZM=!++A +MP@SU;:V6J&[*?F!N]G(.TQ56AQIW4P\TB[+4RX_EZ)SV:-\U./0RM*8C>/38 +M:6JR[$L0X1#]D\&GU;?!"9%RN0LP&V+[D-)!^ +M>[;RL$ZF[WR/^G7U9A.45H^2T"^._I^#=2V^J*%\@1M=Q3OR:?&CNO4@SA4. +M#J6X,JQ^=1)"Y.5A?.@"ZQD8)$[@@!./<1.Y$'/L<_JV.>F^NB +M%BKE7\L.G*9T*$*\TSRF6><[>>FMO#EHK&5*7X\KD)I-'!"C+JT#\;=_#5[Y +MS*)W4KS"6H,.+L+QG%H=7;5H9B2HAU$5BDZ^EI*U`WJJ0(F]DRT_:\`GP-#L:%*95MZ#,[,&A3.J>_!I]D3P?(=+&DI$_""8_]_5;BD +M(_3K[`!!?RZ20P-DSCL7PRN092U.N5+)+!\XSF>AUSJ;PTHEQ)!SI%+NF[$" +MXV&#$%J>IN0M^EQ!$UQOU-],#G3H:@_(9SOU8?+`\F9I\A0EZ`.G(GZM="-X +MG`C>WVS,<;0V*RI(D';/E=T^6!2G)ZB1KL.C2QXP!7]Q79S&[4KC[=@:3`3_ +MDIY5@=`G(FJ,";&IODGV#,\V,C_@G^*Q[;(X=*?4,J]E,L4B.A#8 +M)M7M,'Q-\Q4>"JSW'1(+_?6*7\^W,'YQ!N_4O/(ER*4M9^CU'OQ2!!1UTNZK(/,,J;X"5H4VE +M2Z3*M(;W,T0$T#1G<[%Y#%.=#J4/H9:G`WWZ5]XN6/^8H>W^Z.\^KN4IH5^K^"?78Z0)1,$1K:1UR2)N9L4& +M3V40_]:SK_8;-@F&%)[-$,<+(Y;`6IWMLW)[VCVQDQN"SZ34PX\R+3Y^5Q;;A\,L+KJY)GEQ0<(O#Z/=M"^6 +M.PG51+$93:DX&'UWJAAL`UB$CK666J##&A%>]<7S0?J<"5X(!7]*O8;^\`:2,5'/P@JA0Y&8E!UGJ>'2A7"!'$6IP3=X&EQ5[Q +MGS[G*0KCIUS'OC*$_:$-.$!,+#8<^,837M@7X5!G2)F.6S_`$K_N6%=RM/!EKL,Q=NI[B=Y9'ATZ(?.C/B."K_@PT!/O6_B`J,8\O@`O*9!5)I1ZH?BI[ +M\S:/.(BC,FBO^'N#6-5$@R#(SE27'M2>E(;/_N]+"\=^*2J4"N5K-]:#N]MJ +M=07\3]X'_`]T0CAGR;=!#?>8D1CW$HEAI;4%T;"$LBA=`&IJ +M,]P%JF>%E%8$]OHY"91#+>_85!XL0VD"S[FO^1&T5N@#65$+B)N6[X=]JUY" +M5&TYBS-<.KT+3P/_0@"K\:K%%J@=IJAWY_=?>L%X]R?-#`!W)WYCX5$@9II8 +M_`N+[$`2_R=.:@]6NC#93?YM7G&Z*@I1>4O85T>]74I0X.\^#@(1?93KQQ65 +M%F33U(+(CC^I-LD^3I#ADO4O?!C^U05[DE]G/Q4CX')IUS((E;>C[:&XV\X& +MJNOJ\HL1+K:;7R?SC,`%#?E-]!^*S;AOZ5T`:]?YOY:/B<^!G-DY"ZI![K@HE)(T8NWIT5'YIQ!-G!1`PTH6Q:V9GX6BZ8U7T,H&H>X'(G_9GX"#12>@!3XB_=DJ^Q*'[4CY^=71!&^ +M[>43M&@8D'6^X@1?TRPFTOL@.+.TZ&VXN^-[@F8"JB/8Y7ZI*3!"'BML3BY2 +M!.?T2IYKU)0Y#4*W*\#X",_ZN]%=7BOO=L)JMBQ]:`V^9+LZV-Z-`*ZBGW:W +M@234C`"EL+_CV6N5VL6UWVGK8.S:GT&WO&<5%;JZR.0%G"])=1G0ELG +M[@^[8L\<-JI@IZ>*D.#$Y-*1Q'5:IL=]D\VRT#+T9-9PNU'67MSI)*5$1TO^ +M"DY5#;_2*)*K<*QHT+]6?']N0I5/7=2?=U-\>:P*SM327^!RWZWPM&34.J+: +MR]?-0,6Q#WH]?\I8QI#J:U\$*YK'Q(=W7SX>%!A]WTV^+OOKZ#MJ +MI8:9J13-ET:*HU-Q0R/[;T.@?"9(QG&6#[\7\41=O'@_F^,45'Y%]*LU3^VX`WS6$:-HJ421V"G];TI6%;D +MPF,V]-U=$S5'U&G@:H_?`7#5WAGRQ@,`^/F!"/>`91Q'L[1U6.U.90F7U2-= +MYP4(I&0TE-B`CP]V!>KANPZI5BG5.V&(=G[2\\Q3QQ8`I6OR%K_V`DV\H'6` +M^\CG\.FK[W&TOJ2$\BD1%FR27HRX:I.^-XL[+P=:IS/3#.3JQ%P$5M==MW,O +M'L\H_/=[H7`0N`W`D\FB0\'Q#3ESCHCT5N5Q#"FB;Q'RU0P4L<%LE_>75<+4 +M.XJ]V[E;CNDQ!LO!HE6:2,7)BZM7A+#;A=&O+"MAF7RM,$,]+?*=5NX)0X+7_$"Z=UPV8U:` +M)?NCG!D@>^VOK_@E#K&/?UMK1ORIYP0LD5+6S*,9Y++OP]4$XM*LA1],C,=_ +MTMJ;ELC26V$^_+H9:!&LA_W$5NGK`\L:/HWUP.>U:/8Q2_7M"Z3&ZO)KM6(-Y_.Q<;!Z9^B`B08`S:L$I-C.,\8 +MK)IN&ARZ`Y]N5_ASM]!N4U1AFO!3T&A(C\;-&=RX(P:7TV>DX03=@$:\'"8* +M&XRE_Q5"L=XD4@^$7N3TA#1]B9@?+SC:DB\R'-B,#'!:1(D?5;`^E[,4YA,Z +M-F`(QHZ[:6O,+FL;56U.6(M*U7E;F)+Z[<3"#(OZOXW7+*^[#?;=BA)_Q[OY +M3.A9VAM="7%\'5>-KO2.]6E"\\Z8S*4`T`/^*M2WC_N.W7Q5U**X4!8,Z6Q7 +M!OUYP)Q$U"['G_931UL>ME=*L=C9CDWA4\R2JYF^P%QT]-@Q2>M6X]JQEHYI +M3,C`H:2$5V;+&Z\M9ZE@Y0-VK2V)?CQ5E'MO8PLJG$VC@-H)I]E4$+0--0[7\_G`W4@ +M;A?!,>2\.T*7LG_EQ>7<#A"(!]*6'4:BW[OBL`+=V5C2[L)#P9*,LIXSI/?L +M./_W/TIKQ18)Q0F#%92,+L]7$M\W("]ZBX,_60"Z!_T@?%I.26'X&@"Q0L6? +M1UQV0 +M4F15]K=<(CRQJ@^`W'64JP1=?W=FOSBD(H78*4[E*R'B1O+!>488U'B\RD"J +M^0OY'S5[103W0D^$28BH]B"67P#H?RQSE#G^<4Q/6/%S@>TUN.%CLV8`(>!J +MK;!?:-G@M13JUVR;)KA!M7$A($D&MMO.@YF1L\TS>5WR#8N9_3EJ.F.$'!7( +M>FM,XM,=#Z;[LI^S06]-Z_[--:/==EX9XP09*4\V71BO^C[,S%@6H`/JI=F: +M;%E\WCZTCIG;I9XHY0"#+B:7P(?;QE%4J=[/+.X\J9_7)K:2HZI@+_B^0'@Q +M:^`BP!I]',A:C+'29\&&>J$U6?5":%X'#:YN=[HCY&O$A`9(6AA7=UG!8HSN +M`#-&:WB>-6%D=TJP$)QU!I0@@R#&A>;G:AUFI=A`T=>`N[CT+B@YMY`H=+&8 +M'WJ?A5)>NHH`2`&XHRF^L=Q]A+994(%WH@I&["G_FKPR<<^:=N3+GZJN2Y:D +M6QJ0$TFU4PAZ'^@MFGP4"__2_\GVR\)2>R6:]26";R;Q%[?+?3F,`]QTA5.? +M&@G\5#EL`&GS71.JX;Z.H>_B$#6G]PK5IU7PB"E))92*4.J09#%8RR1U_T_P +M<2\1I%I/AXC:T/-O5?K1S!<3V*6WBR[P<$N9T#3Z+;P!P8".M'G5A]333\TZ +M^*DSCIC0J!K>EF:QTS62`6$V6/5K&#JD8!YP'K%0_%"KVD=T\4TF)LY!ZIE3 +MR`>OHO2<[17H.$YF*O.FAY5SQ[YW'G&RPT!'N=T?A8CO!]XQK!\2[E'=[V-4 +M]W$UIF`IX*%X(!Z'L7"Y!+%OT0-7SLSRUAQ1Z(D& +ME#<S`?3-GP.)N%#!V%)O"5[(E90XL0++_,!8J.=HZGE]>TF +M;DI"]AP?*HBW"E%TF@Y>1O%11?&V]M^A)\EAN2SXVJ#>IM7@[+T+XUWI'K=8J+-F;5WBP#Q +M_6*'J[C^8\&_P"0\W#OCK/-ZN@/TT3'!=?3NHZ\/ +M6BAD#$\=315VK$Z+H128SBHVN\/2:K_GTA:$NBXH'T%UX>+#3Y#9!N7.R-E( +M<9._H43?H$X)=ANM)(=EE,HVM5#1Q6&?J +M-)K&"(YHEY'5V?D>,QZ>1I3PD44B-GGRJMNHCL?,ZCBAWL_28_]X.LS;VI/Y +MW/6MN,[.+2.E./JMBC$OKT!5(KT,^6/=JY8F,?A7)Q_[`ISJ&^2T7.-N=_]- +MTD/=?I9Q9I7AI,$_\!$ZGL29U8'O`./P@Z9F\CX2R8P,#DTP`2.[JWH#!M@>5R* +MR:T\H3Q,%">5VD;>WRU^9$,!5OP+$&%7F^_TN+(2DC&P2%\(>OBC[^!?JM+D +M$;.M0B=CCK)6BQ2,U!['M95`BZIJZ>PN4X=X&@2`:S[F;K>G>T!3T6):W[F? +M<`,0,@0H<;`_`^33-::5H6[:4)(GE0IV(-[O^ZPQSW2%RPZS5/"N[DYP(*&S +MZV/-Z2@'JV)%LM;02BG23C?XOGOP$`B)\L*TZ]3-.>W$!^;81_<\<_Y-&GIA +M$B)BNE+%N?TR-IO7ER)UAJ,'Q35^<3+D[B'=RK[=)-O#C?R9*AK+Z"3"'+M, +M]DQS]`=JX.X4A;'PXL\C/6:$0680HDOG+>ZK:0,YU'Q-GYE.?.8*.6^WQ]M: +MW,`CK8\&$2V?>!EHNC5Q0'-VQP+7M,:50T\&;&%[T8DW@U.`]$B,)9-IGIF& +MO.\D5;'BSI+'^H,FOEZ+6BI#T;=;0P[!]Z=N"@KKVUN&XN51ZDCHT;)TCOO&Y^(;H: +ML*6CQ()K#=J2])7D9+UZ3\:7RMC\2(4UYG44:K_\E34$F@^'JBM,K``Y43'= +MR+.3YN`TJ:2!E./QO.:5SF4/"]&+#&2MVZ+\4'YP>U0Z2BP5YOE7N& +M+)OQ@^!HLWM8_5LE;5DTR0VY&,'7"+S3>\;F%$^5O=EGH$/%5:%(.U%!VO+I +MG!W1M8UU'1#>F7(<*!>UD[?%/&'QI$;L!ENIK,YJ,3=URZ\&CJR(98,9"(3& +MIU(RP:R(\(-DDPYJU9,8K9I1W)$)R':'\2J?M2L<+'#W)^6GR>/[9*O-3R-= +M,T`9I9+(#)$2^\`7^9=@*NT.5R(QYXL+JT9I5;0P5$:T>T#CEJ*#)5`:8/&4 +MKPI"%ROH%>35WZ/4>\E2H[^_%0:WLT^FPO!*!C,AK5TIC0%*OMQ>=X>[OXJ*KRX.< +M>7D5X%$3S9G(JX0@-C`F!0'ONLQ&&\R^SKVIS;9UGO%K'3:3K9:13>N=?(V@ +M1G[3G-++(MX.T8W"'PMN_,77A,Y]9$4R/OJ3IS&H'9%WNH#&>SW+M](X-9'A +MWAN'H+)+>T/W_.G04;B'#6\(>YG(IUZ#]RK:AH^XE8V]]]R"4"$U'G:@'\*_ +MM717`TI>[CO)`V;7LF7ZGH=2W@*JWQM]2)FR(CA">,>7KUQR0?(V6$BRJ"OA +MHOTDW%CQG[[UK%Z8<3N66?]3.>*>F9`O[CI[/,EPOY,5I%L^7$`02G,UH!>! +MZ.1`N:>61-`;^'.^W%W95WR3CMN]KZR`T7-2LLI^Y0HHK@<]9344"AR!T`"D +MT7W2P@7D`YPI^JWT)U/JMYQA#'6&6FZL^V;$Q$UV\%RR*^FG"'V>$>*Y:!GL +M9.OW6T"DZ,D\7YY:3GZE!8B_14)QU=I'&_DM8N3,)@7DFG_ +M1#8>1SP8KRZE9<4-(ZBM?\'/^^T0?)DF6,0&*D@-P(;^SH324S%07VS/2L!G +MVYA<.`$RJ.%04:=/\Z;H:)V.H[+1(0^H&?OFW)/SX/6[<%PLL09DC./KQTK6]L[DN3"55:E%F6R? +M#,L)P1!DJ@H%,DQ>HQ*?3FEM1SBL??*S3C2\K$^X*B"I*UK3KTVB*YX_"%." +M@)?-LPK4[2CDD>Q-/[??U5_UZ"$Y/%L?Z+[1%6B*\6\@9LD9ZEP +MUK?]#MJ]>#3QSIF_ZO=)O +M[VPC05I9<>SO/B)5&07GL7D)KB7JDEH9LSKUTB>S9<(I(_Z<%DMJQ)!0-I8Y +MH-KS='+<*:Q7&_V'I>Q>V7@1JE?FV;-SLL=-DH'ER.']5?3?ZE[O8V.V.@JQ +MA/%]GH7._O9E>&`&)H\AO+6O]D@@B?.,7<1W;%"R"Z5Q'##$[* +M4EZ!BEU5B;HP;NQ)/3_,>(0%8H>>@(3]N2%QZ5%;JHE%[ +MFSHPY#GI9TB^T]+R%UL)H1X3J2GQ<# +MSE$8-2!>^H8UN&IY!`'W*P:NVR:1&P==4"S^M^WM(&\2ZQ%$J>>_V0G>3D6! +MFB+8MAYW%29[SR`[(R6*S) +MGR^Y;J]5Q`41R.N&"!@B]NJOM1+`)CVA.3E&&1TD]$<#U^:/1P?`41,40!0A +M[GO3)V&,\17_$Z+@318Q$QU>'3\>@+%[=EVHJM-^D;X^+7+;@9Y(C"`G[LBO +M+06#_=XG!RE%H'#.<+LO&&`%H8LX`:X2EB)TQ&`:;8%PGN!0ESP],A<'$D@JCAY`FP581 +MK\]-`,G +M)"N?O3,?$.@QU6>BB\WE,QC_A%NV"0KPFRZ',<0.2X9^F:\X> +M]7T6F]!Q3\$S+J0HQS#N-"&]!8>X6,2YL;N.Y;WQ>QL7?GV&5)^R3% +ML8T20II;SZ&9$4BH>Y]OW[W0#HJO1(26+6VZ>AQ5AU8=!(KWU63':Y_='3R +M\TE;U`GZ=G?_:=QFIR:84/:4V6FR*)G[]$.D7]+N)K+"(:6!PL,5FBX]!L%_N\6G\"CD-1T"R^#;\0I,<,RW`L]@9 +M/AP70LNS\GF+/.K!N;_@`%V':[UP]8R(8_A@F.[4?0$'[RO!"AB'"JC?7. +M$:D73-Z)_Y^@((Z[XCB&^.X$P:'S1IG20A1D^P.6@YJG[T3PH@0.T7$KT\:L +M7%6NG%#<;&50`:E76;0DV3B[6UFN-YI0/Z."KG@Q<,WCJ/.LF$.K:27T.?`W +ML?4DF]\`Z#@;%WZF;,$)]$9)VZ2/BQ3/`V_0V!V:YRLUV"D77?HS$=,/.Z[K*M40\.]=APH0I)\4="`.G]AK>(:S'___ +MVMDJPQH.AC4!4JW72G+62&>V3+YD +MV5DS!S`3GUB3P$'"=0*-V",^9*-Z'BUE*^&;,T#HW/0B/Y)3;7B5`M''E^7U +M`C&T)R^$YG+0YY+F>$ZE"V.&E<(W*WX=1FB47[O(:QLSD(B$:ZAY.+,R_;>W +MTN^416*US*%"UGJ1-N^=0<7XP,O6KUWJA+*^C#_Z=*KS1`->1@NP_@`4_XTM +M-54T[9A>$(8I),470/7F"VI1O'7.C/RFZT+&7+5NNHVYRRTA$D*ZV.C*$:AV;^\9JQR+?!"MB,AMI(, +M'-XJ,KTT]R',ORZ$35?@ZE(\:3>I1B*;+[=:I<&8%EWRFAF)3C%*QW`!*ZU> +M$B=K)Z,9UU)A6XG>:ENMH'3"4*0W99A,_Z5"UCL5?ZT*.5LG;+B[RBW`@!>V'DK"^-Q>CU6J9`TN%QCET.M"[`3I\_HS8/4J +MQG8BQ&N^8L9-LSV[Q!>C<3O%T_);Q^S/";GKRY,-->_XH($0,2YJ4%N;H^Z_ +M&WYXU696HGD@,=0<5*QH?F>9GM'*5VO]0"B9BSR2+[)+$V-FXL4%IK^@O34G +M30GBR7&%D"'5.A+\G$Y8'I]R;C++/V`/A/B65H[>YIV%[2JN9^=_1T!4X(&` +M',7Q_4$?'Q`,!=;599^/23EUAML'2)XI06CI$C:<^N__+BL2DYPD`JUP`?>B +M<&JD$)[#"YPRLH8,1+WE^T0E'K1+Y9&EC]1/=3TRB,X^6\"?80AHM&?%'=1& +MOC^#-G5(EFR\A_$0; +M(/3P<).2=-N)&JN-2#'-?`E`76[VM;*;CPJV)?SDV;\=V[*92R\0"-G9=_"6 +M!$Q\E+0*7TQ\NWIF9+MR!!B!Q3'.51\K(RY1D:\&.U#>N8\U3"Z)<<2`&3BS3?]1C,(&^%.5<%"?"3=N_'-O`N7 +M(FI?&C/MDF'D?10E$B0NMI'<3*6DO/OD$I/RH@>XX,F2G#0E#54=,$3`^6\E +MVN*JH^!O5U&(.W0_3%)$&L%M:0#>I%)HXO":XOL.QD!K9Q)_)#>8*S@2)1$' +M6F.@U&"+1>3R@GS<7RU$('32!=*"SM;'J+5C^ADKK4<]"`"W-F1$@2%TP7FP +M4P3KY8<-N7+K>C>^`I09J7-1AYMUD7=I4OX^`X][CWAMGAMG"P85F>@@JG^I +M8S+K.,)XZ,-^B2RXUDMSZ?DLI3K\)=QXNE%QYS&+4.J`=>">'Z[8(9QW6\F< +MVO%J15UNH#/C#0(U2$3"7WYAJQ=;@,M1UI?IZ4D[Y7&>D1#PPZ.UP?H1BFK/ +MS/VZ8UBP6C\:Y@'N;;K86%%4"="-0==UN>DAQZFEG%0?9S4T`-JEGLB*+$W: +M+==:"J4_IH,YJ@??9^ZFWQ0//3BK+8%PO<.RY8%3LE6;!6TGB1,N5C*[5`\. +M6(,=5LJB.A#J!#K^1-FM\_<%G/,+85K4Z;8LE;KQ6<>'8`OLO,B[=C0?A69C +M^>^=H*SM[=`H[HCD!P%,BFQ24NM6:S`B=M3]\$X(2 +M`?0[@@(9,3'0&Y@1PT%2!^/QZF)FKE4C/J&H^DH>6C7F<)EO2@E_1HF'=F\$ +MO$5+UB-8'3L2DE?FI88[+JLG:<&16PI]XG=L_V^L<+[!X2PHI7=YW/P]$N?7 +M5,]1&LYY\WZF)O7'\;>.JNX@BU,/>#P5`$VO2TSJ%-J-&*V&WK\\WQ']D275 +MC,;L=`%&_Z_&WWZV_`M"MB%1LW8<;2EX1/3K"((N#,5^`&18C/MT2LAL2BM4 +MSOCU2M6)E(?23JX:*QTE4-IT%:TKPT-CC].$3#HS,?!\R@4VQ.).\#><1`@S +M!JF_A/8.W29I'>3^=U_R+J]:%TF(#8IE6W3D_MEH_'?Q'6BCE=(7O'^U5ZLM +MGP8]")VE=;T?A]=W$1NMMLU'C`^R2MU^7!QQ\U4[(TJ6RP3LDK()(?H=I.KK +M)DZLTR])P80)%,$]%3J1'TUE&A?)'CY@`W*2<%?JE:9\:TX-U9UJX:4;+,(9 +MBRES"MJ;E$NPJ=DX=,3O@EH37ATD\%F!*&&^R,GB?V+P!-TKQ>VM8F5YL[O! +M_JI]2(^[G*#"20,O+08J!*3C*1*@:/M#XBYX)Y1='HP%@'WK9>1TD&X@ +MW:2"`2$GE]674I_*FJ9&;,VBX]F6]<,W[9L&ZL;P_[@MCIS0/KFET3O&WT/0 +M?MY@(V.!L3I.N]N/,4P]#Z!$^S2EZH&$+^R9+3T+#-XXT;,8.*4RG)/Q2J\* +M8QL&,O9==M_,!3Q-2\76H/9WSR_^;,%6F36<_=0@==PS'0#C>XW"GU^F1/0]?X +MC$?CGP25IYPBUI&=4!#?;5=/T;6>5DS@M5N"?B%G!DT1)X[+\^%6`7]�_@ +M`(<-HITQ.U%=A-H9P>9AQ`OPG/%MF'1Y7R'II7#`4+,)8H-=4!Q`8>9(S.0+ +M>*%.!K&I*>9NJV%O#F&B<0D7+_]X0I/D)R'"XEF(?T1W_F-(T4N-)2H[=X(: +MCMR`/5\IB><=>[S.B9>;`QOD$I@E9(FI:N[R*JMI@OP!X+P/;E)\P2GY3/;J5'Y_0N10Y^LV>[S`%[C@?2>*S)J!5&8FWE\T=]Y/G:=\"&Z=S +M\9X9!.N9VK]<@C;Q-,(QY-DU]-.28(E-BM]S\YMW;-:+3@+"0.3*,VJG+&VD +M^9:O5&@O6"XF7[PH9J(YJ%=6&,-9,NA'%#F^MUB1#)Z37UR8IBK +MP'3#;L]H"'\UZ&AI(SGWQ!O;Z$8(4")D,L?]N.'E>IO:4`J&LM\D\LIC^ZFE +M8-8>2RL8:K)=2`H9O=]X+)P>.'PZLS&[5^MP7#IP#/;B_WNY[T`^U>(`@X^_ +MFP)X]IO&0#,_F[%"":G!>(\$1RZ5GW0QT^?&UU/NA\'87#5EAGOX3X=@\5+/ +MYE6HA(0#-FH::6EO]WNRV<7P)UN4]VP-&C&L!'T,I\'=([8UYGSKKS\!M\20 +MH,*[X(O?VYH+T8W>M0Q4F!S+PG"VM(87]-[92`PQY2!Z-5UH5/J&T"K$MT8= +M6!:MKV"F^]4IAJ1(+S[$.$2_1W>"[U(=L*DCS$A05S?QMG+BGL$J41B1NI\& +M_"\5,P$=&((`>QYJI?"S@4Y_J[&(*4=NIIOCN^9"MJ.-VO^OW0U>^Q5@J,OE +M6E>%-#]?0YCL!`JH7O2S=1CE4LFUEB6%U3R8A.J5)JJ[\4X6!_B<^;-'BL7_ +MK]EC:Z'VXF`6,J7H#:%#6]:\=G]T*(@J?\!62P]J9P!5]EETU`%@J`0X61[[ +MU[;9?-Y4HO&SBT_1U1/,(]4,'A*$&A4L09$^7[UBL\`6N51\%]6\0)&>H!GN +MZMSQFQ[)I)%A&96V9,@H3%Q!)C,?TZ`'>^5-".^)A,,I6_(VQ'`]+"?J+X<* +MS/G'Y8E?XJPK5T8!)J4[K<6(:PI?=9V-7P!46,&7HT>W/$,,F:-]C"[.M3)2 +M>,^Q!+VO!IO"FFL4Z-]0M):EU4S`CP/]"S15I6/LN8"33'KK\/:]'/!(Q+OL +M6YRU;KUD,74.0\7W$<6R(KK0KJ +M_.OTTWP']-?6'>SV/#,$<:2H2_C8?,>Q<]DWSXUF5'>,CUY:OH"3A(Y<Q& +M+,N;*$8["4=QX+XM\J9*%7?@$<10.EC739J.1[&Z=9149SELHEF@WO5O>E7W +M*O7M28DJ/*OV2CFCV&E^E*O!U3>NN/OS+^B'./:!D'1TBA>B(WJ'(![9^T4: +M@B+8"""JS1]H`QL2-VUO7,:WW^:SMK$'2)E]*R"ZX;W*K5(4E)]5B%A&*&,A +M0CR^=9-7*#'G(FYEV%&C3$0EXEJ-I@?#`PYN6K..O7:"TTG_)U]O_^R7$L`L +MK9%[\I%S^45"M7!CX"SEN[*;N8&.AH:W2+R'5=K9R[WK'LGPDI:P!$-D?.`6 +M&^+J75TFGOHA/[@LQ,*F8]>\/>Z3]ONPU'2$?#:SIMTV[CK*;Y;.'%SMU)W\ +MFZ9]`:?C-&VP+QRD]+!SM0"O[Y#L1#;A`*"D/3K$UN;>?N:4$ULQ_5'?A+J> +MR_6Q>HYA729_5:E>7W#P"*Y0BRMJ051BN>GYZ9E:;D&],[/:V-C9A6LN#<@F +MII=DY==-[?"(6'(#ZT8A&%,]V] +M^VMGHKI?6>1E]^C*X:;?8I6%G=Y@%?/( +M-R41X^"20S;Y`&.6B&'`O$2_+?V0LYC/AXG1Y5W'P\\"4I=.OL63'?F)3CY4 +M2V!D#`FW)AQ+,4P8?5&2!-R(OR1D:"/_TT,+<9^,"&4810+KE6+FE-V"\N[Q +MMC<3_U9J(I9$G_"Y.>&=00'M,IH#Q0VXVQH':P;6"I^XDZ/G<),QI4_**/Y0 +M9(Z9LIS5]2.$XF"*X;=.1UX?_3*U\!J/81%ODLYL@?X5=_1.3PBG/JSNH5R. +MTF+LL?IFM#9YNU'D1$`,X$E#V%+=L)WUJB5K&D6&7QW%FVK\SF#TC +M^2:WNC_^OMH++\F;:P)FO;_(O`0>])7"4WA@$EL[UE;,5U** +MA2A\^*7OKW@.E/6?6>,0RH@U"FA?47\]DN(9#P$4A^B)3D)[#SH\%ZK!2]S$ +MW^/*.2[AZM<3I:7]'5LQEY8>A&DC]BK'2DH_,90&MQAM3&46VCX()XYO[6"B +MB6G_O"S=D;T@4=R4=C(ZI/#Y9@FE#!9Z+W*!7$+D0-71[9V&8`FI2;!Z)=K3 +MN&ID?LFUL/H7L&@>MY$N]FEZF@&/'"MX75TE4QCYMF71CA1@4&73?4V47=^4 +MJX8P>0TF(+1#16AE9#I/)8?\Q][)Z$PPWW_+=]1A'J]1'-MV! +M=Q8'0#,.GY=$5)(,_)8/;PM7$>@7146`@]]V+]P6NI%"HHQ$`]PH"L`XDDZEG^!&_$2"R/^[\C2EJ'?`[TO8<^MGSSCJ7_/H'#]!GTH +ME\#;HAAEX3]1/XAR#I0E+R";#CK9$U[2.#UKN1MWMDAMI0;VK)FTY>?:RA_O +M=(;4M[C-2[>MX>7KE^$W"ELHIST$22#&+[HH-,H870J<"5<[AQ]5*BIOA($;'%?[6XGD8^X,LH#A7>07QD,PY*AF*>$ +MG!<;'(\QI4-3IB`F48V_EOTG(>PE^2?CKTM$E'#F#'_3MR7631(/\WR5_I?. +M4_'B:E(A!$:%[@BS+_H9Q/"OE&-#[??GZR0@_:P9N*F-;-7*Q<0FHJ;'.UT1 +M5".+@H!%T'UFBR5E?JY-1G28\BRH_I^>;+6.(LKVP)/JB?6OG@Y9>%T?,-0S +M^T0U1O--,V15VB&;U`9L\Z_?6)N15,'YZ-Y'&(1'BSEV;*4U%I=$=RGXIZ=1 +MED"B`OI0ME&?O7XK-0Z=H'Z%+E7W#*F]LH.AU7JGW@NUF-QS)X,?YQ9E"&2V +MGD>+\\!NU4T.HPV@D?TG2![7&O5D>K`Q:7X!!XYG[F7_&7>@$X +M4RB6"R@9F:QR(__9:J?3>I/9@\BKITEI2;,Q9&\A,2V"EPJ$(^,"3!E^*=R! +MB.V]/Q?O(B#_LK`H8L-W@!"R]P#H"S1TK.$I((B'!HY7HW9L(T/Z3S%<6CN= +M6$K:>-82/*['@2@KXR(10J=Z:RNN4$L#!#,``0!C`(RP#D4`````+B8``*UR```$``L`3D574P&9!P`" +M`$%%`PP`O+MA&GN63K,ED&Z5"B;"E=_]*#J*:B:.>O.IC!<,`V89N#"I$PQ' +M''MTYV#M=K^C?Z/-K#(*D1`JH\E%A;_\J:D1,I)B%A489*D9+P5$-=85E>QW +M7'A('PW(#8BMOV85>_7EJ`QE,RE+E/WU",[,/W0-/%1:I\-*]Z_V#E@LQIL9 +MT1!&3XQC5JB"SM"A7X=/`%;C$!F"((P<_9-P7H#WI?MFES5_/Z_[/:L21A=* +MYY`T)AZN,PP"(I6\(A>>L&]$`6YF&!%?O0XG69'-O?;%.L>=S(?MX#^Q"5(- +MN%K96L9USL!H,=VCM`&/)M`7MNC?7$(?!5B^!0^XII(;<:U@I;_I?)E +M2:EY8F[ZZK0B5ZF0:\CS%\=:BYMM*IRLAM@#W(?SBK;0Q$@"WQ_M_93+KCJ'"L=2A>]B$*(^9U4)@[EZ"S\TE6%3MD^A]53];#/$'%E +MG>G2I6BQ4Y5#[+1.&B+R\K/-"">"_?)U''VLFY\"!([G,J:`%AA^4]-P/KI] +M4!BR$:=>$?'[GD^VL<&Y4FBW7XD)#`M"VY[9S#]T%-LF,B(97:5UC4,0]GS#'SS +M[T>X>)![)V2N*S>ZMR7K\H]ZEI$C..!](5GYXW2M=QA?&P1RF;XD[FD-A>Q< +MVW*=\=WUS,2?:_KG:-&.`\)TW!=++GS&I_[X."HZ%=E08+PBF@ZEPS(/C6S_ +MN03#<&[!@1%,D;\(G%#BH?'598TU6LUGQ=]@9`7C&,RHQZ)"^!#1EI"4]_0" +MY"J\J7)5^Y::Q6#J>"$ZNS]P*7=?]@A8[=V:8VOA_]<<,;Y2L.F$-PH=4S+Z +M*[_OPQF%''B/,;&W%EA.OX"S'/_:K+&U19OXT2C-G>4656`XP@(D$P4UB<*:9P(:^3A8M_I6A/.9?4^.]4KF7C41Y_%KVMJH +M?.@N@$C#E3;6[KRRN[Y(Z64D&#U\[N'%CF8*YC>O^)'8H4,GYY:ABZ*2WRKG +M7\0]CXF0YD7:MXMI+B5CV1GYHK^> +M];7=RZ'=_5WN7)JZ$HU>U/K).(FDDA;_T/#/K4JC;SF8I&]GYP&>P03FTR#L.E4[0D4WR-I5,QK'9AO.53C[A +MK#G7\+9<>82<.E$N/^2@/TL`QAO66C,?*MN]-(Q6%C\JF^ZZ0+?WA8(W&&+M +M>["VGR#64^D?M8KKHRMO2G0+;(1S);&O#9O-`M$VED\HVJ@KY]);_IS"D^-% +M0(B@C-D(^L(+U`$),U'DHYCFM[.K']0(-8$X3]=A*%_-`B:TBO+SID!,IS"4 +M;9)X(K+UVG%T#O>(`X_:\47C$HE(M#<-Y(=PO4 +ML^6IR\*$/U?`A)[227X'Q:2J\W6J%X\<(XDQ`.B.64N(Z;RN0O+?,+';1!]7 +MD_4!P:Z;,6!;];/.@X'HS5I/3+'MR9AG>,TF!)9%7#TLO1`2*9^B*3::J59\ +M^W5(KRO(;;T[<4>^(PB66[^;`Z=^*::CLQKRI7[I#!^WXWH6R1V4+D0\ +MFR$N(_1_F(W=TZ\-TZS%[Q,C%ONI\W^C?]N +M>^\36IHT0`^>6EF$\,!$(>'>2K3JH*,Y)ZNME`PZ +M<2%E)D7$.0M87EUY>%2KBAV]\)/K';9/KEN'2;!8KNL.:T(?48OGF&"!$.(>\X-\DS@3 +M4D^GUHZ5;@VX\+%["U#3$Q.S^!>G$/[`.0D=#'Y/!>L[S5(`VQ]1-K?&C:'RP@PQ4@VK`U5@P3= +MU1^4!_6Y_..N)K%QF8KFNK:>6A<'V.246R\(/0PKYS'"#,A(S6+D5T1*AHK' +MI3W&4^\?064GX*?.P%>2@[0-R,@/G9_/PH-/` +M%EB%R2N[Z>!ZB<8AXMLV3'G>[+M_?JU_9U<*V0V=2G*DN8)/H$9!,=>G47^Z +M7%]K`:*G/KT.DI48I52]SLGL/%ZU5%+C6$>(RR@H\\M[UQRQ#*3:!*.$OY,D +M#=2L0CW)26Y]W-^5#S"[-+4.N=?W`VI6W#%Y6>N^S'A(:KD]?NJ`50" +M>X3+0T89B:LU2'9[2Q6L?>&XEV4^FH5FK8T(F<%7PLIK*7YOJW-Y\YUE*X)T+)3^R3A+/+G*VA`,/E< +M>HK#@*ET85CX6;^@%Z6OA[L?%HY4WE,8/U2C70*7?` +M4W#KH+J]2O'HBH'C[4%:S^F/=0879R])$Y1H/.$6'\_UM8&+.\L2=*%H0$]J +MCP%1Q2&LI>FRT$?7!,I[KX\0!ULW7U9D*00Y/P2*)!=,Q<#KO41KEX\QX9Y` +M!?G:"Y_<-2;P65&="]FCFD;:&0W40()OZXF42@'-UC=W5YA_1!GL+#S[\Y\Q +M-UUM&[[*N/>AH@4E-[?-02@8\Y]*JA%G+AQ!J&._MB"DIPY2*%]VY!$<&9'X%)Z9[[WB2$7X.O>UVL* +MHA!JEUE>]'%B&04,G`41-X!@5&\-]U097<:--R-`B?+-%%0RT;I-3$0J&H_K +M+J^F]I`8?(8(>P;7AWFUP2Q+W&6`T3*7MFTMJ2D(WZPJV\9Y']\1T&F21+6KWKZ<^S$Q7./S@=.=/X&"^O&$[D!^(_`7[9CHI"$%%;_AZ/> +MP2>2JQ^JKZT1/0I%3K, +M!""HX(P_44Z=7LF*KY;Q97<'GQ,J\DV?<[I'53^RO'*L;:Z?OL_'+=68%Q)2 +M8P3"%('[NJO@IST.L.O?!RC&*NLF40>[?QH53N?!&:$*[^)+Q+)[5%%Z\*C"ED5VQD2*Y-,[P]=I!-K,M9WU,M%:.I +M;_]B+U(@?+FP/CA](6T5^Z9V003IHY\513H"H(TO6L39/P-"-C2+O0/MN#7P +MEU%QR--M1H>?WN!2M]VI8$\VZ*M*,-*Y.Z5C0@M_9>B^!<45JJ&`PBI'#M2# +MI(5Z^Z?7>*(XV?M8BY+QJ:W"RW-J/KU#X98'9;7:Q6#6IT8H2J^8,#M:X"7B43'.1_`$9-W"IS3"'PK\BTXIRP=T82M3DSN4=CQ$+D8'HV_1U_CV?. +MB'>%A'?&>:)T*_L`E$DVU;:`(R`U,ICWA.Q1.6T\]]Q=2E.-L/N#%J,P@CA[ +M@,YKDP\QM01QIOY_X/[NL`$LMH^&E`H'?.K,0F8W\J!"3TUNJMQ",008+XUE +MM;M;(MC4IW&QE'\?)6=@!ZUW#YZ)LI3`$@1L9&.WWOH@K"KE8P2PJ`A2^PHB +M&QE,:[5>M9((1-53H/V[-D>):ZHPN$`9KS',Y#!?\JBSK)K8<4`/1TXRMH=0 +MBSEG8M([7U4WD:A<9L$>[86JMJD2/4P5%X[D7RLB2OB*Q4?`:E.C<].WUM;L +M%HBO;#O::"T!CWT[KKY+&ES?#F//<=(+"3FN>CK2Q#>RI?_>A(]MJ+)SE^Y_A<="HJO3C[\?8#,U_!R?F[ +ML>S"^=.%N:PQ8N6-%'Y+'9F0TW0\O;HC&)<81?.4E:7FF+<6XY71.8.X89+' +MK>OG\;^5W(Q;1@F3H-OT9O-TWLYH*?T='`:NZ0@6"[LYN-:<%P0E0`Y4@3]: +MO17QKT1,*5;M37]#+Z][\CUN:LZNEB[#250XD,78]>SP&9"3A)77ZH\X]>X[ +MA&6(&?C'W9.N+@J`VQ_O937^H`MM2*G=8PB$JR\],ANZE5?/3G0+K]R=T5?` +MQ(VO)RB':R=T!8U5TGS>^,N0,=$LXQ;:9`_:+G:17'3QQ33X(-<],\CE8M1D +M"4"@G!5OA^6F9[%EDYN3,T[PX*7[: +M3&NM$_CO208N=B.X,SN#Q7>%JG:UZUZ%N,/+D_IVZX8`8S_0,L^'M>)4RRR7 +ML9'((S*%"A*GL<*!I]U5?2`,!)X[L58_-TV1FRB-'EB[ROFX\/MW'(I1%M@@ +M32Q(*7:!+/")I)B>"SZONUDCX,WL-\:I,1G5BJL>(S?T^0LY%9\H*A":FLV/ +MLKU]U\ZMMD7@>G^G+5V1;P!+Q-UYX@$EQ3';AW"3\#B,F&Z,BS54WEH7*`^` +M#H7$T@Y8`;N;%&CR`-9*%FY.YDQDU>3>IJ6;3U`)V'?S9]WU.7%-6R69^0(F +MB02R6%FT?&D+F!&BHWF,+T.T-`!%1@\>+Y8Z1*]8"E^!7\L-YW?653V@]CN" +M-.V^T@#1UFLW<<`+>F):Y1#JE:X91X4XTRGTHR/5)Z*Y"C+J04DL[\'OQ4LJ +M+48-_E"$YHO\\(\G":5LX%I61:PZ%[(-:DD@_@`Y/4RYD/"R8LA$I-("J5W' +M8FQS*]RO1%SH.U97(0I1#B/?17-74LPQ+M,W=&).)MW7:&5$3Y0UXDTX?KR7 +MHV$G>WPIE.YK3M`Q<@_9H`N`J)28DR*CR=X_`+Q<1K")[H\-"8&DZR8<\&\; +M^"E#JOF-,3=Y>7,&\JZ73APW\2>[VZ5;I#;VCI+38G`^&&&W4GV[6>2<.X!^ +M&T!H1,F-EOWE*DVZV\\G=YI&_`*)DX&-M5VF4X"D;07<&=0V!&DZ$55O>!8F +MXCY@)S!L9_/3*K=!T9T4B$(\28N]4`@\)UC?@&B04BUP,U,=5,15Y2U)U/[G +MVR4^:L?H@_H-=GHN?H;N8;%WT/G#9Y<[&A35`('V?&/XZ=Q$?R@04\3JV&PU +M6+SSES@N.^;[9HS&-Q3!$[G:ATR<`]$&RVN_J2F!/IY4A/KOK2,B_6_-B +MG.@ZZ6OX#3G.^&[.5*0"L)Y&9F;0.^[2Y4* +M\S%5]N,IX-Q3$;_&BFXLDWVA-JEM[P[7"?DC&4N](;@%,6W30WJ +MV?_^=HEYS&/WG?GUN^6S3D%FABQXQ@SV)\A&M2]G&Z;+UBV.N\T'%VTM0 +M.H4.18W_YT:^-K4W!.8X%^C<`5!UWT018H!;PYHS7<]DP]B.=1"0]J7G87L@J1LQS'M72?'+LSS>M>)4`9CS#46%5'EIV_0&(9\' +MHP%#]6]U%\V1`TD;-,%=C^#=K[2-BK7L;$L_=8[94@0FR](98:VQ>)`#>)MR +M,K2IM1Y\.!^&_Y>M'X.[1FD'A7KT5^TUE46^<4/]8=A2XU?0Q7A_J-=F'*K) +M>#;H:M]S,(52N>\J^N^DB2'\UD3U2X:'[_AT2M2"6-C^EB.4T[6MU$%%&OP7 +MR\R73/FZ[X\.!5[WI_8:,?X9)ETUU_M-_-P^#GE>;6I=F:)MC+1)MF[)#S*! +MCF/Y+9'I_J_.2=^E6EF>!G69(8`3$&X,RJ1O6U45`I+`DH-=?'E"$].@/C.G +M<$>K^P[C;-4<2S2BE.S5.)OE`M;^SOD`&T['0\<\]73UA1%DGI\(*A?&.$$, +MN)+@_?0B-G4.LW"G]N]DSE$W0$9,22WN4ML\IO9;C"'P[.>`9*<]TI#]T0XR +M'2LQ)1Y.Q9:6]9-9IE=1^H#+S-Y\M<-%P)=D+#V06=3*I`I!)LP6ZT=D!QVY +MO(BYPUS`JS)B8G;UV-,.0IS]+O$ET6'9AY.-[-;YDF'WM04TI;2!GP&Z9;(%(B&6!#B1D^X^\+_%L*"QNWN0[ +MI=>"A4;[6G!XSN]#[6>P-(M=?+`+E<-\V-&@N-Q*FAFW1ACY&[_._LV/#Q>\ +MWY:,!0&17]C-@T +M_IH=J*#>*PZE.8B\1`L9&5HK_:W45VPV(WZ\F=&'0QS!_R2)_JJ8VR:,*(N` +M_DH#WB_O$D?@6%^B=NJ74O[/WT_)U38,YT4.T`I5F68(H3_"`9$;#LJNV7`T+5$+IV[*3*Z@LD-[1J-SR:/K6>Z<9OU)`IRM1"#R' +M`.[E9SDG*5E4/(XE)4M$C-+ZKY.+EWBY?=6,^I*V8P!0*VQ(]BXP/TZ4YVBW +M=K,('^Z%IN--P)C@^-J9DR),/"`Q\3QC'Q#6#'0MUPI@[NT)AI_=K))C5["[ +MMHFO3IW+P=.!&-%_I/%M']G4Q,Y8OX*,)0QUD@@%!/:?V`[W[_@"T;62TS+C +M;G!CO>,6,@PM3^5EC<>PG9?DXI0;J4#AS3L@1ZSZ1N,+HB&_=01C'TTNK923 +M)4$]S[@$LIY4A7F^6_P@+!;T<$DR1_`>&*K=@J;88#/!,!9'=,;+@;#WR@=C +MTY&8A*\/KU"4%P!\VW60]-O]I'&RIDY[&IES4>FQW;R>,J=TQ+V +M=UI7W&0KX^5\')S>U=T;#S?0*X6UY:9``YSL;$1W",8Q`0MWJ2'E(J4-5Q\P +M48:VS<4-U*B.F;E$'SF\1;N*R[1O/M$&V9O`\[VC?@H26=339(4>>.P;E' +M&TA93_T=I)W?:!T^"_,`\J^4/V<_2MQRVX)``+MEI8R(![R+:&)"#%#[2RQ2 +MDE.WH7X;`^N[F6?KP!(K3#Q76JX477<%9[IUME$+Q,T4D?!AZ;L9-#,T;B3' +M'(1#!.?0)>,))S>R7P=$-3N7PX[YQ79XJ/VKN0_VF15^A3MZGXX32%O+YP9O +MFFTJAP;V_,X_N:P4/7DR:8V"&D4)#YV>J'UOH#]_+L^>D]E.8"JN\L^Q6D8(QV9VZ]2#>=[.'?\=PP_.XB%-NW7(4HFCCKFI3BJ'=%DX$[JS\#98>XFN;)JP#3,T2"!*5?YZ,V+7B +M"$-RJ"6(<-467.9;U*L7W5C#A=:NO5&T'L+\RC:*;;-NHDW885C9]D(*P9HU +M;K6?LSI8X">7#,&5>#H1D)_9VE2!= +M_B.C$3",_]^\>E)E$Q1.\(%7[SG:>9_+Y0M_X72X^5PKB-ZR29S0RI +M(F>QELAWGN[]:I#;Y+O]7.0H,Z,J_LH0!7="$&O0TSI?;.1=!UQIGG +M)\>EZAYY8D\!3NY_5NZ:DRKQ2T!;'!W3G!KY8G+-,X=-JL>I0O]BM7ZE=#Z9 +M8Q3_LQ\I1I^/M!S#FX*,_0X8SY/8\/(+U=;4<(V!P*^IZ%%6NX-67_9?$3$`3*CE:KU[AJE%+@< +M/(7?SGEE]J^7/8CP^N*"':BTY&V.T#./O*?@K&="'>!Z1_"VI26M8I-&974W +MJK4(2+Z[B?TQV]*2%BE09$CDVT)JD2H3H7^N:O7X`QZ@2NGWKM)D@TZ;HX9[ +M$[;P^?'D.MBBQD."=UF\:0%Z._D'H<7`MQ9:,(.[L[K+,%SY4\^3 +MWTR[PE1W8"8EP5:SZ@B`'86W*:ND6"C2,WN_HO2;-T?H5H)4;Y)*.$LE<^Q! +MUJ+)8D6WNI@I&3Q,+G6N].YH#JQH8">^.YM)72FUVQ'(T%6.<'H;TGS.6@3^ +ME*Z1]$??N]_ZJF_[4MN'5&!*TS%1"^=)8F.%5[L) +M!RY9!5Z='ZHND=PD-M:MH]^F4L,LEL&:3[%Q;O+X.L@L869(R"3UFFCG_LC_ +MQ,#B)WF*+-]5&F.^3-_C(X9\JP1=;VPO;,^V-TH;Y.:X",/>0`6.OV"2W_LF +MZ_Y:V&N],ANT$-Z,&TK=VMG+`:BLN^^!W;M:!AL%NA0BT+BB)$1G"X#_L&Q$ +M&QZ!--6U'CN0D!@[!R_\U*.=R;$&^]V?^9'J.4I\N2>F;%"F_D9L"_@'S331 +MFE^TD9"^WZE56>G3[-1I>M).'0K^C%JV'Z^@JX$0NXH?$#05;Z_#G!@9(_/O +M.T9HK[P0,));RPXX?S%9*%/QUOB-Y7:)X[377500&!E);2(WC-"LX]K'[]5_$<&PO@8/=V>RA:\2 +MX2=HQH0"??DK4(;6["27%%UQN!O6M+8;-*R.__H0CWE2Q&0`Z.%#)8<>+JBF +M9G(L&7$RVY\K'">0')X7$D7;A0G7%4TA5(7:\YJ!^],H1B9!01^]W($1\_MU+6F&V"C_*,%- +M7V[C)2PT#^<:/T?YF]A/9#Q9T=2;&A`,@49_2%8M'Y.6^Y;QTJBB;I&I'B_/ +MW)B%4<8H4X?7#M&*N0CUY?T:]Y.4(:*VI-K=)/UP(PWI6)$S1O:JK@VG_`:&3^O""A6@Q6JCV.;^ +M[:M\GU37J$6ZE[HDYNCM0T7II=JN@P]]G9HXTF[7+W +M>2OZ>\B:'PX+,,.GO)>0H4+M(HM5\QKX.*$"%O#48T)$6LBM>97$6Q+(=G6' +M(UC^OL$Y_F!G_B%P2?!?3\%'VI\G:APY&%EC[/LI*>N/4!01""54C_<&Y+?U +MA(/-@H:0:V[[_QD5%:.U.@*;?)^/F2;+)KE[]1,G*VKW]#<=CM4A'^QA?N=QAM4Y-(JB(P0SZ3(97;-NPZ'@Y2.[,X&'S-YR^0+I(1,A4%-=Q(2W/AQ,_JEAX>V0 +M7T;_*1^EIA+8%TH2I"RV";6I_R0:P''*\R2T$CA<*/.X;9@4Z=NO!BUY>!!9 +MN9[]]]A8^YF8(1Q%$N\Z+`)A9Z&/^:G9P<$FL*RM>T3(?@CT0J^AJ\28`*M2I_ +MMAX.F8'#9'`42GZT=9TI(C^/2>9C.A3^LSW8E/H\M_DQ#/$TLFH]5FC(Z9_Z +M9O_8)79KRDJLJZ,7?"]O22$CJP3A?I'J*DM`X9Z2?3^1WC='[Q:C0"S%LGP: +MK]E^C/Z&@:0T\U/WV@OOGU=-VZ:QG.*57,[6!I)KZJ<)UYQD,5[)F@'Q2 +MC4\QF8VO.!19SC+6I`JH(MUOKD<7\?=`^8$2`V@'N]L$9`''OE> +M6Z=:UJ,P0=4)PB^8O(5YKYCC'_'"[U^P/>/72(2=LW>*_(@.KWT,'!_\UM)E +MS-OIIMI!J5]Q770@["M8:+O<09+SW=GP':S=E,3.RR5CH2`8WTO=7PIE/U:M +M;&(W1#/T%ZPI#?YTG[\D'^/@A9?0ENGB2L/0Y;AM/D,OQGPXNX3N=I<;[7%,52AP^O0CO`)WN1?Q!&D:IAJWZ#6MJ$6HGYI\J@ +MFT/%#YH(/O*W=M:3],9'@UN0^LA6FT)U*$)BT>9T7#AE@$P\_994ZEV!&,*; +MAC4`]/0@[(7@[]COPM'1;;S4244HZH5JTMX)FFLDES45CP(X3=LP)ZA2G3A; +M,JQ?4M5OVM*Y5*X4#BZD!(1"7E5M)V3[K:LR-5;;G'CTM9"$,Q$2+$177)P` +M,1QL\LK$Z!;7A4%VA7WYICX5`OF#%M5P_A&4@U,+O7MZ%<-8P!$#0O/>#,-V;G?I()ZQ$KF, +M4"P'E-"#;"MDLQ7.6INU=@YU,JW5#^K>.0 +M<7-%[F;CK+N*(3=H9R2.VKXAZ\&C7.;%0HV",WZVP+J=Z?,^EI\+9;]P/\K# +MX#(\%_QET[K^E*%T7>-(="O>?3("2N;R)7F#+9#^VI-!$LI,TTKVD0Z]F0YS +M")?=G',91+J!/'H6J9>QM*84B,+NXMNY21`2?O)RXVPI\`LP)5$`$J#M'1,[ +M6F^2PUU'2J->8M74#=?,`22F!<"L"2#S+ULZ)Q)LW3!QOD)42(1E0\[J%,,R +M_J8;Q!%!Z<4#]@:@>L%_9:LU%4=76DS?(Z:0F5M_XGS\(K[`T69>!I;DW_+2 +MG9^:6.O<9L,FT\U<2B[0@Z^8L2N`K_\6`_)HY*4DJ:S%B$48V +MCXW7,)!-@XS_O8,%E:3&;8_DO'!:7]@X>1;L6-F>/RS<>EI-?#+/.4W$O=9&$ZG?5W7]F2*A1-HC@KVXD +MCER1H(%4UFO<52`:JC1=)./]09K1"H!]))-2[7!;\":?AVULH8DH#EC4*4/`(% +M"%>T<5[[@6/Q);8?7;[+>"4YE^.!F"<*OZ7J#/!]VH3'\`TS*FYV&E0)Z$*, +MT_A&IW/GRY@[#"RT%0E41I%1R1KU_`+YV?XV5=C^YXA^F:&1B,WL#4$C?[\% +M'-BHH/\V[OVQ%WO3-(V"7>_;)\;=3FH@5;EXU^F?B>#VVCS0ZFGF-_WJY"C; +M".E<`<]@]WMCIER#JLH.0P5]DN!]))Z"T48Q`_V`%7*=H3T"1Y\:K_B4?42# +M`5(GU!T71QI?=HZS8Q9".`6R7B#FQ\`L;+`DH!^`$8-0I?)J;,8+[[9"V? +M'RLV5BRMU5N:N'/4]$@.,$,3RWYYQIA8W3-:=,X)>G`,^&VF^$J/8R7'4R=OA\$$RA_B<=*ZVJ:4 +M8#7K"IC'H(YH04IGZA?TK-(*UXD\*KG$Q!7C&X/"!6&&T,US`$SN8SP-!=\7 +M^D(M\`EST!G<\WL=M$@\(S-TCTHS3.1@H,8JULAJ?JM*G1-A]=(8NW-97!<: +MY8+R:@.W3`/;$(1FRX_H@=-"T]N1,I0)H9N(D!;!'P6.+5:8QB;+9<=F/($0 +M.(&CNDU1]/J7$\E#@DRCDG::K==*)4.K<8/TWEIY?0EQ:2.!9WC[<+-L8LG"1>ZME#,F?B,Z)0[/=XD:Y +MCTV9IS&8(2>.@_;2]97)/_S2.&BEAMP[7]=`ONU3;H.SA+)G2QY#;D]&_ +MAP6O/6VD8.R<-C=/'G1T@$#N&'GYW9[R`B/'U53D$G(G7Q-C5E;?04+<8#Y0 +M,C5*YKJ@C".%)(5?Y:"MEZ3^U358;%933T>D(W5IK1M/T`\9C0G]XP?25_0D +M;A\;5+9R`2<>3$9_$MD=:7!.,&18ELX33.L30*'W(>H[@5/:DE>NH\VWHOU* +MQEJ2),L&6]$.C6)^=OR@;"MTK,;;)75W:V16%-<\'/L\M(`E@OIRW505!'O< +M'U&*W[B83_PO'1`S_@`Z:&4W2OCU;Y,MC<0P;B(5.J;T$_I)I7M@A+R-HDJR +M'X%)#$E".:=TGX:5N2%UY&XGJ#OMXF@I4[[7:IUE>6]Y)H;[UF7IO&I@\?EU +MXGX/6W.0U(+JC")A]_X7X8)=RQ@(@$(FQ@\LZWKI,9Z]-L$02&/@MEP7WS:O +M&?,)S#2&VLM+1"AA<-\\N)?U*!&DA0;S9-=.1>3Y)A(3$#E(`.8V\9-\MDI> +MU:ZI=<2Z=?`T4J@/'9)0A[!HC`,G@\OS@&_T(:H52)HXXW+>;LR?*^- +M*B9#^1>36=#.$>+:_?R*[8*8M:1ZP-RP#7$1HHX#LW$QSM+YF$YMU/XVM'%= +M?.".C^;SC3G,XDNJ@"X6BQ47WM37AA\-ZPK3WV;=SC&:TSUW2'5+Z2IC]@O? +M-=8/E-WF=<4/+:.0*AD,%K1(R/)]CSYD,S?P+B&=U-#W<1)WJB90OL$9M4CQ +MXU'9WY<&ND]JX2S7WM4.[3?=,K(>Q\<>'KB +M[FZ7PYI%S*C-1O?W_-4XN(4UZ4VB\6(XE;+IT+1-[9+%I4[`?FE@?);#/+5` +M(?6?I=BD)6]2@\I="1VP?.=<%T$V*F5CELFK+=%=4-X@J:OG:?`A_D>U(N6B]]I'','TBX>KR#18BZ+W'CATI*/'^WN=02^3!J>RJVYB3="Z_NJ\D36X9&#J-&%*_X[9*_CT1N8(#LL./9RZ`5N9'E?HP +M3FD%[9-+#D4`````W!,` +M`)M_```(``L`8V]N9FEG+F@!F0<``@!!10,,`"4$,K@8[S*ASC+-;8#X_B%V +M-ZB=<0:\GKZ+0K>VR:P:W`JIG&+];7IW]9+FC.TADG&B@\[Q<:5EPDYQEL:E +MZSMUUQO0"B,7389[=`7W..%8;$:"C\:F47Y%JHLTWIF<$*T/?>@*OQ.7NPI# +M`J/OS;7J$T),-*B0**`7G6F94GA##B1J0@G#CBJ2M)8[T]'EI:\XK;HV07A] +MWKW$R9[Y$VNRA`/TS_$R">P"57%!N0D`-'=?$QJ=1;9?:>AP!^][#&,A0%+- +MN^7NT`9(IQF]K2J5+%1">Y)XU\A.-$#X(38F=9;JX`PA>+CPR-4RT3-HODZ4 +MXIG7-,"SC=E*42$'C)%0[2=$,9L3Y9[_;Q1;F!>N%`YN;Z*-)\$E'2T'&[6G +M/@BJWB4Q]*RM4V%/(>&ALVCL;C6=O]84A]>6?&?54>I(]K?FXDC7?_SBH!D% +M-G4+(/]&-A^(6&8#%(7Y6F)_9ZV@^E)#P1=11%OO2OCO3S5="`&3.1I=MYI- +MK2.(U95Y4%R45S[**,\=IFDR +M!HJ(C"X"SRJ/##9JU<-YRO`E+(Z-EV>,5!$@#GDM$R=#(0,O=9$R28&.-4W. +M`*O&RNIT3?27-67FJ+-J>LH"CNMR2$=3Q#,YA#`LW/84>WUMMQ9,P8QK)D*, +MD23_`U5VQP]%XKBY\'F\4-DP-5[HL=Q5-4W!G)512]H)2!.4VA6_I+[Q#-V` +M5KU7V`PGZNZ8?U]UGJKNDERQQ8/FK%\ZF#ZA&7@:N)(IY<&NOS$M3A'BEQ&J +MF6!I.G@RDH\.02X%8;PJ24#^K-&RO%2^I]G05>[\/K45E9H@:-?YCY-JG>#@ +MR88BRVTT9A'">\):D.6BO0[A,IUZ$]Q0--/4#>'_:D`\5F0^(I_3DQ8%-'#IC7@%-Y\5Y^&I"DHDBU'J7>E7)4@Z8*TV4^"$ +M>#\TKI(`AKIIVX\5_[U4]E[OXON7[65 +MI$WWCO%(%32>AXY!E=:&\)RSIW:)GNU@`^,"OQ[LXN#[(HQC1Y\8W0522$L) +MA5-H/3]./M%"`6NE.9V7QZ+H.*H\N7>C!.]OH$NJDBMV#Z(57.U>*)/ +MH2OU[CS(3A(K?-=\I>V3G7M20G;VAE@)L1M%/6,>%#<+;3!Q#;#98\EA!DN%( +M/G7RGOY%9S+'&YBZ?X!W<`[K""*RU3IT>\WK3'?!.U*B\'FZL`4D<+:BH"?D +MP>M98,`F:%?&/9*XLUO9$2=(H)WVI\V7Q<<+J@8VD1%/"KEFF/ +M\\S/0\N,#.Z;VL\5F`?B:Q+ZPB'$9XH,@GD-988E!J]Z3(*)?U.H]9JN_W` +MUHFHYEK\G7[(P"^*;]\,4PJM`6P=VJ%R*)K.7J02,F_SU.*"#N=1W2J>BXN, +M4F;+QEGT>A&/=_PX,>?=O9\*(#_;=RP,W:7N3C1HBLW*D-#\(,^RB`XN1!+O +M&?RQZJ3K6V*1I?P8U!"@WK95GA4#)_G'3JA:^_2OG.10G2."=\#7>T/^A-KT +M'.\[Z+VQ4.+3G;<7$=J#N@)O9/CJ1P9?W6';%,&`BGU:P#C12D<^X.SAH42& +MH!!9U][Q,*U)!:)@4_,F0IX9UVD24RJ(24*(,WW;NJV,CCH7??X!309O@/EC +M^9R#K'ED?]E&JJG5WT28$W>LL'%EY4++1O,;:_!VGS69VKPJF.W6XW<_:K:I +MWV_ZJU5B%#BE4LWF6!B2HP$AMZC_KW?L6@>-`8"20;CL@=OEQF(\GU?;N.A& +MLY6`87[V#%YZZ:18<<`6ON%_3V]0Q&9:A(FF8K:CC&=\L(VAGI`>7\+V<=[$ +MI,M%D@D9I3,W5)J+[4-T72=G"IRDW=;]'J;<7*@BC3JO?]$.0X`"%Y^G4P=Y +M%LU)^>"EDH'!K"F6SEG@]'S^=-8''"_V38M)Y)%79'OH_C) +M-&&K$^QN +M!Y0%`\_NA5M\@QN(\9J3#D88I%*K"0+\^9$XB2TESO0J:OS/NZ+^3=HQ#]C7 +MCR85[*8R6ME$]D5M&.PAWW!P-]MHW` +MUF07T*?> +MC^3&DS\BCU1Q9U)&PGNBGLHNL8)G4S[=A)"Q2Q?QY,/M!7"=>(Q^^N#R85@7 +MOGMM>D3'+376&G3X]TKB3\%NC?]`:AL&O$'V[02#8HSJES?^^>>U4G4(7#VV +MUU+")]5%3Q]IF%J9Q?<L"R+@GA/+PM\SWTYE76C1C!0K +MCXQ%F[40)Y06@)O[WLSAIC.$[C06_NC/0;\B%'JVG@.KX?!W8<(/F7+<,W6( +MCPBO5>H@,J,M11(=@N+$ +M<+?AG-PH1J9OG>5$/HU91;BP]`R=J\45;U^JBB7` +M-M:=>',]?__@7W3T9(\Z1B..4FC1*I/%PO%*+$$?PJY;/D$:QET6*H>_#S6M +MCPFP,3$Y^3@H*KHXXB(J"H0)I'5O#FBE,6_%>L[KK$S"']7!G1NYIFO>J214?5CC+/5J"Z(B_XJ%_N"E!LXGH86A]MR5GS)>.$`C!1`4]%1K`H"YZ%Y6 +M<54=:-SK6]Z(J7RRFFN:X*R;VM(@#[V,X\.4%9.+B.<^#`G`1R-WF9S +M.B!#S]>6KH5P"'+@,>O2:Q#X6ZKPP_/W),'"V5.P*5(*:46SKV63\XD<_PN: +MJ^=86G".3J#`-EWS&>.B0MTE!!7^U>:Q-,SE96"UGB<4+XT"ZU;<\\X?<=8A +MO:UN`.!K5].Y>7C["Z^Q.)[$HC9[9BB&9`(Q[R;A:"_H"Y+5)$4Z^JW)#$?<%&_^4D +MFX3@OV$DIQ$0ML"^>'O`APCX?II7%EBX;,P4M+52;4(ATI[EZ,@D>N=L@ +MSVYX+Y;/YJ2K6ZZN<+>O0-(6L-<,G7J891.;@="[7I%4L>-CO&4>)#U^5Q4R +MQ$BCBT"!*C>9,[K9$B@1]23Q$#SWFPJ7\JKF(#.OR82+=WC^5"P<FT.1]Q(E:*,9AW-0^0ZR,F'O)(RA)CC98K +MWLAA5LUIH?B`.7K8H)-OQ6?`\.K(IIP:,=H.K#TA)H,I`031I\ILVWH+CB4( +M(J=D+C<@3E-"Q16K#U*>PWJ$KLW.K +MQX(;WO4X?1PZ:..@:2OQH<471F&5`$KGJY(3;OV7O.< +M,`Q4O]UK%`&&C(-10?X9L[I.9JASV,P>/A2E%)VJVJ:9V_G]:2@8H&7CC<1H2W!F(Q?LO,H-B]H-C,?F-.G(&;*1 +M-GX4+DGHVE\<7H!?$DRUBM`1PEUKF[=$`3N7#9,8E"3X8L3.O+*_G4F%.;SE +M9`^(H]&M1"HT)>W;R15=ZJP!IY7ZS8S\/@3XE7@S')K.8OO/V#=HT +MC%'5(86^FIX@N5B_G]#ARYK[ON.N;'.=1BE5B/N=7X0L9!9UUS,4/_NG=?G?/_E>![ +MLMB;;I6DJ^]BN;Q>IX"+*X`2/'%7Q'N#K"B*PEMT>92$=A[OA!V94LNB^.2R +MEM-*VM4E[6GK(XA3OV5XB48-7HDV$]S\64LHKVX![WB=>R+(=EF]-;'WBE=5 +MDAH4*2B&VOV5G1%8R[-&[F03:)I&G*!"Z-?-*]RIT?+HU91QJBXB^3"OI9W,&`OY)KG^TW +M?PJ*[JSE,GC/BU0J//Y?][T%"\"Z@5/C$KOK\ +M$-I4Y0)08B?WR4W0^"[Z?Q#3"M&%L)2V00X4%;4#E1&/.QB)T%"I:@W+,7/W +MQT>FUVCT"Y01ND%CC)T&LSLQ=@M#A(26EQ_>PO=HY,J_U*;&?D,5YC2V34O< +M!1Y2O^CV'ANXDHFRM4+B.4;QXC`2^=1W] +M"3LUV_#)[29=I:=;^`6(GHG((6F]]Y#/V$=?L.^5_V8,419`W^N(G4M'SGED!0$E7;.2V5Q +MH)]Z!B?8YBV))IEEPIS],J4N@/$5>$`!2S5*GMK,\:EB/6%BRBY<.2`%3XKQ +MW(`41T*;K1L[^(3K6,Y0G"3?MI+P"/_V#;AXSN+:-7!X_:>53,/^GXVHK=Q? +MGK`%EAD0]WC?IR?MQ[P]$3I3PPIA5*?\A2(\>.M1*$3\_;;%A"8/$O+%(]D3 +MX%OW[)-B2&-!+G"\/TI^,]"&:C%N]P]W`$Z55;G"I[<`0&9!P`"`$%%`PP` +M4$L!`C\#,P`!`&,`C+`.10````"3"@``HAH```8`+P`````````@@*2!$_L` +M`%)%041-10H`(````````0`8```\7%,#N,\!.E56YPJ>W`%&:U;G"I[<`0&9 +M!P`"`$%%`PP`4$L!`C\#,P`!`&,`IXL.10````#<$P``FW\```@`+P`````` +M```@@*2!U04!`&-O;F9I9RYH"@`@```````!`!@``"FBXMRWSP%&:U;G"I[< +J`7)P5N<*GMP!`9D'``(`044##`!02P4&``````0`!`".`0``XAD!```` +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes256_large_lzma.zip.uu b/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes256_large_lzma.zip.uu new file mode 100644 index 0000000000..5207777b79 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes256_large_lzma.zip.uu @@ -0,0 +1,1893 @@ +begin 644 test_read_format_zip_winzip_aes256_large_lzma.zip +M4$L#!#\``P!C`/BN(T4`````HP(!`&LZ%@`(``L`36%K969I;&4!F0<``@!! +M10,.`,9.Q>#XH1P(BLI2=:?C";"7FN04SX[+N$IX\W]6[;L<;*^%U!JK91!L +MP-@Y]!03"S8@(.R**'Q^^OIEDHX7L8B9L<&+O3]J*%"5O9SALJ1V9U61AP`0 +M9^)V(3\P!:2!.<2-6FJ]#>,YO9>Q=I`"W+>.RO+Q"V$C[G8).<0:&[`MWG_)F%`'&B*K5K"_$1P1_<_N#(8BIF;,#)?/G5=)MAKL#T383(D:0S<)\<'*EI?CW2@AL9E7121`;G=9(-,*!!I: +M[PAKD(_205%@)M7'BF@6K59>;.\)%A[M9RFJ(NMQP^X0W^C@NRTIWZ?R5^Y2QLT?![U +M^_D$EA7)+-#H/G:U2U`R2*L[#$N4"W(H_\'_HH/W:P+SGV%2`B"709\7\;D] +MU$/:OOQ]:[1BR0P\:L7"^&6_A8A-ZOUUVJAG+-`O44ZSP3/C^MTK"S1T56+6\%TDJQ&5L7*NBO +MLW)(V2%MQEXIGOV\_(),Y&JZ:98$8&W;2A5BP>/Y4SW#HD37(5=E@.]O5G$` +M:%"%,/4BMLMOUH,@(%9-LVQ$BRI*`HL=LS1B.`^'`C`1/SHVBJ^#G8M7P'AS +MJ%=0;,#6\U"3_@63PTTW=>-'FS)7``XL;P8B8&UH:YR.J:%G!_%H*LZJWC"F +M7$$M.(GX?0J`1A9Z+')['>]J+7=L*3@HWD^5]]?U?B3S`/2J4'N\=^TUSML: +M3HXM"7-I-6;WOAE[M@#`N=E6Q++X[KI8>M,1,RR^=H;?$(,MNLEIS"XN/F9I +M/JMQYP[4^`]KO6"/B?EQR3RPJ5B)NC[=/,J;Q4OI-%N"'N>27>'&:=:/D',` +M2V)-A1Z*Y0'PV;G.MH47FWHWI@*ZFS:K.=0N>5Y`->8^\\>7H/20>C96+61A +M&06II&X?X7V+.C[T&5S>HB*7'XP4/+%QAU$+4!AL59I%\`5YP\=NNK((H9W! +M%K-QM`0L+U.;]90+Z30[JL(J!EO%_J#Q8C4'C,(_\@6]/PR2;FQ/`HS%Q1IQ +M'[F&8%&=DWGQ!G][6UO84;61T&S5OR+C(277R:R.V"H63&XWU'LYJ)[E;DEH +MMLK[32A9M7-Y?3`.'VW=;#)B?PS:]'D4K$$@MCVE_TM:,-6VM0%V(#80O)[9 +M8"S-JI=9&08,;NJ.1]W.-RNJ^Z9TV[YVP-0%,\E.06W,4@#5*&E-&-@')R@& +MSIY=/+C&E-]#2='E?B!`+0J>0K1[]<_)A_J]T")\2)!OA7IEY2$IY7**<(5`AI(00'$P70`'*=J"+A<2^>I7J@SECXB1V(]W,3A) +M5"X'!@/\A%B:%L\$C'AA/_T3EWP64,H"2Z/!%$R)V"HJC1RMG`(@T/LSQT80S6LEJ4,:`"?^D9C$E/(&X1> +MUY\6<+B4UZ5&9P.AM""YH:X&G[$!''J_G>^,M00GL3HX?7SS%K")Y9.56K7? +MW;+D3]'7:Z$V2BP&]G3,V-O1R5@_M(Y4##FC\OPHT:Y]+RC\B6H_F^:G+J_Y0N%.Q;AMY`]08<:!QH=Y +M1JDDBQ52P8>&@56>LT-_3*\5YB(C$9/)U_AREZ,80_U#]!:">S?OW$+X9C#I +MPAE[/(7[F:TA,S:PS2[LEWL*6NG?35J@GDT,,77OWH+E`?>Q5+K)02^452PA +M@QI?LFDO`)V.4\20F:[T=:/KEG\863>$,7Z4FNHCXS47&S-\23:B%NGP.-:_D_=<1Z[SB0HW@TD+,IY@6AKBH +MT-0G^667Z8SZXU'"I1XR3'YMFQW2]M).>US'?:=N8(F-MJ3\QPMPJX/1/L1Y +M29:F5KTS8,BRA56B,QI+?5OYVEOP'LYB$PYQ?=G,Q8X?\:II-GH#_ED9%6OL +M*EW,Y?7IG_ZEJM6%.9G%UZM@\. +M['8VL=+ZKBP*T#PUV8O@S=7OV&J@R1XDK:/?61<3S-R`TD/UEGWD36LQ6W?<,G8%3BBV3P +M9-98M\;T^0C?I,OL-4#X7.N_FQQL_+!I?&51R(AH;:,?GM(1W>S:;Q*@[1)Y +M8CR[J@H(5<`%B".D>_I9Y&5^AB`_4>RJGS)$*/WS)]H<>IZ3-1<>B11QM_2) +M&<>V.YLVHYRMO4^E^%X=CL(!8D\7C:OAU\4-QI(O](G=^//F"O\F+IW'6FU! +M(FO=S@CV.&M.$WTN6S&)AZ[1:Q]/QB),\3]=F\2AX][9>YL"C2AO"L4&68'6 +MN`5&71-0,HM!>(UUW-6@QKHWV!5(FW],OR-6*L"4%K3F^E2[+7/'E0TZQ@G8 +MO&0%L4*$$[)M>_DH%TVD(P8!*),=%P2E/_K6BE%WV0_$3*%_@@=;NWSI:(\[ +M&5B/&1J.`/8+V_BG4$[:@]W"_2,N//[BK;+\IU$0QO%PD'[&_NZ-&1H7]N-I +MY_/`'S5_.%PHB$9I=+V++R!@@E:^OP*+M5_@I]N].@5G=9J8W7P!YGQ*/%[P +MWG7N;Y?(DXXM_+O="N?LLM_(V"Z9YK%X"H6MDP,KF(ISB4&W".H@JK6KITFT +M/8G08H&25Z7LC4@I:K;G0;7JFYML9,=&0CO_2Q(=P@Z@1T*HZRPO?1[)-ODN9/KB("+0[?^9U*QW@]8A`C(U-6LL8_[8&>QJT]%U@7+:26_4*KI$,CPYDJDI,2:ZR2_SYG_ +MM;6[F'97D6%`<$-!OG(K_=\-:[4>L5?_@YPVV:[!A:_10I3Q26>R(7RD2\ZAD?/:UBOLF=; +MO>7I2FP"'J>Y128JGC]`3M"(I+K(%64+.`*!!SC#PQ=./H#$N78(CSX:&)L>?D\&--0V.-9-2*4*E%! +M>G9O/`C(C`0%X4+U,_Z=\K9=T^%=9:SPU2WH?=E,2WJAWPAVI@YGB3Z979`; +MO2*#RZ"[D'-+N!#1R23ING@;#6W6/V2YZ"PRO$(\+HW;2NJ82:QMJQ-GSQ7H +M[])NG62L@I,%?9G$84(IGJG!H8384`E=\3NPJ.I4^[0&L)NP>%0@4K,HP8Y. +MS&?L7D-E_IF@M^75QQ:%B#.++*?0F#(15AM'H43\AZ5-8/72,+95W>LK/'@, +M[_V]F:;C>TQ,J*R@6.EA]NM_.I2U]HU`>4];CDH,*24UD+N]5,*H;/($Q*/W +M/^F/X+,NH.0C`'Z6FFH>`OG1C7/0!B"Q!8S=;]*O=#\"F'SM\H2$\WW$R6;( +M6QSNMV7;7[RUC!3;%_[B,8B+Y@!.H3W)GN0R[DU*R,3<`?'^.BKY*#(CZ5$C?R#<$V$,C^;Z5?B +MSC9E8U5OEGQ$TK;&9NL5D,[>]:H4U,]:M>S.*IT=P"X>Z+FKI'&!9E>ZO7-) +M77_O\%41L'T1[C6;EE3CT2VMDF(2[FO8EF/=GT4_;3=4J%LF?>9L'DSNJP'@ +M/$N*$Y"WG4/:'H7Q)X(;^D!WO@1UR8!&1IF0UJ-0:?K5OW68.'J`D"#D6#L< +M9D$C6(Y.9;7RA;=1ESYAN:9(^%]EK"A%--4#>8;K-YPGH(GF,ZLI$X[IYXA% +MR;],3I"& +M6._A=;4.\.Y9A!E[5RUB$,V9*IZV4%`_@^>#E:CZ>S0'*4-782'-`HC@S[<3 +MI5FF-%:+<#/SZF#'LMJI;"RN5,IV?=>F$$J3.](SPB[WH[(?/ +MN[=KS-]&OYCZR;%')D)-0T9RJ3U]8CRBHN1*:W\A[X\-FA5M,1_?E8SB`Q54 +M;@\&ITW<^\?45!-TK%;5K3)/%F]?.P'`P[LLJ,;K@EKS<P(7\!,7_4'3 +M[M$Y7!]6'-2=(9)2?D@OG1Z2/YY?-1/>!!^R6#J==98?Z&!GW]Z$AY7\V:Z" +M$;Y,+Z7OP%W\M]J!Z]=#0N&&_PMO,,A!N8J_19KTU.W,]]X!U.#1P^K"/W>? +MGAQ\H#6CD''0V?"(4:0(\^7];-U&=]%>0@S[0=Z:JN3V5?L3'AU(=B1.P5VE +M6\F77J%3`+N#!ADZ484#G\S+X6_BS@TC(K?5+?)$#-\_!^ +MMX8UP3HI)XO!!!BS6YH#HH(HE40!TDJ64/0Q'-"(.[V4%M`$>7^XF9)K:QYJ +MUU]_(1JO:D$=7Q!**@[Z4$P>7^D-QK@?+03CA86A>. +M&.8I".%C)_#%SXZEKYIR.(M`"9!>6@&O[D?6ONYN)IH(6W#69Z2%^>_]'A!? +MG)QP6H^Y;Q-X9T'N$=#Q]>0L>C=2TT/ZK";P,24O2]T++.NJ/!HZ+\>NP']A +M7VM(@&^F_YBJC90SA>G+0VU@]\9XH)_OC-.*[T9&MUD1TBE*G(J4"L@R4R1? +M(7ZIW$L6Y3_Q_'L&<)"Y.G8]FUB"7S6PPZG!?-9>E`)CPG$/6XKWG#KS2">( +MOI^8AZ]/[;O-"O2KP-&FBCV0-A63HLES.5W#".EB'@/U:6O"Z`7&HTI9/!>3 +M*$SQ,OV_\<:]WTHL;]<3>FF=GN3]+K;PSYA:"J8-J+T5(>]8<[DL:SP+'Q1["M,!# +M,1$80-_W%JQ.VOBU<'86MA>V/2;:`&-*7;36J: +MKZ[9RT]Q3.UWHLKB;AGDOMHYAEZT>W,9K?EJ@8L)]SN%)VVWS_GF1A/VGDPV +M$XU*H74\CP->;NU_DABM8^#] +M?<&H#['Y(DB%09-@>0^42YO&"'AD3/]P5%*Q\\+T>D1KO*;E,K>4Q>9\\N4\^U?XV1S*`H=.5Q?L,\$9_<@D9._]@ABB9Z5)25OX%&.W7#$<2^>)382M +M&JTR$)K%KK82B3^PN\>T@^7([>\$ZQ`FZAB:F=^9H;,4KHU'2N:DJ`([YSHB +M'9&SN.))<)2]H[[#YZJEM]%UN.P$)M*GXZNM'&5YOVP07TWEGE'>\S +M<%974G^JQB25?U?I03`%;CH@+J'<^!=`O96R.UKOIXU^.`\-E?HE>RSCNVB" +M>#!LG_%RYNIKNT`YQI-4!MCL-71>#^1D,\E0SX$F<7F+6O\_@5&5Y"MN,;*F +MR,N1R%CTQ]C:^9XS9#-!>IVZX3A*PM6D5.4Y$/4I<9>[_0J[@*EJ!.[HWX%S +M^#V*\V;HCZ87PX\\9Y2?@HG#H'B`P<30&,E$&,[IO+$KQ1/OQW'M;:&)A[(_ +MG5?!M>"&S_+9,<>_`E_<`4J<4?Y>D;Q_$%#!R"6`,;]S@3"FQHC9.C1?!PU. +MYMQ%ZX7HGV)J?&BW[C+S_[G07R'QH9IL$S?`-8K-Y66/+5]O(FKQ1!J7*>IQ +MM+_$:>;+\^B]#&<-OPV9:;DWTOCK_G\G5A)_)"C\9L)G[YMP.`""(>P^#C5EX>[&?8+CITS\K.K$[15&_I(DLTS:]<5+,5P3\BJX` +M*8A-5))K_S?_QL,-1L.#$>MP2TA=L\05X0I]J!PTTG,-E1BZ2FSJDWPN*57Z +MVI<$O7V4G77"U(-B*02O_BN*S([(G)X:8CP:TI5Q@C*/+KE`+;6=6,L;?:-N +M5+FC]+D;LV9RWV=(-4M"HWE3YJ2O39K]P;9'"8QRG+K5.7-OM%BT"0$,'Z>W +MZ0A"YPX5D/1TDF5<&*EFE0,7S_>0\..'V0EEW&E;Q\GD"K08U#;HMRH)&VF3 +M:\O9IQ!@M=D947V,7SQ%2'VQ/=LT%RV>P8YR0.VO5,T2@FRF&^Y#L,1N1E]/ +MACGXB?"+:XG%-QQ84!&R?<"F\\;),]('!]ZN[LS!O'C6I9$?OT]YAVKL@N3I +M=$B"E+@^RU.3*CZ#D414SAPF7V3&V4:9T.L/3=K7R`4!C](D+<;VF#$ +M%RO2J3"(P`=T[N5@I)?W/&:V56W,P.)RUUGNQ5\DM#SA=D@U8+8(PH%;"Y+A +M0+\WI%QE)TR$9]Z0K0M7*U(`Q&9>(E#F14`/275O)I?.'^%O"]BE3S&O_FO) +M0VK*)7L'PYKXSL+<+ECV>`2;HC-!5FP&P*=+JY*!-`3:"`I,7)E[7M)0/LF8 +M;\5JQ_H'BN\]DFF++S.W#&=%(`,LOKHR!>7FO(-/+(7RDF$,9CG:K-^GL&55 +MDM39PCQWI?WJDZ$4MJ!HD1.JRVW^]982J,"2ZV +M&_*MF/@ZP'NW@2E)DD%$5EEJIL=%V^PN]`>XXFBG_1ASBT!Z2Y801%Y)&W4C +M(F>E7OE+:)+=BPXI\- +MCI&#`EASAP<2W44!D5^5;]?Q+$6VE2&6H2#S +M*2P4D!J<#2[.47$(_OLEM1QM1D.9G?U[>4P_/-2;'HUX:>N9685%8IV:]`P( +MJR^4?!6YYM*FTZ&?4H46K*F'.Y]84O3E!"O6Y[K+V^0*VE#T-!:(&,M0>W' +M6Y%^FVQ`D46$@JGO5;P7$_)UH0TZ'E@B\K*B+_PCGD2E?#EI8L7LB'OC3'2? +M,#NAUL)XB;I07_:%V`?*TM$:V\H;;=:7I"T1UQ"[XUTS(OH;E^Z--3.A14AJ +MGG0[>^A^1RYD+,P1*FRE\F%%UVWU+!6_PS216C+X>%0"Y/,IE^:^;<`A^D4E>,*7%3K1+0\&'@GBV?Q4T*4"V2N,%7.3 +MD#O]E)KQ=F_/(R*7\?4N/3PJ2):+KR.0$ND9KH]# +MWK4/U%*J]\]%$P3DB6_=C62G".O=0,;*SET#CZ&"4<3Y)AMPEX^ZDL*S:^8[ +M8]`XZ?IES?BM6A>QKYH;%++[VY."`@>8:]GH1,N0`8?N@F$I"H^2=?O7WJ;_ +M@;$>^JDAOV[-Z+3`L>B4:T@U0YT^X9F/7IY#M<]WI?,$KG`C1),I9\YR>]41 +M.():?KR3AM#:`,C995H]E46H:7D_`17"S3%B+Z!V."FYT2(/;)VB5I\:FR-' +MZI:A`E+]-"8]MCU<+Y5H9BX!Z/$O7X2W2/5!:,_J.$9^QR7O9""C0AA(5.=% +MS<%VS!XI0KU8M62AY,MG3:@1"ZFE`#?Z8SGDFS)N8)H7-)46:)4.Z.WXOX5L +M;DN:-T[@C*^NGTJYG=6"^-3'$@XD"&N.FP;5]2ZE^0J:&W)OK%1$D5,67A-? +M%+6;F3L3.$Q/\A!TQRYL<1`/PX'+$92MGV[M%E5=W688$[P1_ +M!_K%D)N:(BQL#U:M>+0H+GA$)9T:26RZT]?1AE2(^]$F(5:Q.4>Y1MW,@AM04J`90]3D<;VJH +M`VZW)H&*52[#T0ATU$'2%4W;A?S_@11"?)'.?J0E!VSE^VE6@58WY!+H(?., +MXQ!$)EM="`'5N%^1=N+(2*LDHC77/BR)>A4Q0'A]P\G5&?\ZND\N+J<=E7Q=VI3$,X9-3)/B`QF5W& +M6N7ZMEX"W4QY^M%5"N82QP9N*BZ4VU9%5/9+=:!F4GSPB1=?92H%GMK*#%.& +MNX1!03R6=5#'"[%7I?6]DE@US$!;8JKX+[.@0'?*"BGWJABUOZHJ\&>U]6'T +M"Z](B/<%*Y"4Z_5N`06-@I/5F)VE%N.\=W\?M8ZI1"HA#"0^&V!L'$9V%3M: +M3/<>$_ZUH$AE,D3?KXS4)6P8,!,"1XPK>Z[<'Q,O+6HB,N@=`,H +MIS-=PXK9NCW!Y^R_D<0>&'_#%.[^8K4HT#U?XQ[5-/.]\MF/O[V&!+$4N?GM +ML=2J,#05#F.,8,1WT%(5HL^:]@X$+]B+%GQ +MW=0VC6-%++[J[6FG_M:X/\!I=ZI&O9D2.KE2R8]0BG?:7N1O2.5:<;M0DD4C +M4A%T"?C*QEJ8NF6(AJPW"QQ')M2(#>>UE3Z;R[1K@*KJ^E.(\246SD\YW6:9 +M;/,HWF&B:_(0HHD80Q9C&2F_9W$22AK5!^HK(XCCQ"&2&'7&`?I_KRPC +M26A^RI))(:7SL.,PEN[^(CQ#R1IBV8)'(>>CZA14T+V5PA5MY:5-/`02'J]; +M>T"D4CR)H`/%8;UN,@25F;:+#;SV=LK8V.0Y^*SADQ5N`3IX?I"]8#%OR.[Y +M[T$EVMJTN[V#07WD"8)>HZ.X]4N/-GDC[#4GL7V09S*[G$>NOR/Y:4P>3N@\ +M]##JEZ'M1Q(^/]O9CGIZNAK&2:D$()>\S3GEBC=R][_`*`SWO8Z+CNJ%U![- +MJ9:_L_V(8M]]Z?'_\.H2ZY5%*T9_ZE)C*/!D_O!^`]>?EXE@OON$K<[64?%$ +M;NYX&SZ]@;[/2Z`LZ;Z-J;6ST=&Q[F9Q&,\Z9BO +MQ:>K&^[N\-;G_/0@5K)4XZXV:"H*W-4V\ +MDJ+=@?BE1QK?@77[T0XRX23PS_>KDL'$@R+E(76@@._DW8%[P,)C[XJKUD!9 +MLSK49J=?/GUR,*$^T=EQJ"J/@317<\)\SH6-"58#!P;O4$Y9KWLQW4CTY0;4 +MH0^5\V(.!D.O1]LTH0:2$1V$^%A9+M^:/XO4^ULXHQ2)3EQ)2#G5#=>X&S%X\OZ)9IK3/]\),)]FR"6%I6UOY7R0-M'0_A:EE$68;TL>%OE1D +M?RXD)/Q_]VBL-UC$O5]-'PDN=O4.5AKLT6*HY(CWKX@2>`?%D=Y[B4\O!W=[ +MM@#A="A3;?S\8:GZ-GSH\Q7N<=K6,&C,95F.F;;4.4XL-DS0_H-;LWU7BH&G +MMZXMO*0J,D'2(0=M$SJGR[#N\$RFS"-2ZV?F1=^1$+9^?P;1B_W0S.0Y&"^` +MP$7#(\ZU@?.4AS=(EP4`S5Z]6I*.\@;AQKABC.XEEHM;'9Y +M7=[^(\/OI6KMN:VEQ$38TQ]?^4:M.X1BE?ERGU%)Q[B4FD^Z3]0O_H?_H/IB +M+`24.B'C$<%7V;BM\__0S#/TX4]&C +MH7@DO90:'N._\*_(K?_-=;C+3O4V<"76W..X2H5-G0?@:^+^7RP#-6IG45>N +MQC1(*;9L/`=G$B1??[#_&IR-.+AP(/+L2.5+40JK.._^V^,;"[2Y(/71#W:W +M.&B/_@$Q1PEE+*HN8ZN=<#H+SPTCE;[V-@J$MNT6=U0T0FP.M +M\W8NZY?,MIOQ.>K>+].SPN=M*%4P.CU`W5WM]V^AUB>J+'V.W?DJ90`T4P^I +M6(+2-:*49)N0N0[MGY[0EY'G(H$U2FVK#9V<(7^60CTRB52OCP-["SMUJX29 +MRIK2Y+`_,VA/.Q$((CJ>T)&>DR]@C?+V8[78$-\R6&:Y-W:;SLB;*0 +M1A/"?#)D^@+GMYC#O%D&.P5_]'IG^_502D=QXBY2I9>:X03)I)[D5V,XSPJP +M720<&.GU[D2LX=CW.FX.X]1@L@\]2MW9<-Q-:WCJB..;6\"@-MT3YW2-YNH\ +M[^7W:I_;1=][3=3K488:Y%26G/E*M&GC36*PI1[,8C3LHL4FO9!6>,/:_!9& +MN4^HP$\I>]3/_U1U:1&98!A>9[5<^],F>OF/H)N7@>?)IY@\9=A4X_&K+1P0 +M%84I:#^C'S&ZO5FM7:C-C0_;?FE-TFX#OVY$'?1'*67?)`J)EV&,ELCWT3O= +MC>>8+,Z;U@/>MZR)ZPQ.U3-$BEVB=2`=DQ0"-]G/WLS+SX**GVJ2=H)O;<(3:.Q=UZZ$+EL7 +M>MZ'UG'DK;OZGQ$QNA<+P-1;]A]V>VV5,5I67K(N,-TKT-,2/FI:`47_0([8 +MQ!$B-NH&:FZ?N6M'\%HG/'7.B_S,)&#Z!O)S4PPH[1`P19Q+&5S;)CKFI2RB +M=ZG2/.IAYF[4KG:*6H,J)3;5WX:"X?]CD6P-VI';D\DQFL!ZIB@UL!A=;P\$ +MF`7K5*F(&)ZF<6&U'V0H*D-6*DVFAQ'D.@.;C4VW@X.+0_F)NDLIF`)N.'2X +M&5B;*+$UH85DQ-5>Z$S5K].EQC<.U`()^S112O+,FF(U/F._W(=(@E@8*P@R +M+*,?IQ"@!SY+T)2N.FA"E!\4?>?&_0,M+Z_TQ!6,P5)">/KL^7!85\!,P0M( +MMQ+597<8X2AU8^%VN!>H(`J_V"X1EZCB(BV?L@33ERD'"AI]$I(%#>M2TA<< +MIG">*\,LOQMF;GS,#'0Y+LE/T]<>7JR3J>GOD)&"0T!Y%H_>D`E>A*[*'E#-**ZH50> +MFJ1\.085#=JH-;%)?:I8$]%?!Z*6D#"^9V +M]F\Y0N;V'!4FGYG$7#6M\C_VDRPA*RKT5(BKBE`::\X22JU`0)(=O(U/9F5E +M5=06[67V\MB-KEM/)*^>1Z_1=0IB?>6F,M+MKZ:3\N?%6?F`I&ENXA3Q<_@>>(KUIH6:BSFR50+FKX7ZG'*:2L(XZO7[TML$BBMO`V]0,/QA +MQV+F^A\0]"SZ[?)VA+UP>'R91!,R+O[!@W(?O&7:WO=;?P`QIGH$4:2'V-?G +MNN_LZX&A'6'H35OA9I!28M17?8@UWB3]<*7$5[WNLR6910@I9]X58-0]"S`M +MRW9;WU`S%');[H!2J6D1;+I5M#AX-Q];H($E7TYI")$W\E"L'+^5TQ^`?$G"])[D" +M.TA:#FU*H:-;3RBR$'Z&M2RC?"B]9!$E.2=`-X=9=;0(.I%5W;NG7"2?R%)& +MI8THO_W7U(-Y;X9A>,*C+8HB9"EI$16ZVLBKP9^)J]&>#OEC)B#2F2W/-3HA_F +MY%P?A7$6^&U1V\`437I]]:W$!7.Q:_^6H"XY&7GX?HQ8/7Y@5`VZSAM6P^,M +M1]&4/OJ"E<,_B-![49U]WS#DVMSM.8>D +M9#(BF[UY.B.`G8!-[M^%\=2?P&6X&"#QK/&[+."[0,$6]69T,`11"3K^GIN$ +MK=N)=JRFRLF'\S:AH5%/M4]J!A>`1>C +M_GB154=9[=)Y@/O@')FQDM`=_<9=^#0.P%S49'#KEXA_@NU$GJ):!N%I@5)\ +ML.(UG/CPSPL`_+,B*<)CO/3'-HE8$48D!C])P96==8NDT;WR!UJ532@*(SJQ +MJ]'^M.D,;]BQ@D4"87+=?;R$F^$@@<:@OX>11-_*40PG:=B$BCM.FGVQ3[AL +MSBHMWLO7S(C;@F(<2]Q%G#55'FC^U4LQ8WP0T)S_<-K;:T1JE+NY-"VZ'*3Z +MV'G+MW<[L-+TFTFQ%G]G)R2WUAG?4?DF%,MLE9W8@P"?NW"L`IC#>+,;'PB;YL=Z\YVJX42\GWV71>K33!U3>1=J&L`OXC/\ +M@X>MVIP\!'2VU$[5]5]JV4,3%S]GC2?GFZ9.J':]A6R"HP'!=P" +MBKW6A+Z(\`95+24"-VS!0NZ*TWE,`_`R[#ES!V/->T<*[SUGA[S@#33(7T(@ +MC'=/[KI[QO^E9,K&WD[H*`T[3-46GW_@Y'ME?FR$/4=U&-8ORF=Y:O@I2;,@ +M[92`-'^= +MQ6,V7QS\J$"4>=];\)1`3B9B/F@FBVMILFH-,2H6/B4+<*RNDAD0'P<4"``3 +M!F#Z-F`I-+7!UYV,:F#I_"3*"`SHEZ#K,#4!\(GJZ)KVPBF'!O/!70.)\=-- +MIZR`Q9)5$/0O)#O-\DN/X")/36(5,K-CZAO+6(P;ND,..#S44;R,TA9_@V57 +M0LQ$F4`O.:90J4VAW15K@'++_K7\/1RCQH#DTA1&K_^"3IPQ"NF!=#:6UNRY +M/9OE>+*C)J`_7/6K\]V"'B?/^#7,X/)Z2V+]6._LE-H"#UA9Y$*RBT&@/1>U +M)8]S,+[.&X9GS]-B/S+OX*<5_<1Q*L*?1NDGNCMD +M(+Y>;MF31F%3NN*PR3CO4+^:\%!;_/CT$_C +MR*,^HX+M#MA@8#*NU]\:3:&5SNNO,7Z-1*B[;>>PF_T19WU6%M?L]@,#J4<0 +MT>B;OZRFN)-O!:W`U@5.3?77PY>B"##.PRQ*]1HR*$1V+\8)698B6MT*"+&_LV=#[+B:.UZS'NZ1!=*E>2F%O +MK-$P(28]#GC+1PGSJ&L>=*SBZVOMAZFV2SNOS:X9.0/(M5G=W +MUB3JT\!,%2KE3&SW%J#A6$VF"VR";NIWGS_GR^!\LF'=31NLXD5+G$$1O(W^ +M+?U>:PZR!BEE+5'/.MNOX&NAZ:FI[D4J[,1VL[C>\JQL"B6P@_0,!^2KA<'U +M\3<@8?&_=VSY]B1Q8!K0=<-3!MW]SVX>-P-[@SO[RA%-GI,?/1*O[$&!:3Y@ +M:1G3C5R1C.5VC7=;5.5:ZT.([!8 +MQOP<-!P)!$=UY;'E9L=V-2^[FRE@X\GD/T6\+DTX/E@??D4TO6^Z[_;\'WYO +ME%JS2A]CX#1;B+M,RPDE1B4Q0/$H%WR#D?W#C2@=^(T:L47K#W#[\YTHJH7TZ/0C_&S- +M=.,-R&,-5'K):-S$A4AN=1CJY/#*,V?EL?S)_M_?8_Y@2U#0]:%H"5CFV8W, +M5EQO&VIFWZP;V`S4["3/",E;EC<'2N+6VZD;][DT49RP'GG[7G60R45YE)BR +M9WI`*X,N/;SM]"&WN+>6X$DP9G_;X&Q4_A5]Y7])D6DWN0B5[<5S,TZ$^1FK +M2FWE1L^7@+X$U%_"T0'`L81YX^,33YM,KJ&W24G)/OD;?[D4^3#\X%-WA]0N +MKQ\JYGT^5'["E*TV*)(7/A(F945NT?W\B9C:1[[E\2/FN25_U/=`?Q:!7-^W +MV[P59M._\9F>OD+9Q?GJ-8&?9!I[[3%GJ-^F2^?(C*5^88A27NVU[0]1FK/[ +M5+&7L5+GX$E`$OSZ1RTI8LQXTJ=T$?_VU>1PJ!AN"B-#VKQPWI)(8Q-D-G4E +MJ(>KL>G]8LP)\Q-K-%TE%_G;?LLNWP&9<3] +M$W2F:-C18MIG2!'S!TW>TO8!\7\Q`&_VY;BC="WN1/M3(/#% +M=XI)ZJHR]47.J7')\L=J[ZP\BGY2`D#PDM?ZFQ"'L"T%A&)[ +M7=,CXP[H4;YW=2-FMGT&7:BPN6V#5P]C?-`?3_??_7.:+'SDLG:!4?`8Z\DR +MK>9:$B>`$^+M$U>BX_9=,2)T"88!^I;M265")+[OXCD.FJ.*8TB@BV,W@S1JO?L +MP+70\H_YD7OA5,=KP)>$P:^GL@GHK%#^[)/R%*)`D^/)`3/HA#[M>L;6%U&Q +M:Q'Z'ZX$O[C5(CS,S0N8&40KGW0).:OYN/-`TKNS>2"FWF76JV(XUKJAIB9"8.> +MF!I-%NDJ8=I_YNN['F8^*-68)]H\^";W46Q]$POV;?5/E4':Z='-^N2C%K!S +M?8YS-PAU-J[1S^7%_O1B+"2H>[3;/WP)5;SU$R/9K?!JY!(=V,1E +MBBC7[4?W!!EH\YW`)1CSWWHU];0B.0*5KNL?=_AJH>7E_U!\Y\_[ +MU*%:*@U=99;YJUEX24(+$>#>JG)3U#N9!J3%7UH;:J#>'YIL5`%V](_`A54# +M=7B_!#+5`N'H#\N081GM`_)&R\Z*A(,-66=3WJE0YL)8+FM0ZV^31@BX1?/2 +M4/^'^MY`4R5$0R"&2"I&)VQ+,9EC1K95;!M%)="/P>O#8$CAG_(4NPX(7K1? +MU%2P&UO]]:D7T1(:5]6LH(KC%?`$;5)=(;:J^'@8)&7E_@1RY[(O<6]O\+\7>1=S$2@NAD4^&2]"=)NO-@/# +MIVIZG;]^X6&M^INT_%-$!67F&F[=S:.XTD8W?/^INVGB5*WV1Y7WV\:<)!XA +MII$O0)A6OTAL'PDJAN`("NX`D +M]ZS>D[MTH'!D9L%9=$EB>!U?%EJZ\Y>9`U7\\:@37Z"%OKUV[YMP=5T8+FN4 +M?K@\JH[E#)8B]M1((>VK#2)E734Q[7!/FVK(JE +M<5`<84Z#C!`R[%%UP]>XN'8JB5/"YU]3TZ1S$RD:%THHGO5U`$])]J[_!\YH +ME2;!-5S7\FL`<46JBO$*I5]*64Z+NY;32W_U$E;-X4DV,Z2,"`J90"-4)VFA +MA&%_JELC=,_3\FB\&,`.\Z#CPKC@2$OU2*>E5U.Y!BTRXQ`^T=B$H..QP%D' +MXB].]E+8P5PUD]+SM/T8_XZHM\1EE)O6YFJL73=2`Z%.$)O5T?2:TUTF+&;B +M&><)WE'L$?.U,2;+BQ?1_Q*7P]X#:PSY3FG2.%%*$6?MJ9%(LR7E<8M,.&69 +M9[Z3S[`.+D:RZJ13.)JK3R0L].MM"WMA.]T=3%./TI&F*>\&B>]$[5H8LV,E +MW7P^'E=209CEQ4ZLM66'[6&8KG9#=5]PYB3F%4#U$$0Z#H/>7/@C"ILBH;M4 +MV*\GLWE\%7B`=)(T"HGC1-MR=";")"]\7NJ^>_,2`0119Z[=C-+9 +M:$H#B]0V#XG\>2:V1A@#[`-;;:VJ'FJ5P&2?CP:<)2IL7HJC7[17`3'VP[AC +M+\TN-,DLUIM5C97;=+*@_N4=T@+@L^K&^S#=4FB3$532(,:S<)`:>=7ZU*S1 +M!=;V@.YH-E81ODJ5OR/L3'A$48TZA6/FGH&>FO!AF'M8A99[ZAN3FCG$GQDU +MD,P.)NCX+OM#^.`<<9AM:6#L5-TO;OV0A)#@YPB,5JB94_7#DH5$GFV%9,8A +M5YF3)>8CJN.FZNH/Q^$8()UCY4B@#9#YYAJIBZTBN'VL^B4[A]UGA"5T_L;W +M$X]=J1+,JF`FGW8>!T6`)\)*_PX2LE&]C+9_Y'D.K%P@)XVA^M-9E^RR)/+? +M_RT=NIA1H%AC@W3PQ/A^D<0>_-AF0@&,C'6RK9'(TB'2]C=]'UHS!5#F<`3+ +M0H,]Z7JF5(;\2E*I(\$8+);0O_G@ZV9H>25Y768MSE?LY?,O0'@X"KE+H,M< +M_K9TEDZF/UQC)L"M"/DLLF7V(XLF_"SL9O[>]WXYJD_N/>N^337P`?7A5@.D,80M/(9-O(D^F-H`N5/[Z#&Y +ML7UR(."8+_)FLO_O!T#BMTV[4CSJ21X.&H-Y_*_8'$]`K"6@EQ_F.R<_S$Z- +M]4M??+R+M^GB<+=1R(:QG(G)-_DGK`"D.2;`LLX1FQM.7T=V`8O9Z,K&/R)2 +M[+\T1*? +M+M8K/DTO9EUOG87:7]-5X>NJ"W)94Y01^L[Q"EYO%=?UE3-PD-Q@I2-8D&M3 +M-K^@5E(F&I-XW1(+2C$!N74N#!KRMKN8"5D"4^:+)^,F$K3SXX73)>BJ/J87 +M2<(+8;>/1-(,0!X&ZJ*#N$R+<4Q^``[QIQXQ#Z:+[0BTHD"H67>`*RJU+:'< +M/`72I[-KO'-$5E75.C@6TO:RLLC`_)X^!!MYZZ,VGEB]:+GPT3IE>H0P.CX\"._YZ`@S +MM]83';;'CE`S9LD4`[F?MDWYD<^'N&*BRJ>Z1U\K3;AK!WGN-],CF(=ILM'*=SW[^4F/EE+[/\UE;^#5:HU6=\,Q%#8(/W]!FK>"UE +M8K;,(DF+C/(&C3#]N+KZ32U&TMK&.?$DD&(.8R0]LX +M%9%%%JT9;%O_>P\)BWYBSE3[1+AYMW,Z%HA'"1;/405*OSWF#>JOD:+LZV9%HQ-+T-D6R7XB87 +M*T1E>$!`0+>+;U;G-G9)58,.1I\*%,1X0>Y?'"W[C;1MQXIKJL +M;:>\H_I$.9L_/D=!MX+I=0;A6,$Z727K^QH[R7?-2-!%4TW_B+^:@HWFGK9$ +MG:6?:*^R:X7,'3.1L9TA`8&Z80&=P+XFH8"11XE4[CNAX`=?U]+@-"RDDK0B +MP('JNG*PI6MB9VV);16&SP'B1JQ;CXQHC8KJ8MKO>3Y;-O910^?(W"T*F;?) +M\]-[=/K5V8;FOK)^^0L1(M6V+=Y7=6/ +ML3U(^UB38\DJ\*0)A[L]AN&JI:ZQ)NSO!7E$U#U#>TN*42#?>@#@$1EM6N@E +M/O%CM6?@$_\?`94!'7X,NTCR!X*0_:E.ABU]J\H.A#=+5>T*1:'T(Q4]N_AT +M;[?$H7A5JV1*RWP=)S'T/A5>4X7P@3>O6??.1GD)^YR;B:3-/L\,C@F3^_J[ +MG6\E7)>(3LAKL(T/P:Y2CRB0@9RZ?Y^Q+O(Y&*+":@.7U,NI[=\835VMT7?C +M;Q/@6!TW-;!7[C%N\62W3@6&AODRZ4?BE1!S>-H%Q!I=3RKZ.0U.52(S,PXW +M[#`]BA+TZ[9T+A8:G1CAQ2-#QR8LV$A?$RZ>S(]C!PRH/:)U,&@KB:B:?7.2 +M+5R-$>Z9(FH-6'=67]Z)3D<\_="KL4QW/?H[N]3*Y"4XC8S,EA2RO!\*#X9D7WL@"W_7QYF>E#4#6)H9 +MKE$(WV#JHC=_A1MV^$[UE:V,]JF*W%^!VJRMJ:LEV"R`X9S._MM^>5D,5:=-ZMQG]IJK-'6V(RPJ(`Y=H!DKFN&?^#,/ +MD5^RB&@**I!D%"P#QA@`AA%=>*P*'$E:@9(%_@GEVX.1&[ON0R_/0N_#%H,JYI4U3+)-FB_ +MR1.A>[8+A=8@B+C-D'^2^48@U=XOG70'SC$[4U8&,NQDV^KS\`PA\3[(JG1S +M/U3S4S>+8P-)F!@'T)ROX=%O8EU5BB=F8$WU_=#2O27%=B(94V]_79CM@EQA +MF!_]A?OS,IG`GK[7D,UQ$]PS$V!X3NL+8*TX\\\<@3+]O4#(8&Q6Z%J?M)1*CR("J%=*H-IL?@'8-CEVOH^G(.. +M6D-"MOWFW!2:\WB/!T[M(&F9"7?`>5?/F0"7E+E;[!329T6YTH.CC;[+^'04G9O"36F1*SIZD=9KE9\^^ +M[*MVA?_T0RLN6SI?_?U#XCS=;^0KBFP51IKW<#[V/]]H,&N#?ER$\L-/W"RK1F;C6 +MLA(Y$5;K?FC9.`W^;:F1M3=-7]^,FB_L4H>2_O>#;K&>X/H+854*F[`,X$R" +MK',-63(YYWT`UB##OZXFB49U)CC2G9[;=2TW&+L&XO1D-0U4M>*<*>Y7+00[ +M->WN"FFB8$65C&,%BD)K(/P:@.-%LCCWF.?OSZL&C?]3W +MYNU!6:J@?=->_J3\$3JX@E?QO=Q;4U(4T+[&!A3>7#/,^]8LWV/%L#DD5QE]@YG:.3_N>K5B"\:\+\@K1=6ZF/!%``:C% +MJ?A*$AAS7U..#"HWQU]`=L9U%'Y&W0)V?CWG6+LQ1$EYCR1L%OMC +MC!!]W-+/*;49C3VO&^6`:ZU3V08Y4)4^SNK>V>M.G%/T79-.;:;M`ZI"TGKK(Q?8J_?:6XXR2E$+=3WD&"J=T5VMSMTVWGG[8YZR:_!VK(^=";B-J=K#""O"TZ/33,L>4IM0I9;*3,@ +ME""R>&!8I%]&>N.M/:HL&Z9;(KYG%M +M'>24=R>@/.5SKA[G$7E]723^I!C'\>2*Q9@/OIE,>@]QDVL`\Q8W(EKF4$40 +M+S\9BXM5;OVR0E@F.O2/M._2.(#X+&5,.J`P!`M[C(.V8&ZFN)H$F(Y6&9D= +M]VR!]8TV"('L[A(EQ`]HY*]U_VS!^-31X'?->I^*M\U,TJ[,"7?QNVVBQ(-K +M`C0#>S#0U2]15Q7UK+K`IZB@@MCE+5MLU]I]YY&7!\SOROR_RU04Q/N\'NQ_ +MQ/Z:GVQO@U\[N/T;H+MZQ1<;CCI9M!+H^^6.ROCN?G*\'#49S22NHN58KJMG +MEMW:1:GE^_E\=]&<-"F;TP)91`=3#^X*"ZP1Q:Y#_-0("]J^7D[:RC236OP8 +M?L5O)"@H@01H:$.CRQM5_W6X8-,188P]U""E&XXY1:^$>>)[$GXB`=@TCV:2 +M`(&6>0(?)*\DL5X3_PP#HR[UR=<);"Y[LL!!E.R63&W<.7EXG+=EX>4%& +MS8&T\44FH#*98AD*;H<*C1!R9N-#"4=9/^6)&'8ZUCAWY?*1I +MI*UO+"X;-9=!?/^9N(@U%(*/]^C9=K+:I>&A!=+/Y8`O7I.@J%11CI%^,B'\ +MQX:,8.$C&__UN<8N;"OX&^F7)9GA:NL1= +M?^\,/UQZ=3Y*BFTT#/)A4J#][ +M5%LB/$-Z^K"+<1)^6A-OF%W4F:!=UNE&DX`.R5<$[0!ZK'DG96I%PE=7IEFU +MBZ?/LQ`4SHCLV#H*LC)X+MT$QDK]GO9LZA(3ZI1(*;PBC&01)#SJ@K&\H30BO@ +MHUN<$V:.HVNYU=`;5!?/NN[3L]/W^6^*\;B=R6=G&E-J"]N^5?;($[;4[QVR +M+MQ9N`]*=7!@_1:);OP0NC<^TB#\0KJ)R<0;>(S;G9_UB,K/7;AY@G`AAU<, +M2CJ;Q2T]);W..'%NM8F^( +M_+(7\+?OD,@Y]%19FKI(@[),W/B`7EL_WF:W3OIH+GY'T3B*9N9;Q^LZ!A!I!G+=RD`_J`P575[#IZ# +MBS@?_1.NPEC40/*-+&,#DAKLN\TG^:8?7FA0"B&4HPH0ZAC74@7T4:W+>T\\ +M'U?;GL'MWRHF_[X9Y +MS_6[S)A/B^;$+J'"EH_\=E&7]Q(A(U/%!+BBJ.1@$\8!DK+[WYO\UP,!#FIL +MXW+5"\*]&@TVN%!$/2=?O9(4Z<(S-+G.S]PUNJM"Z8O*2E+ETYG*0!%T+72P +MO_3)HRE3<@7LP"GM3079(@PH'5R9FZDMH7AA5'5_CF61G98^O&4?'!99$D%; +M5G^UNLVS$.&.<(Q!^S9GH57IU+M2BL'=_3$U"68\OR'/"VW,X!(56_V9P*&J +MD=X3T"=8]0+<<"=<&_";E1-+H"Y`\4E92.];$?GMCSSX"XD.-S[6GFFH5J_M +M'?'[1CX&WR"S&!+)4 +MW[F&C"C4EZ$R='R*=F)Z>"LC49&B=DP7;-$&EY:A2T?%\8G2YC7!&F,YXXIRN`]!M#28 +MP9:7');R^V"6E87V(ZV_K)$9P+F!A`D2V-\'BO(/RG5YCV& +MFY;R*C7F)RSOM;",L@#8*'-S(!.U15E#R+K$1YD"$%G6 +M,@1DJ[ZR`RFH)6]3D+*3ZC3G6C*Q#4\$#[$-G3WR0XJ1YR^?P9*S^X%TMSE) +M6",LL;VIN69KCP/S9GNN\CP]>VDL")CF&/+*-Y#7;D:WZ?ULA2>>^!&4`C6@ +M3')S*8[OANJC^698]]'1F7+I0K!X,FKF^(T!`503"CN@($B=/U"*5KUR>S?Z +M9N0(6)E]FC=(6O9%NZQS)QJ]C(&D@[]S,3S+^M\-X&<)4*OR/O/OZ5HK&C`)UB0`:JYX=[JEI>A9B8=TG`5>$WY!9S@745#O[-7`@*IUM&? +M#=Y,9IZ]EM+4E#[^%B3*[M"I_<4[IXG#B-IFI6E7BPM!_;6AURGH//C2.V6K"'"@;S[U\%&XO^/&Z#E/$8*8^#IX&E.9C3/Y7>.H-5&Y`%,1]1 +MB\L9*7.V&Y.-PKG5H>*0OE+XV+GS[(()%MA(<-)@3AS::QE +MC%$^1O,;':$#BDKK4)XMQH#R9!9TKOA>#`EEM02]_T?/XF6B<,"-!K.B$8Q$ +M=S&);%SL114GWA?NJ[6_X[]D45<)U6H))C>HI#V6_:TVX?=/(I!),J"OM9A. +M^3NAF&5D#4DLHX+=]2\%),W"+1!+N!?;?5)T0)F!0[J4 +M#S3(=IZ,'7E8O1!H=.__R2COZX$E0C12`UW[.O_CIUO#ML=";H@EZW"TL`H:&JD"L(Z]520QES:*9<.U +M;M!_4.0.A2DN48J:T(Y*F%DZ4C?>I?SQG!W5#CWY:#F!TP_%ST\U&;QC_B_N +MCB9'%@,5[!QRB;P`)>MKQ[_B$$:<\M;A,K+A3(/_"1#.1]^O8UO_A$D)UD=U +M.TC79W/"VKBU`+S>[%7!E5J`\>)D<-*">U`A[I+P)_D&`-#BT-.B/S0,;T/%8G'Q`*`9`165C-?=.$!`EHU]0WI+1M1*6G7?9%.(3)<5!*EIS"=?6'Y)<3]]^2W/`)F(I[:)4UUAY"`L'3$>) +M7$/C+AIMVL/YI8^'T?73/JI#QXHLE9,?GL1IVC4DN2W@&66HOCF$Y#$6:_)9 +M"/7E46"%%6;IR+DM$QD,!-.'&*@(!R]\2JKJ$GGE#R7TL^RXGS)EF1`O;S<` +M/K$+E`)S187.$5J_D&%3.FH8"V:E`5EA#S/(E/;'F-D9C"@=];3OY9V654 +M7('BZAS9`A%@[EI#2LIK!/9DS3^K2IY!$.F#25\*U.ZM]^,DM3 +M=;>./6@$G<%!E@7?1PIT9V2#,%YUX_TRWA]V37@[49JUW?[Q`;75A-8L3;>& +MN\>,<((A*4!J(W\SWQ)PLLVV/ALO=S8-U1&)F:"=*3;L_JN*NVRF]Y_<[KC2 +M+8/MDE,'6X%NW00P(7'OL_JS +M%J=8/J#]]++ES^`2$B#X&)V9QQ#,UGY'7"JH&%]#$T4\5FSL9_O>GW"D*/X\8X@ +M8.\(_T_D+0W]/+4#3XE15FK\()!BD%;M+/X3H'4,@[465(W+ES#XJ/:8AM'9 +MRI+S5%O*RT:QJY,79=NJF.)4\IW'Y?&CUMGJA'/=Z62(VG+XFZ/;#-2Q;_E3 +M&4*`"<'\^:C-*[]MD,&JBCBXL*@LM=0,<%,B7P#UPU4GP/,`J!'`5&DGQK&T +M95R`M$$GN!VI2$$5C%*8LP2^WV.@)@5]JP%8N)'58Y6#TB[MB+F<;[=:1&8) +M:R[#A6E%X[LF[9S(BRL.4Q +MMPU(';PX](\1X+2R +MQ3MZN\JHZFACGZ.\47;&R+/T,*Z7 +M?XGY*D7L>T;U`A2G=N-0[&DLB!L +M94_9@Z'N[GA2UVG8E)WR!!M2R(VL+.A)>"#"I9`)&>9W-`:V>*+3,8.&5J8` +M2_;,B:4X7B2SUE56_U=D0WGEORF&RCY:%4"_AIYZ!1(J/#B$Z!"WF%,,&0FS +M"DE6FP$BZ/X1]Y?U(95R%/^R6\Z;P7\/R4CT3E][^^\P-5ULC7^PX0788M^\ +M001W!EKTD.X<$&)N5=W2F,\0ENT>@H +M$@-80`.<_@!K>R8(+U"VY#N0M_-;!SY65#0$JJVUC1+K%G?26_C<,)',I5=$G0\:EK5,*$)G]YT>0'OE3@"['XF7R`!V1R/*O^3V-OHMR$3]<:9D<^ +MT5/INA7<9ZX4(<.])KNAF)#C<>7>7'"=MS"O"/D +MVJS]Z6,P&*NS@#SIH0RJWL#I@2IIMELQE1SK_7,C^,/Y&'CJ@@0N#>@F@[9K +M!]<>N4*WT,?_01]HUB?'UH@7@U@^R4!\*\#(N3EYB<7I[-Q9L_3^7A'J8W+W +M`27!B;;0:_E'TN7U=M*MA[-7[;9K4'L)=<^N5B!J,96U8!\&K@B$/TV$,Q<( +ME"G`R5;%_H?XWO(_Z$5-@_9WT>;,DF6BRI(@[G-;[($*(0!<%T/C^Y9DG6>+ +M,9VA/_BHL/!LE&_=-=]MP5R^@S$+SB(PFY-)RHI9?(IVC]M5H),#S@TFP"?H^E*[C)>_(@!3N-2(#B[/#BOU0 +M!U#)[_/CED^ECE]#[[3QC((%A5-T3*S6'=HC_,$OZ`P"CJ2IOM+ +M209Z;U\NT[J550;%`=^ +MV'!:P)L%F"=(12UKHIE=7,2'T(1E>DY&A35Y>O*_)H4BLY[A5%5X$3\#QIS) +MK::SS,F[%[9?@P:)\_-"WP"J3UV/N%P'\_D])5NX!3`.JD%B"NY)"RN>LDJL +MTP;Y8%1WW"'BDV-@"%[-&K;XR\2AQ..1BS[%+Q5D#2Q4YE6LN*#L@8S@:3:] +M$SD!VA1I;XW$+4XMNA'N-8-3^R_101?BBCYT!7C3ZI_L19+"[ZDR[S+L\)AR +M;.D89[^S=?6R&=$FN6DZ5W_&@9D*-E>20BV";",@F.#F8;:M`@U="S!'G>NJ +M&-ZC +MC:D2/1D!BC-?]K(GQ3I@%RA2^U:J:_!"^=YMNO,?L\/1-#<6HCZ +M=^Z20B#$G@WYZL0];YJ\NHN\>2XJ="]XJFC(S?FHY^/8Q%>&HSL0J.ED2!/[=9O`<2-#)K9].U`L_1R:VC(S5R"X=`C.)QZ$6VO6-_9 +MJ&QF?GTS+(R/'WM/4&J\[#$6`8J*%>!:I<"T\(28XC-ZC&V_4HO\K>!1^A0T +M6!7[C5.,6*0(8:%(E[7M+:1=`Z_N&$T+X!_ZD[A(5.;<$["`'\MG+G +MNW..F-R/ZRX8XS@B0(R3?>8"EGZ6LE4C8``%Y^^205QPKQBZ70SI0ZF8(QZ; +M6D.^XUFH35OL@*I26A[1/Q+4I18*_-WTM$-SD8IX\>4[A?-%(+VLQMUXN\6*X@X":PSI@$?QJ15X4P(XU7ZH1+T8 +M\F#L6$^:D/EUGHDP]'BER^&A<:9%O/G^-08*2.M,0V[[>&.B%\$$="!&CUF5 +MSL@0&0=V/)IEV2,YNM#S^&%)[O$76FE2]@-Y-_:>J*73!HCKD*PC>V(P-+WS +MALZ,NYW3S+#3Q>Y"4KSBS2@J&Y;?61UG=UZ+2JPW:Z^'?>\$5SJ0\.J/$88X +M^JA(7"J7J\'V2N*A*LK#%HQ(]:&,\KJ+PCYHO;Q`$/[5"<RQ),NI)1>]*\Z9UJ?\3*:C-YE8!0CSAN@[DB6$[4W!V;#]'/_-= +MMS:]QO8DY*UTI0'5_0C;*\??&+.M="<&W-V1LMKEYD4[(5FO7U=1=M@QQ'/? +MQTB^Q,&>CB9[:2\B..YQ``DXQ2YMUJM!KG1OMB?(J:,:"BA4AMG!*4Y!.R[2 +MR@HWYY`G*C[T,,P$;)#T$-'HNL<&E/G#>">=W.E9#I?B5C*"17X.-?LD!=SG +M$R`$4ZEA78RU +MMC(K%1[!ET!""<'S#D=`)?A*&GM0<)!E.[H\7Y]%]_Y(A5QO0',WK#%BY*ND +MM)H5GR$_GT0S%GY7V5( +M@C.9<:BC*;QIK8I$X?TW@R"A"^.BVKWEA4:6",B]QW2AV,^WH+:/L_#--+1= +MG:9F#EK$%77K21!*PX2PD0IMEJWB5#TM@!4GTD?&<93;?O69IR%_O?"ZT>/: +M.R:\26@/-X7:HU_,(R^N4G<,'[O848MJ\A@5F(*?Y^M,HT?Y=LN3DV.23RW_ +M)$(70H5:"`[>&BAC_YN?95EU@(;M*,65P4#9E(>^H!:CA8)1NP:Z!F#$]3W@ +M&YG4FRJY'U@`_X(,>W73M5N?:@K05Y<>1#RPN-56O$*"C`YD-NYJW&O,OV%RFE[! +MIL3FT<1S +M%V%*JJC-:>RB^`33N:A;F1-#.\#:4O?^#Z\$Z:&QE5E%J,6F3''%S0`GDE)ZS+3\M6!L6L:(W$;@8.10> +M>OBS+]6D=H'6RG'1F1_A\0YRNBQ^[*7RK +M3DCL67@G;QCLXM`8=?ALXPQ]*@J&YVBZKPE9NQF/6$5!H;'ZK.$_6SRS#[2")@2\O9 +MW^AP#1[]+X8B3`>%2<1*JIY`TXRT*=E=M4JUSS"`0.77PSE.U#D`<8OE2[[Z +M^_9D$:GP5#4.&=)9R9_IPFM?7$Y=_UUJ*)2[-$O_^;"V;,0F9-F$K"R5ZFY: +MDSKU+$R%J3'2I1[]B9F`SKD$*+@!7>`U^#.)8%[C^LAZ1FB1/L`MS0UK](A^KSH6$/15 +M"U/$R]']HM9"?>49DLEW*!B@3*_OFTAQFDM:F;V7$?B.1*2]$GXE!^ZK^8+]VV'FU$([<>SN1+,XF.DW<`KN4-+D7C@0$8#M@?'$&U[#1?:.6TES*VOF8`CI +M[>P%T-,>YB"O$W"L?WYY5O!B2*X4/](3(-(;CYU,FV&9'% +M3Y574>"1841GU*B]^)-7[I5"1E#`I:[IXWT$>UFC&J[4I03_RU*MF_(@W1M4 +MD_L0$E9.[=-;N9%G)E]=5^<^?3KE!O(`R,/GA0"$??9?"L5 +M/9N:475+W&9>#2S^O(;VU4@EB%;ATJ*O`>O,S&G%5,KP;(,#0GY+5#_8VP78 +MPHH!G"__#L&\5@=(V5A.UI,3&=*B^FU!,M0=0\OFWSM-,)_X1LAOAWC1$X.J +M5@Y`6Z%;)YN"IJOS6F"/19,2\CV[19^5WDT,S\G:#A+"C,SCC16HY4KO>@OC +M7\V1\G>`M-$,)>-0F32];VS2(P2P7WGHZ*X91:/P!.0]@F+G/"[<#<^,?X=5 +M:2$[!)#*(/>EWQN79;WK;VVL5V3*5M%KRI0O:GMP%,"NWG8!>CT:63B`?^`- +M?L7KP#@]D=8/4:5]%HQKSVJ>P/JNS(EV>!'NMSH!K]OA-=#0?T3B=^Z=$:WI +M7$W:6$@H^1X=S!I\UHMO[`3ED%+_?WRYN:GOT(UU+'[F?)\Y4(5$C=E^LBY; +M^9+5N$2'^!EL>YN(Y4`@9TKLM`A(0/6=+^3L'."*8LM%C,R/='L7OJ+6,W9\,ZC +MCAFFTT<@O?E1$[(KSVJ"YX09/0NYFB3Y>^G1+40YL)W"X;PBU`6-69`4H,Y: +M36_D8]W9S2>$CV?K!OK?/ +M^>A;PXE^4Q/ZEF,,;+M_,?-/5=G90>JSZ/X34Y7?A;\;VDLZ9<(_C-D36+5\GA`K((QX!G +MU?YU.7GN+#M@G<17A/"^=X?I9^ZGTDNH2+[XNVY5\6V;,+W`WDI`#R+HE7T= +MYYE.#JAR=\KMBF[U-_-F_5Q17/B'D]C'EEJ;Y;3!N+XCL=2UH'PAOE\UX=F1 +MIIU\H__/!O"/Z)`T`+06O[?`G*.)M'D+@57?*H@UPN3Q)TP>MD;1'3A=V$-O +MD2!]DD'0?I8D5N9Q!:A"KX.:I>*KHZ29U#*UYZ4-/!+G1,3N2QRBF$53%>3P +MS!Z^"0R +M'3!BU:,5?RY_'3@^`8,@9'Q1/(F8!!J)2.(7B?O``=J6S"=/6N;?U +M>^)-&%A+=!CWX\6Y"'%(E.^7PEFOXIE"3_47.K$E<8E\(17:%&_![_E2CB2V +M\Z`"5I']LMUBYU60PD\W?AGCA8Y/$(-:L>3=[@3G/+YE-Y/=O*ZL'11I\Z[X +MEF=%O7;)T$3>+9ZN-&86I7`$W@T,*'"6(,X0[2\MQJM`KA+CW2'H@DB +M*)I]DN?V,5!>,,753466@)4V$(PGG@LK57>#IK-42V4E(7Z-?,8\$4H0&-YTG=7CD4-=5L^;I;KW2*>=NN(_)$A(^9ZCX)P\7` +M/NZJNML24Y7U\&$83G?U:N:-JA>ZM:AS\F>X7<(ES+PZ/,Y. +MG28"F"$N+'0\2'E,G^"(V!'X/\Z12CI4[B"1+%)]"Z":`#8(]5=7(<6*IU&6 +M)?KBZ'9L99Y3S)%!@#5Z@6?4V3@V\,XY$'O;Q1@WXA'/HFJAN"R\1Q20^]D7 +MM/1/1JC&?(LTQ-)(IR5BFY0N#`Y#9B,+`G/6=:8$WSIKZ#620@XY]K8\6W,.8+TWN\T>Y#8?X8I0W,R3$,#K;UC297;$\XJ%V'7V]N_51+KT^AUUWJ'!&B/<,"F2DYSGBL6)0)`<-C8\^MR +M6S-(_ +M9KI[2WGF&Q@%LY3[*>CK'%E<-HS-1TG,B]7;[A\;9-.?&)9APR<8S7A;T,#G +M^-'0E!%$P*_CY,S/]37R1;@>Y_IQ#M!*:^!W-*UWSON/3ZV!OB"L<,FNQ>N#QA( +M:0>U=)4',S(U;1T,8)/L1;EWI_92Q'A>[(CT>:;!5A+/:+.I0`/B&K2WC06( +M\Y]C9F"7B_./8:WQ!R)2W`'F=^IJ^.K)?$/2C[)$2:O]GU41%M8GTB&GKE]4HJ:A +M;Y7H'FJ.6B%TBL*6FF,4OD!(=AB'%G@LO_E?8V(3$48W%Q3BXSG[,!`_P/>! +MG1S*7BD=N2KT%%2UGR'J/MS.8#;*M*"#VD=W56P]E>6O%Y1=@%;3J2$TU,0Z%X7.:9N^DA):P5T9]EW\OU]HT(W#Y^ +M1CVMJ=UYPR2[:XLOL9[%3$'P3WG?&`+77U7%N6A/K@8.2H:3K#;KZ4'$V+W* +M`V;,V$S'8`>1=):(OO4,[G9Q@ +M\W_25[BBN7UVI1M8J&R[>`7,<4F=0_A%-"[<9.?5=^'80MH**21UWT9TL10. +M/X)ZS@%9!Z:)YTG@@A))9=2$)ISSX\>R@#U]OA#A!5I)#$XVUCC) +ME?K?I_:3"O3=TZGAC@J)A/BPS66>=-`Q!1.')K..+AY$P!`>O307&3\`9.6B +M67*KB[!OI'*\(T&8P$%!KJ0[*18N5L^E(_KT_DBA^,C@V6/%T'@LK]O%>"]* +MFQ)O7!0_R>BCV1`51YKJ%NF[V;X%!ZGC(C3X0'_BL#F?[2L4V*Z9EK:O#>&'LF49,""T0^A@0]0P,Z>Y<29U!#R3=$8,8_IZ%)U'U&MU&:&?U,3@&`#=+>O.DR9BE`P +M56C_XR3^Z;N7Z"2S8F^JX^?XN2(=%X`QT5M:P2TV#ST?_3A<:T +M'DP2+-"MG#(@05Z[E;S!70WHNSL3Q(`"/^WM=Y? +M$G(M:;=(QL!OU7;H6#WCL4@K?J,NXL46(30^'V)U1)"I"F\2IHJF`QM*I3;T +M)9YL`IQ+EJN'#ZTY*O77I+*9%>+&+%'-PR*Y/^.M^M26/K9)3X4IDF,S%W;+/M0\)O] +MEB[ROH=][H'8H:X%1XH\^M&<1+R!B>VTMLK.$0:=O +M&-9_IWM[^;][CK.,#=/?='!_,?Y"/6>S;//.[I[>>I^BQRLD,==QK$'W6\ +MZ2X4,4\S],@300Y\KB&U00E$B07W,4ZLQ5$O%=HB8C!E`3=\IXOY=7;')*33 +MCQ%>$;-;A_7,#?[D_PY@JR3W7)02R!.9U9@`-Z#J*?XH?9T5(CJRU,B$D%7H +M5/'F6%!UPJY[\XCMQVF`.2%NOK!]L<2'14AZEWC32G35]NAT&M;P=M0XJ0M2 +M6B@G+D1"*0HB0MUUGVVOW^^AY3WD6BN+:B47#HLY-__<$J90*W +MPCZ\FDAD.8T9%K*RK-(::G:8/$D_.P>V3JJ*$:8A/)6.H,N'6RA$"6R1;/&\V3-GNTB]=)+5A#V$_\X!BYQ8;(N$3TRNR/RE8&@%D7)C +M$9R:I%5%,5U`@2!RAJZ+?@7=328-[\;,,Z0ZA%J-!;037?EVTCYAKP-I/Z:S +M0!)>)M$#201JLW;%P3<:1XVA(H9>$Y`3!F%V_0L2W+D&UK7].Z!X$3:W5'WB +MG96^-C-6FC?;,0?(3`>ZRZ%E0C"DJ?2RW6'96#;"JE`0-/H46B9?L/\QK]B, +M^G*=``$&!EB'/9=RO$Y2;(:TBZ&H*(T[2:;F)+A_TXQ(R7_BM:'7?]PNK%W90#!B8I_35)M+\>3Q +M2+NI4R828U67MJ='K5\,`A3#J"M*\2-60/*&T)2E(2P7CJ<:'OMT^J,B3#?$ +MK_'("27DFI1HNBP??)7$[L2R'!:*"N8]QCR7_599K$EB>C!P-SU\C34#$B9_AL, +M.:J1&>G$M)HE^\:[XVV$BW35;Y*:3*^M,2;L:_D7#*3X@DI;C/ZAUKP\R?21 +MIVP70@$EZ91=WE,#B&#%]3;9>9Z_5XU2L'_&M7=X":_D:;NW@=E@E>:,FSOV +M\@VR$`Z1V:1S=B^I]\+%K'N9Z+8V`QVL4DU-_$,"I".-Y6I%.Z'^F*E,/VOB +MG=G`P4N'5./)%!DT/XIF5EHW'QSF[N\DNWB7P?;>%SSYM0@CX)$\1LN%!BE[ +MA\E8G3"`.A,+F35D!]QHWUR`8B%C]9&M/&9&-\,C8N%?.8+J5F@PP?GIUMZ@ +M!>MZ\;"`)?^G=,KII*Z"JQ22O/!%\NM?JVXG,2LT-*(P?EM'BS1N!RC,6%87NCF/^A`JID6OCIW<&*;J9$65*B. +ML4_#3Y<::?VAV0]L0V%HEG9OT2+Y/-.`L&X1W&GM3/13>@>0#W_BS7\9@)>T +M%[_4<$$T`\+&$PNW./TY+NP\2$_<]3_UFQ79(T&6@W0FIPQ2"><>Z!7,P!L/ +M%RH"-+]-A#SK>7*)6;M!*C\V^R2'[FD+8S!?O&++OZ(6Y@A,/RN(W?)!E.4V +M?1/-6D5(.U;B'RKWRU0O-E(Z3>T^"Q_PP8!QYC>!%_IZR*4JLG&V,?%C0]L +MH@2>1E!M52.&_"B6AJA5W=I'[<$8EJ0"WX1S7QZ@<<)`VK^'Y1XTG'UG#3L$ +M$(?EQ\`.EY`"-+/Y2FPD4$7H+4!M#HNX??=J*PU\K[MGG36N5=$&LWN`AZRK +M?:$*,1%+JZF<:$E;W*IQ@;1T9PU->*!4>+GI7F.3B(%SRDS$`C6[@I!/'XC#J@!2>C40]<;NV!/'&#T' +MTK":<`TNH6I6!L(S6$"=J[XHW'MQRYV.RGA(8!>%WSE]O/L7RA$P%F1@^MED +M)5=Q+0VO1#,)2O%*',]+P?ID-S==QQ%EJ(33/'`JF'D>@_OSML7H*U$_`1/A +ML;-`("YK9V"R^:^(?9`#44@JG*_?M/^H(N&!*.]:;3FPIZ,VRN?3)WPK?Y1# +M$LQT0-@EYV.>#HJQ8?:+Z5+,P#9`DCF+&EP;!1@E(C7I#I)4L%'29P%JN +M%;.LON/'K8&)F:GN0,&S#M6@@^7[>ZK88`J2?Y13']\7*:8!T:WBK\2J$L*UR6]-X($-%=/:[O5_SN`.9;":WGC"!)6? +MM;21R\ID_"9FJDPP88AG*T/WT"FYW)@['%`@%:$JDF!G0ZJ%@QBRO5@>P?2U +MK'7?J2#-P0!2!.SM<8(E#&A5R>=3"MS3@7V!&9)%8H0AL"HJYO\+MZ/OI^ZI0+O?2[R2?PKR$_ +M']+H0>-Z@.RT$CY94`!H>.XJ`[W(/';5CBK?IN9*XI:8`\#H#7-Z- +MP5F>`R_^J.DJ+O+-2$_*:@+G8T:*.5?#$_-(HA@')R)E.9V.Q9E>/E/#<1$] +MO]VFF[U2>^;RB="HPFC30>@!3VONZR;D07ZY_?$GB?\A^FCV;\@'K?(320NS +MT8V4ON%X\4/A^7.FQV5&LF+9V0^%,2?F'0"X*&TWNQ;7]`7_`7O('+V%I2"T +MS0(!;P7CV8/^'B.[A]2J(([FP67W\=BB42+WN9`%TEBW./4-8,D +MOW.!<*Y&%)$#_'T2F<..R((#SR)`2,C'CS@DS$WN`;0,]VM/L`S/I=7?FO@* +M+PBE$HIZ9^>RC4?5O]8\,K^I5'+&<_Y0,;0\8I"!B/W6.H7-: +M&C\>NN^^TIH'36T'DK)^Z0Z4\QU;3:,C#FDE(D+-1H-[*O1TZ2%V[L6@4"6A +M8DUFXBL0M`%VWI'36B#>ZJ49Z6C(&9'@+SJ>Y21=UC>:[BQAA=S#P3^:(/OE!6@%$Y#W0+;+V1Z3"T#J0CV8TCHJZ5,&?VP\@]T7+53I2 +M%J!/V<9V^\3\)"\D?*6Q/;V>NEY&XABW05@YQ9(8"]V$]8MRC?:,Z7513I/G +M77TU/MPJ5EY/-PX`+KM%0K-%)%[L5M![U;CMW;Y,K#*)FXF&,#R;M7S6,RC4 +M:<(@!#6R[9PI&[)RKX6L1]\HJ1P:K`S8EDR_"`M>K-/_]_W%#$'[@GRMK?._ +MK$D`DBX(-DKVDY5D?"O%HS1T[1D-OBM6-TX. +M-16?4;2=T4(`3FU1][\HF#P("O=,9N +M.N,Y]W%2_Z,K[7^(#R<["HE',&3-/T72"-L":EYI>/8=>K@&9B=1D'J.JK1ZTE)Q*@PM9&$$_\OQ>?FVAH4_A;3G(7OGCFKGQ!MQ[G<392U +M-%N$;V#NWBTB;]2TR08J$)MF?MUBN^V(^$3M:U@CC/^/-[Y\C8CSIGI$D()1 +MX7QKVV$^ME3I6^UP)GO^XTW8V<4ZD3Z_?RF^^\32NRU@-8+E,53JL!_^'\7I +M:_\4,6&`>%-%ILZ!(;+0S+_H:^XID"D@ZEM9J9`?!C1?R)I\W#&1;M[$]#XK +M,HCJBUW9&JM"[O?1,3H\'WY30PQG)\:R^>L;;DD$)VO72PKOYY5U_]Y'Q\HJ +M:;+^?.3L:^W.YW<;G]O4&B%S%9M2;)2%TFF/\8]F'WN]@\]6W^'K*3M'AI3M3096\"=T-13.>)8] +M6>G>1,\L>YTL1O;-9\A'-)!B6(BF,`UQQ(7I9#K=&H%0_.M0L/%]*U@RR$ +MQ1)00'P^$W2)B09^[!TMA9>.G`FY?72XSVZFP!<$#X\'23@P;]XC$-E,X<.K +M<*25XB1UWRS`[I>7D)I($"D1FP=CE`#"(Y*I42&),!R8;3KM6%CF-:2*.?!XEMG?Z_B+I/@;CHQRRH3(GG.V*V@,K2E=YC.:M%F)\M/3 +MGC.)[N*UWH'#DHE98K_6Z&84+6ZJ@\!#@0`\:)70U>+D#.$MU%,@P$"8#4G)6O@ML>,.1@,)U.=GU=OM:L]Y.B>ZA[T"\$DC$F6/:6 +M%T?'%W.$OZB$G&Q.Z8:3LK<[6`M0;H-KBY7EXMW*;1("F(DF#BJ7P@!(CU%! +M?9R3NX-#,S0_1%X6F(FC\T\;48-\ZE8-LK(@#U$),(X[^GP:%KV=Q. +M6\BE4G0CW'G8QA,R41U]&+4/2J7D?EQ^`Q&>Q.HVYW,[R*X#$V4"?AFY>/.' +M^T`M6<$==!:`0=^+\J;+P9QB83/M;A^15&/64V#N073NMZLU-;F>U\0T2VL4 +MHD[C)<=;-$XPY>&Q8:KZ43:_\JLQ9/K1U&?5E@E`9+PCK",W9%][924PGF@S +M1N;^<*RI[AUB/W58S4>>0[A4++LQ#!I)R!.QR;\K?1[*":8\W-U9S^8",QN& +M6^#J"ZA/;W??]'OY4G',6)LF7D$L+CD]*UE_HP\;!.(9VB>@QDW6_*Z-M4@LLQ?;1M7DXJM>:$@1J +M&>LKW51"_I^QV.]I,^<=AD63#^86,WM:ZU\FG5>YWE\8?+E?T?%\^Y@4)Y4F +M-Y]RO-AEM.3!?4!51H'WMPM2&9F`;<)C76%H[9M:E@!H&<^*8TC$U,\)99[P +M*W@BV'!N%VT]AIVE,>E;+8"]S>!\FPJ"_ZH/TN=*KD'JYJ.H"70,Q*N/=?E5G_1:L_"^*3E#B?ZZ09 +M5L0"#,S@U'U<'LFFT58NJT@4<)FUD05$8C2%@$-BVJ>1WO!7G&.WUEDF`NV1:3GK-$\>^G^WGLQ9Y#=66^G1-\SC_0%C7!R`X5*K>>'066^$:MB7.^B1`+-;7=1YFZ<5 +M4N`J1'-<[43FDFIF5D1J+*038'?JO[-=@O`APZ-1$NF8Y)P/)%T=?:";&HNK +MX>A<0%/SYJPAF#4`KC)#+[#CJ=58&.R&))'72@NAZCW"A+/$PCJ8_%$+H.1. +MRX7J(^!&Y*G;`L1I>BD_'?J7G^V3+D#E#?G1>(:M`\10>(A;NKD$&WICT'-Z#ALB6'1%B2@W(W7M5%$OS*F@ +MG\HRKC1"2$/S*[@MGE3!.(^VL,IYS@U@V`HO_B^)YM$FHHZ_;S>PGQC +M6D@HI'1R<]WFSC_[#P^6@.+I.V**\W#(Z=46N+7'5K`YUCWF2`S5A[6(<4?V +MO_55>+L]Y&-SPS?(YI-X:)>7*9GM[<:][2A::/C),;+ZEG`=)G90P2.G2/R> +MR<7/$,?]='IV9A"F^,Q:;:=A,?=&_OUZQ8CT\&+!QA.C!*'7\@&^O%"*@'ZX +MU2X*P$\56Z2,QM35US_&HR\4^>L=&%Z=D@Q[DT!CU1N_GN)5>^]/^E!P\5S= +M[U0%^XC)#!C2#0)J'O>-<\G[?)E)^*JKT59]V4/Q'QO9?/J;FJB]2[4W-3*` +MCEY!5V4*[T`PYT5HZ`7K=R*O*&J)O11CT7=<".^< +MVK)9"QAL/9RP31):L^L1,8229W.-(AW&C.]@^.7-IJ1=B^^<_B5&1X-.FU +MQB]2#*ED*=+O1LDWG^9##+[%#109DE&V4B1A6K(!M1@%&AYL=(B:`]WR"AT'Q?JU>O,UCW,^:7&9=U8DS5FP+I.JT9B,1&8ER73>(%\`3/,;X^W +M)1FFX?Z'6]7@MQW_MX;M$"M:5!-EL3!'#$E'^:3=KYP#F_/$H4?.4W5;1(CF3*?6!K:"BKN$?QF +ME$.(?V^`JFL@:4/U,Y/;).,JEOP7[Q1S_$4L/966I)"^G#&_Y67C&!/B05/% +M%B4W*RYD/O9@A?4V+FQ-G]F^0ID.MX::EXD%]C'Z'1=_6U%+AF^G[HNVT0SA +MR'(ZF_'*66O6LY(,N(R +MKJP$!RR<$N_>EX%!ESJ=!/=EU3UDE+:!%#,WK]@^\V8*(:V&-R,-E$)+^+R/ +MJU#@?(=8WZ9(XF\/JN;,G,UHDKJ8,GHI/(%N.G-(C(WCA*68#V+UYG7*R;W^ +M!<<_ZWU4Z#1U^JBM>V(JU,DHY[=!I9]WX+G(ZVNO#;>-=C*H889EV*I3<4N2 +M?O#'HJW2S0GEMVR_=A<]R'LGS\F+L$.`T3\(O`&7BBS->]I:@O`D"@*B^:!W +M.;>+@_K5HK55T)!%R,#F37WZOM1BS]J-6CLFADG%BB`ND2JT11_E.,*B`[OD +M17L#3"%+I:@IB/PBDL0!3"X"DB6IANH`@5H=O>'U?-#YN*_Q'V7Z!`]I[(IY +M<>%QFN7.C:M*"W\Q)*\8=X(C +MM\@@9P\`[.3^-(@_-O@-4]8+8N7%R:H)3&V=S]XA3'W7JQ>G4_W7,25@.Z%I +MJ^71CPV]F/8V8BND25*GBLXD_@O,/0RL8(Z3'G/;0\73B:A7@L^'+Y&[.:N> +M;5SK4MY#U)&<$/H'WYEKONY?8-MLK,(N8JQL;UWI.N?2BI4FQK13S:T^<_@S +M7TP_*4B,X4([=$K"'%KNJ:F'F4=PSUJZUW,O5FC-)`_HAB0(SIG0#*+!=<[U$/\6:'+2`^CT_$'H6'"/ +M:>&7T5+<&ZWPE]:!;Z8*AHTI7J;(V;+O-KY/MD,BDV0$[H21_(FYYDYZW446 +M'C]],Q1^\^_M^;0:(ZTN[CN!:.)S(X5ZX2-:DX'9>&)V_G(:JRE#6+R82'(] +MFRS>.(G_C[G26"WO#$3&7E2"B<@ZHJK+[(%3/<'Q4GN+M$>X8\`6X_K>RSG& +MJ2]&5)4SY*R.1$K?I>42=B]I0U%#=2X@^66V)GWC$$9\$@%'[EZ\N4H>6C[P +M>P>6H`7Y:3/G(+V&G?D,^QCX0$I?*0/FC#RV12W(_E1AX+-G@QXC>#>QQ]'V +MJB3*RG>?>(46B;O/^@'_WDS$F5U4;6JYI4H='C'OQ'=$9!%WP%*Q0UTOTNWG +MLO52'9&FF$Z]"V/$6?]H7%1IS4`U;Y7Z4=R-?7UZ:R$]$>,)5;X?8[?9CZ\I +M?JAM[U^<4EU(G5$NF51-6H^`^BK6V+:B%Q+A@&:>72$SBO2&E08C`0*&(/S: +M\PCSO[M7>3'#3!&Y1_%)%TQ^$,H]-'&'/)<';O.JE;:`:A,0M&;1J\W$.HJ* +MY/G<-E2W3V^/P?[C1I'I2HK&]2EY)-WYW";]OA,:=8O[04$H4Q5_6\G +MN]Z7:8EW@66E1:%ZS,\8/F +MJ4N-?9^S)9 +M-+S8X.XY,ES!\],37<57WQ60(C<)W!M$V@?.5OZW*4B?@/]I;C1E;W1C60/? +M1\^"-5)K]9J?1(4;W&#V8Y2YCO/M998W1H1?NO+V\._@I!*R"2<@7^YWQC/_ +M_IX+7J\A/;>2_XPU3[CT78OQK#ZL7_(*B\S=_*.'QLA,.>;*ZP(C?'IF3`@K +M;]62@@5B^^0Z1,RMWT6([2H/]&\`*6G:3@**1 +MYR/2K,(#ND%BH1X8WOAU7TNK"11CXJ'U4/$8-ZDDB:B#D^5T!%T#<\1H +MKQ4IK9E6>/YTWIBQ.F)S`05*:\I.W4:&Q6&?Y[2?L=CU&3&1S*VZY*0Z%"?I +MH>]L-CQBX=[OGW($!1>/'ICG:$QD2\73IQOAB!,Z?A_!3!#=,0=*Q?2W`N\; +MJFB?/30^V>F0]>:U&$/=]<7$/*1?\O]O.4,N_8('\ZN;".U:^V[G_]E2Y5F_ +MS_&UH!N?J&X;<`<:M/B-L\&TY@P*PN\B=_J6*T(1B5BJP^S/H_+3LZQ#$;Q+ +M`PK1M'*HSIPH=T##\@#IW9*]IK!L-"3(@9G13$8(9`/\E=LCDP:9^7?&&'Y$<"*.QBBFB*]TD2'LL\=ABY";5"Q,/)?";H9 +MA2^8+M<0CE$9\]GOZ#!S_K[_";Z?[`2%E^J/0D_\-A[1$]=*WBG<;K%3$E^R +MNDQCF?2>"!K[0D?_[YNB"O8J5[=Y]L''IX+LC8/V04;"C@I?EU:4?`>#1LGH +MIS$G#+/Z?M$S?+VVP\%Q'?LGN/(7*_ZP3Z^D;L68C""\.-T1_\\*"D%F\:F_ +M3L!6I20'N\,8G&3!"^QHO>1!A]V",?=81Y^5WC%M&5!@8A-9=Y%E"[UH-M&9 +MM`O'&6#2S=58`/]G;`79SFHE\[O&))301RFR%X.8L\%[I#`.<0@J/0'1ZIJ6 +M=LM9>EGN2ANUZNA-4!$6XX*RHSJ&-<-C<&R]@D'AJF@;Z?0\^7-4T.=DN?3_ +MU\KDUF%YY/6U!HM(,&7=QF))Y +M4&NMYO04B"W#FT1!O&7OP[;(PQ;`*>V9_Q$ODC_>ND5*VJVJUD[D0E_X? +MYYZW4G!@70M`_'==4=;S##UWFR?N'\]8%JJ*2CHP8O?6I/ +M/>Z9$Z"@83A/=T\/N-'\KZ,T,_W93X3P&F2>DSB*K#8.',L&:3S]-OAST0@` +MB]88`)E)P4EM*&$LT&QE#0%G+'%OHT-.K9[O,DQ;K/3D4I'CWT2],3O08&(9 +MB4@Z/]*RQLVO1$0,FHCENO7=E>?:.#TW&)?IKBPF%F[V'8-&!V._J&AZ$+,] +MEV('^=7$*7&]ZLD"O(SPQBS#H^>%HESKLUXBQ-TFRJZP?;<$IA8(T2@4..J1 +MQ2FI8'Z2XO'9Z9&?4(;*1'PM6MCS#6AT31;)H,IW5,+8N(F8\#(KWJ@$$UDN +M-O)3+WR3O=@3!\03+__(*<`JE6I$IV=NB#QXJJQY+SS/175C]7?1@'860#31 +M5"-+^OI[S!*G8\D3?S(V@:['`!F!NJ8`:J5(%;!?5W/L-\F*Y,M`K^!B4I-? +MQ6O\QJT.DEC-$P?>\XTL`3H?+#$#+:*_.<5IUW$$?X+(=;U +M0#A&9&@13L2UR+:UG&.%Y3EA/^RE"U]QN2NO9V74X->M^?5BSZ%9V5ZEIGG@ +MZ[GTF/2!%2@+>`;K^LVWZ9!N;!_ELN4I*L0U +MM%;X8_.'^"/VA5T\2[MHT!#JI!*?4E+D/^&$+L"`J#K%V68/^,5=A7TPP2W*^2&:"T,2LK.+6L8`Q^<*3)23SA$SQ5`'[2;2\ +MQ)#5W<81=85994#`S`)^U1$$5/G3W?-XJ2<\W=I!5V4X[UAMOC'\$L$9U1/A +MJ>63K7!&^H:[DI^L&`Q@#T_)W,!<4N-GJ(R#/0DL;SH($EQIZ>5VB +MCV^H?Q"2U)VX48A/^2M4]7&X"HMT9.!&.]RY"U%GKL"2H\"``>^E)T9I2.YE +M)$XYH68MN$"R&W[-<8$\.`M\G,(I8Y-ZTX4]SFU'#*VSLA2K-Y<1CR(K7)QL +M9Y13;53@>V*=6T-0%$1#NJVCQ[$?(A01*/UV'-WDV9D%?G]2Z2EI>53K;A&] +M04VK+@RJ%"BY!*Z)CRT+RR;%2]_M@V=F*B7TK&B+*,DZ(A6G+Z61C39HM3RQ +MAPT:!X/$%A0YK?!6`5L2CR3=VFH17?W>W5?D9NP)UW^*++U43T\PQ!2`^#ZX +M(ZT#ENG;WN[@3")"IZ%@UL[OT_)DG"$R6;QH:YQSJX$TXDC=V!4R_?J9I2LM +M%AJ"3&E/:85FLFO-'SG1I+R[M#1DNW6SVXIMVV0"86BY:MPM'X3"$$DNKE\T +MGOJIMNGOAP2NL\D[JF6.LQ/?3Q:PM1SA+K[E!J;)A"A8,<9FTT/&[EJ46\*= +M;T--JI;>;0&*D@U1$N7YY4(5+X,M.HL[5+SWQI6@OMKOV8!1]DUQG/A.L\*3 +MD9$Q*VZ$9Q[@8P%8'R=5IUEKFZC+N3+NQE\^\!0=^YHF];L^%<6J^*QQL-Z- +M!&Q$[5YFJ":9$1]3;M;Z!?(H]>7EL*_EQ@/5`\X@S^"D%X$##)^M68K.N_8A +M;+FP7%5YL%S*U>CE@.Y)CJFW.P.OWV/T/XF,]>=`6NYL;#9'WC2(:%GN1DX@ +M*!.96Q\V&=#@@95(*"-\_+0IU0'G$D;+%XM)<:W:)2+T;EK8%$\/73^9*9XT +M,97,W+R?6G0N]XQC_R5*;VF2?LIG]P40Y?I/@>0,Q8H]'_J_BX!]/^O')B$*C+[_[DS^"'&@3/(\TN:.-DS3'_L3N)76.,4M73XB#AXC;?9Z5S`> +MTCU3%9_^4%OG-0^%3'RNS?#MH0.[(7RYC1%"X)/6@*1+`R.J<9,60C +M@*;@?&)*'&^==$:#[_XS]V3^Z4:(Y>ZB$AP&-?-D+']Q7R(=WB44VAKPO_AH +M5GOI0C,9XHI)E1R^::?TT,Z4YEJ2<54UT28(MT08!6E*E'M0%$3L:K0>"RC] +M@+$O*BX")U8;J0E)$P^@I +MI"2^6TVC5+,+6HKP%@#?R4`_"Y5D0>N2S-[BF(J&,E3,92(BD`]K; +MF@28VUSN&]!;1K-;;0%Q;UNJOR]XTPWW8NF +MF'RS4O0!)8N+$=@BCID>._N7&XY?_%Q?>YI(&\44:K+-[(VFA;B_0_>2GV73 +MWZB*15'R`_RY'Q@+*CDH](*K#PD +M"YQ`^`55XB5$"9"0-.;R])]8,C%<2<5'BV\XJ?]W!_"$['O]JMO$;Z^ +MYIO(>AJ-)9V"YF4=_9F';&:?[7FW*`8S,226FG,E'=#O[B8V:;(.+8#FT&2" +MM_'O3P[Y#N+4DH378NW[$&VMQXY%T^GM#C]?F5#[MYH176N`I$4GS@,_]/89/&=VY,/]N"SEG7%.BG$8]ZF`\G"] +M:,!_C*;)\3[Y:TU_SPTJ=ZH#>RARF)<;6)VEI[<5$S5\;L1A,^+Q5FWIDS/D +M)_D82@IB^R2^IQ:IK$*[>9>8?2`W#U]=O1OZL6RU/JSR0B&^)K?BE=HROK1P +M/_1FA/Q#X/WNNI^4=@]A_AYFAM'T,3+GSDJ#*4PE&%RUJ`Y+D,`"1+\12?RW +M9I)3.+9F@I7162,)-.)/G/^R+7J>+P:BJKV]F9BV5L'=DWY$AWM*BK:05 +M#!]CIN*ST3N;S=6=Z0WNHNZO9)`MJ1.!2.IZ^B:3OGCZ;3"60%8VORA[]*M^ +M`J*`%NK29K76TU\J)%9H7?B#CQ#;Z;),-E6O!RBK"YND8'(/P1B>BX[87$:!$1$G&"S6F5M>:O=NF=:B^ST)R+ +M$F\XSR@.CW\;&,#=%0'4S(`?'9%P=$=[``I&:M)3Y5RM_;#"<-R_671D\K@H +MFV`0R`U5QR1>6N87ID@__X.@GOP';@I130CGSW?EY;PVD@Y#]*+2"CSOZ*M-U,B9J]LMILM*ZU_BEJ$V)!&P@M:RG\\2A<^32+G-KU +M^TJP7NPD[\/,],N^]T$F/O<"/U4IA^4SPF[[!1N$SK1=*,)9>Z^H'JQH68JQB +M-"+>[U@^5K7MZE:KB"*^?'@):83[>.UAF +M6WHM)8[6LH]C"YR#JUAC3/PFO('UKZZ.%_VSD;E3(A(.,\O873O2$)U&4\F` +MJY5_:!$YGHTC@%Q!G-',BP=7E<5P"AJ'.<"W.;52G4-Y]P"3*R-!L`(,X-&3 +MH@-M;N8/&5&:#9M!%MS*-_.^++.`Q+.,D)M^;3T($A>:JEBL_#YSU-K?UX++ +MWMSV!MD8RQ+C]MZE\J]^=KJD7%)#+?A7&]/+N"2N*5ZE(?"@TYS[Z;U'3*SG +MO0'/69J5F/@Q6`45Y3OQT31I6NY+=[\?!Y^P>/U*^W.=>=5B-K5,WARK*TR0G?K%>':<`?^[5[.E:*5)!LC7N&+P=[TIUR=/C%8 +MMR]=3JYG;G):&"VYO<;OFC]G,7:BZC.*@MPTP[<`S&<(7 +ME`5`U(EVCQYLN5WV3[RP0EM(0Y=H9!1=\.-'!!I(.15KJ7_:"VOET6$+L01D +M-F1@R%BS3"-EBY,(#CJ5MD5GC8I$!6#N27R^IN-",/]LYM+!TSAJ(R1CO/@E +M+9]69?PZE#@T&GIZ<^@?])FJ3FK=U.=EI6")#LI8\6Z[>,T]KMY#GI'E_S=*2L`Z4R.]2K0T852CP?,*F.F^-+;%QZ#> +M/"LG\=I21RS\56"^+-UCZ!=ZZ#*$(XD\W@QB*C/VDD+A#@"]J=3V0HJ;AG=2 +MQFG@Q-J3LV].\"&9/VO7<41Y?*(<"4)6IJ5=9I8$0Q_)M)EC&+*^EOEK*'.4 +M"9^G@3P.V@_^G#>%HCX'*^]QKXY1@")&QN31;H5A=WN!&+./B<9/$9ZT?/7I(; +MDB$='\UI.M9ZP$)2M_JA8UH@5R3]VL[`N\KW8F"M+I9_J(_[]9[_]3Q?M':% +M##?F3ALN[B&*6UI.A;!!.4^:[-6(A>#V$(-S84?Z#/?'Y38)"1-4P#*>C)7G +M_[ZYY@"#>`-3DA]AL=Y#V4&B2PTZSHFQ,H>'H_'ORG8W0$@M+@Z%IQ&)]^DT +M/;WYK\`M+PY,DOL5,(=C)ZZ(TM"*P@GS=YY7:VV@;7(>^"$BQ#7\6*=B3)?? +M"IC66MUNFS#8A>^^QGH-"Z8U>W05-,(F()$:O'@A/9;49-!:%>+C +MX?=DN;%/-7E[7^.][HN)HZ$M9[X%GA&M(VG0M0HOX+5SWN@/H/YO2H*Q1A(O$:`'L%M'_\S0 +M6LM>3Z_[_&N\E\-XB>X-:04F>A;]/I#*@<@-_0))>)OZL>NGN\I1"W",Z5#P +M^HF@;QA13EUG-W2"E+,CXW;E8"C),D(SXDS$M0X^ZT-J)IU3C5%D9Y2VSVEY?`PY4L8D(S5\@'F6WT8K^8,'Q?.\31,\ +MD;QU_D1=?V8'$;4#W#MYWY[N,#O9PW"H35$9L;N$8%4ZW,)"J?:7).KPC/_: +M&@:9Z<&:=#>$I/;3"(RMRE%\!QMGP8FOKV%L'F:!2PYE<8K&T"*-^AE2`/YC +MMFZV7(L@S1Z\"&S-:_-F!*TD[43O7X^11"?-%760I=_24#A657/7L'@ +M4F(<*S`#MJQ:IA4Y5=.;X&J"0+&%'K0>(A.S^9TP@2SR5 +M9K/#53!="6/='H>929+3^`\ES]S`^:7H]H9*P,(7LIN>/]<':A;$]W9TH--B2&)".PN.YF!A&O.UH#A==&*S3NT#\X^[%TU0$7^0AZ4XFI= +MY/80:P?TP2-$HWEEIASQIJ%!_`_"09(KO3KR?8Q"W"^"NF=1-,9_#MIV$O@8 +MJ?CVH59E*#IEI,\6-,E1)X"6I[>EI(F):I'=9SI1EAJ\>H.4Z7H6<4*;!>'G +M(X6T6G_I,KW%Z=)$/#C-U9D?E^R;=*A>'N1)'Y49RV+)\EO +M9D"WW80UPE];FRJ75M)MU$Y>@$49(7^.T4^%W1;D%FJJ`TO-CBX:CFBU(I]N +MRXR\Y_F&E1Q5Y3UO/Z+`3=0*_Z9PSXZ#A\X.#3EM9V=.WW1]Y17EXG\89PS6 +M437HJQ(XY"/BKFW-=ONSVX1)$*-WB?,88NTR,;[^7&Z(MD3[E-$T_%MSP:?2 +M8KQA$[UZZ8PIJ%^W>A?%7H)3?=Z:11W<^S2-;:XJ!XJ=VX._ZW#J7=0(/4?_ +MDG8W]UL7H"+,WT-D_OC\]X,+%[#Y<);;5O( +MJ<(Z']&#H3\C_HKQNM4T:_7.R]^B:^9R!?:7*9O@(4F&+!$\6;TIC@&+XANCXQ=HJ!Y.=O<+\Z[RA0"'V89=GUBV3!`BN +MH)":X;=3W=U2AX:%4D--JPJ,Q_.EJ`4CGW,;Y`/48\S6[XH(IUQKV>MHYI,_ +MJ6=A_+?(A308\#YJL6^^=L"C,<-+O00+Q.IH,[ +MJ#,"JQ(R*MZS,H@3'R-DE3&*TQ09N)X)RG/`B=A50M#_JL8+@I>(024MCU30 +M.PU1I_@GR4<+Z2\AC+=&VF:<@T;Z>:HJWARU&G5/R0R-Z)C_NBZI7\%M-O() +MB@#;P]4WH%?BUQ37-F-7FK9,-DQ)*&4_3P"J=8>%Y(CCV?G())\]JSK7Z0CI*2-_J-MQ4]N8F>I)_, +M4[0WD7@9VG`$^W\SJE@P_/^.[+@:P0]GR+'@E0AO2N"W"IEONH"W,WR-RBI= +MPH=T"*;7`=*O]%3ZNG`$ID&,`[=#F7//_#.CYC\KBRS?/&Y3<^`&583IA`0; +MWSMY!,:%HN5Q=7I=9B]#CL@\, +M[FE1+>$$4GV^"'$WESCG#TM<./[=@=D$Z)*HWLC9I3$2!EY0V4X*#/=MCCY?0L:)P_Z!T6/N+JU6JO2/;5,4.L\J_4?3,+_*[[6N9 +M/3&_#EGBQS2([_Z;@.1ZE"1(?JXHC97'8_0YS2U@D:7B!PP4NDK/1?Q0]8AQA8\I#[5>:!$5 +MU$9E1,\RG%15P4LU*![O7\@?Z5"/@$9>T#LO+C>DSI9BWEC>Z),6[-GUUO0QX_`5)E> +M`0>C'%>XWFOM8CO[6_P?Y1I9D*JVY-&DYS[B#;@%E'T*[-"?N1[S@]47.@I/ +ML["*XYYNTUO1!UZ6?,MX!MIOR53]-)&8KS6`WM]Y*R#D]M^#+C&@=U:^E)/K +M8LUB%66)-5WCQQ10VD2\::\=0PTBW@/XYE!F&O`&JG?IM''+)L5O@P`6$@N1 +MVW<%G<[=T!=Q]?T\=?# +MR;[W!9>K``@=Z>'R)UPO2'Z:I:%D"Z@A\L`,^DB`$4D".+98^2C6)E\XF#3K +M-R<&KJ0**C0@L:[K5L#.-IB&'Z74*>LIF9;*AJI3$YEJKIN+I*\"^\G'&:/^ +M$'U]8Z4%'$<($\SR^7@R+:!#\I:9J"%"D8'E5$%O>A8&U]JT.H-3V?LN+"Z,#O)B7)T;"]&Z"4@E>W1%;[ +MJ^GMMO$[J08^Z2POBS(O!9>.EZ`\I59#K1`Q(]%2O*A0@Q707)7YG\EUK5N% +MQR!^AY%0E[*&S\SUH5*SCS05]&T_488SL?=5SL:<_[6C4IW*>([,:)S9Y4#S^KM6HJ"3@WT5R).I9MIC98Y'S7W4F%SWQP=6L\ +MU*.6L;Y2Q=)NC9@:GX$TC\P"(/K*8`,WW:EA3W5D[=4.8`5CQ^UN\YD(C]_U +M[W@%;TX)G^C#C->H/V5@NB;QE4.VFQ,N'Z8+>:DC67_62U/Q#*!%456!HUUZ +M:T-1\LU=I;NGT=1303.FJCNAFO_T?9!([_:(8BM@L,8W0CW^G)_`JLB.C=(N +M_IN#[@`.X<'HZSJ0AM9T>V'XMI7HJW;V\14!4IKFUZ<28GC?3,0Y?6)&[;0I0 +ML'[3`A67!=3#9PL>.$TH_;%ZJ:-I`V3[M"(]@#D@&?8+NFRKTM2<5F' +M_7%"0,KDRC;&%T=ENA$J`;/@;J22Y]TOE].^;QD;YIN@$TTS'C7^DE_7Y8Z5 +MW6A,*:FEB!DK\AV+O%5IT,6C,QKQ2N +MK"]I5\3[)3%7T7DN1/B3UY[?FI&J*82H01KVU4?I%B2DG=QP%KH%U6N#A'V#971FR<9E]=.$:U+6YBC%LRKNN1`UL3U`9-SMM],%``+$8%:&$HSM)#.+V9;JI]$SCTW.YNZYC8; +MI;I]5-LM@ET%)Z)K24^1#$ZVFLV'#SYH+94Z)H520BM'^=:L`]/*^;YBTE[X +MVF2$,"3VO`S"J]!K>'0HH^@I;^>2\/^&I,=U`VUEPN>@880;"K\2JIRN96P@ +M/]B!3:&)28QKKGL9^GUPT0(V\]QU/*46O6@B3WH"]S(HO0L0"^$U>&\F![2Q +M.;!GU<<^X:9+VE:R\+""4FD6^:I0(A0:[$6.Y=QVJRO<"F8]<]C1OMX]WC]3 +M4*)J&9#EL$XAY%2>L?[5ZPKPZ<0`SE!:9;R +MMI`D_K=B(;H6KX'KO)>HN>LR]>P[ +MF&NG^Y$AW\T,<4_XBC]?;EM.WF+/)HP4C*C9N4ZT%,:"-GX1>TKABKT_-BQD +ML?2S=F9GQE@`_+W%PA6N]*Q;88(::.6/_\E7^J%ZJ8GVDS\YZ3COR$D3L#(( +M#7859WPS;UQI`+WMMOL?3GRJGCH$F=Z0PVBL_%.V0Q+`C)&3&;F)D5D:4R*D +ML6T__?5G/?=8EB*WI"0R]%954QY;6J[:HM!:^(.(/DC*'"7PJ/.]T+/AAL"Q +MA-(!_4M(\UG)KVOI**/U&CTZ#T:FE"US`E)VW;7O:I*J,%75C/]??-(5[7,A +M+CL1J/@X0?Z-A/'XG*,&3QW-[):_F\*Y&SFE9'(5?D +M1X\0Y^-1[(@O#(9C^G1$#7:B<9!H+97#%[^/INQFYR)N;/\C,V9(RH@MTGBN +M'`'8$?8RZ&;K6@$N?@_Q"MDA3$DFKTMH3W>#O;>'1?`*'BR[")C=HG-W<^W6 +MO?"SPL_(B]16*EHX?.S+@M3`:D7`#25A9Q7G=PH7*I&I\L=M`-"V!J%DQ?.6MFRE^YD]'$0856"/]%ZMOJI4(U)?%%T +M<3;G`B+L*]$:\I&/8R;_1185<";#EXH=!_6N@/SO!:>R@`/Z-T!W.8WM,#,: +M6WR.4C\!65>I;7H<*[G"C07UU7!A7D&;EA+!>X^`-T%K)L2,E>9!`96^:FGX +MR>RVA<3Z9$#5`LJ5;$@`!#_HJ=.!BU?3T`=<4 +M-0#ZHJ/[(,#KXXP-[2K%%AU'`_%RYQ*CX1.&W,=D<S0#RFMUXXC0 +M_4APN/[(VW:`+A?] +M[WK3T.W0X1@_KKWB-R5G!I=7#^9AM7T]DS2&=I[A9W[("4PPE?]^KL*8G[\K +MLVI42V33><-*+*_Q:\:5+Q2LR6+#*3#YF,=1F6@+A#PHH\ +M*V&SDO5+Z2.4!(O;"-V=`C8T3748KQJD109V'OA#_J^C>QRYK@!%^8/@^9[U +M_>M=U7H!^!_3LT0V&VZ@"@&@:IJK=>YYZ +MO:Z,N*00C95.&5H\_5=YW&;:Y;'-#PUUEF[X1&5*\^$/=NUZ`^`(SMS&M2V, +MPH;A>/82//MF3[#AK=_0%JE\48'.RXV*7TO-5Z`\5(4H1C&UM$M,+KB`NN%R +M[+&%=2:7H,22'^933-(U+]-U>&YH_V[$R>FTURM^1NHBT3IG^?OA9I[LJB3< +MV$I-(Z[87`AZI*HR3!)EN..Z$"^R2S\TO!8X`#>S*56,L[6I%4*/5?$/)KVK +MQ?J2"PU(D3SXQ:%D7NG%II1!Z47FV]DK1?<"9YQ!]#6:S1-U@6+'QCB9%7)$5,C,^1::RZKT-R("8F;*2>:1FAG*.LO>.4``>NV]MT1'_ +M4F,;PJP_9)UD;2=]9D7KB_Y%NOO#F!U76$LJW +M[H7$@S-EP01IZ#8E-`$&",S\QN,$-?_"._RMI-N`65.+A/@S27?A.;7?*#VF +ML@MC?!;1!"TO/!ZNPT'V&$9%#I;I;JSU,RKC`[=!*\QXWWB^FTE@"W/@Z;K/ +M)=OVY-`XZ%MZ2IR%&L>(_VRQEVUW^5TD/Q/")9Q&N)EV[]=M-G"F32/J4.4( +M8@JXW`X_6&,P*1FZE("C;9*]7'UUFT<1CW]WTX +MDP99PM=`$?K:8IFF/2QO?R-`D$N?V@H1\//6R`*A1,@K5@#V5M!N9X1>G8RS +M);&,.48IF>[GO%1%3$U&HB?&G.&`6*K+6V)3*N_$!I8?7L3?G<:'S3TEIKF65F#&4C,@'K):?F].O4B`:TPU\ +M+SYU/(A-%XT_"K4#G^5]W/1;#F)O3J0&HS41T.1X)447`-]G$]*Q:QI`C:2Z +M!"%;GH+WKM*=PC=CQB"S&H9JA.9U*=)I=%M^75##B[\0=21DU[;SENZ:'+ZT +M+8,J9(*=B%)F>+MH:*TH[W\9E0WBA/;HNRR@@4,&]H5=UPD +ME&M/S'>7/]`LQ]&2.4':GQQI*UC$7CJ3/'56(6^`TR4<@[O%I=U +MZR=S';SV.'=C[2>`?KWLOO$9G&L@SQV3(_%P+2(,(0#,J^6Y*>XDN +MXWVV,PV>Z=E@X[;&$54A"@IP>YNN(PN7T;2CRK(HP<5B94UFN5-PQQTN=FY01Z:8RP!17U.9Z5ZEXSC=MTSY4&9 +M.5H`8=QU,)/$-\U0(SC?/W3V +ML@E%:]HMJJ+KNMVM.CS:4GRC6:1S^?;G(RL>]Z*Q2!%WTENK-L@?:/U(6,"N +M(U?[!4U+F3L2PT#-NF=R4>`=$!P?+[]&IZM +M;,F'?;>3.R-J1\V;4(.97#0UHF.>R-9\ +MNN$7XPJ\&P7M9P>=T?[$#!+Z0/FFR1B$'O1^VQ<5\.9#Q&"G;4>CF3_R`6V*K74"^?AS87+;"=>\PTC'9 +MQ"4%VU\!@@`:NX5#PK)[M[+='].O_0]Q/>R$ZIDT3=A+]6#XUI\`WI@/"COY +MKQ+BF[65)+_YSRA5,CAXQGCY/EYY&4$=M#SJJ*U*48?0[9$Z-D0^-KFN<_=S +M2RZTJ^;,2TXM.573/7'ICENV60V&=QC4ON1JR[=/&@B38U\/`BGXW.8KS^]T +M&0J<=_*A%K)=.D#F]P'&8-D*7PZ,I3!3O>69O7,45&"PZHQV"G!&R1OF/Y5( +M]*\']EG>@MB#@)M_$[&_$X]6NLN-W+^HIMTPZ`C$70D0@,"-`;_;1LQ>+>R1 +MO]2KQGK4&,1:J..X[R0N'V\AWPY==7F`/H!R++$ZB(>"N\X$4M_+:IB2ZE>L +MHY:+=M2A5>(EBK@FZ:H:E`24LH"B=%*",0+G<$'-H[_-VQ2+C.BHD3/(7A48 +M"98B<#S>)0:0Q+&EC$($=RS@":Q>]^K.E&<5N2)B>W.>E&">1S/"4M(RTS<9 +MGO)XINFPX+B<[?DE?LW.@-M.G6[5J<^WN-.22?=P[B2YH%,6B)1OZ2DCO3Q" +MS]XXN&@W>/%^_:7H5?+ZR'AA3_60('*(0@6'0>2M^]D\3[YHW27C6)\1[_U< +MN@G_K\KI)`"WH3B$NOYPDJF.?/FUD#TZYZK,,34)-V'/Z:IQIA=@@D>"?+_37;[U<[C +M7C@F','FAC('M%KY#-*%1V^1U?.6P-=I8GT*H"8C96798+Y.D<\R+#8>LE>` +MN%]5=XGXQ3,I#6]_O6_L0_]LM'2P4=RUFY"-5H=FHO.@`.NX'9W&)J4OEP2( +M<)*)3#U^-'(HE*7U=24S@^F8V+,"JB5%@(N<<10C.3%QHHE#Q:Q!O%^%9UT? +M8CX\56]"Q6"ZNXM@TJ/%@,;)_JZ[`^56UYA)R.B)U_4B9PX-I%GW.96ZRED' +M#&A+G=G.#+@O'`[G_5]4"[@=BKWX:J%^<+G7#3WR8(A^PFP,DR#SI12DO%!:5$`14^C" +M4J*81(E'0FGC=Q=>Q=13H!2-2,I?6F[(M>F_N(]];V9C78N6Z +MC4UIKWUT(!DW^%X8:UQ/Q!%J&#!-HQ'5X;#]YNN<)7#6[)`WO' +M1)^D9U%6&"80D2O^=$+?&523;>0KQ.GZ:)/ZO6W)X[P*"VH!F`G20ENXF?-^ +M.^I55;?N:<)*AG7(5J.-8=`:`565@3!96\[6>`W74X<\2;C2W<;&A).DZ]X093OY\-LYZ4@H5=&*<@5%MD58"YM50K +MDMN!I`PC9X#FYNO,H!6]@0'1F[)LB?&0LE]##N?8;%4&J.U:BMPP;+%0^/>X +MXX;R`$F;IM'"MX1$CI'+W4^$"->)9?:XZV\7!P/2YB-MTGX\D+9;B1`/5$@M +MU26R3'"1Y]Y2@`W+[9"UQKL9TW*9)H*4M429R93M%U3_,/M(]DZA(B:1 +M(7/9F`UB%<)5BIL@M6EI0;PVM%G@Z)VP1*=Z-29D%/M@0\`4HNHR>=SG]Y(1 +M;FC4#B!RD?XGAGH[&3"62P''F`0;:PV*7,8&!#C(!J;U@:_D*]SQ"=9.+Z#MFKC%W[=T1EPX@Y"T*-?G*("M2NP,OL +MNOK4G8OA$^K3^J8JBH1LI8.=R$I?]-IW-:M&:06NX=Q5>M$V2XAIM.`A*C&& +MY#L!E;_U[SC;J04\($P(KQH%QNA=-(!8OOO^LNC2=X8HORK'!R8;*A6N+>=]C^`+D!BL:`>U10EQ +M1/J,U7)--$4HE\IG``=Z!=>[\8'P%CJ=IXN9++M1W1>PU7IA9^<9FM?CA[Y@ +MP?&W7Q]W8#1W$]`,)5Z(.3IC[KHKKPQG=92]UH1E4<$1CL&.O65/E-BT+G8B +ML[AZ+AM2.UY6)8"W.6 +M9-99WD6P)8_Q[U#-U*1QC]1AX;O[BUD#:0K39LLK$HKTB`BT*5RVIO?*&*JZ +M@+_]T[BK-CA];8_?[NB\Y!)64UK5H^IV^:R]^3#]<=Y@A&*=[W7.WYMK#3@2 +M4E2*:9Q:ZNVCJ;?!(?`=C4@-/Q^8HK)$I@U9_(2U!EM"V[OY>3S,Z4C2W$=! +M2B8;@QP9]5XQ=:;E'(X\_%H.J`2D+:A1'LRT`M(56/J?R]MD#[^\WM^.<>G, +MD@L&&^-K/@VHPJHOG:XGHXVIM=5&KIFB#\G0GLR28B3/U]%'6!8./P)"V1YY +MV:_F<9\HVTN+TN/`.7COS0CN"&H`=^W4]EQL'7M>?U$F:5AU8Z0I,$")TO(5 +M]'?T!R571H4,"_8)Y-PQ@=%*:S:^60?_'Q3%6=,?OVS41_5OJ$/]RJ/ZI'05 +M$A'"\V`$@117G>32'WTVD`5><'J4AS[@&E//:14=$1+>37AOY/`DKMC5MTGIUEO0RTU=%DR8H^A.@42*#0=ICD3/"O?-P8,-G6UB(LT.1U)0X0I'9&0^`%JTN-Q.;!&!,/;Q'<0B`N;V:$ZUECS +MC9>@-LUX)`SY:5,?&]XVE.6E)#\;J:\7^I.RY-JL6<=T`%=AGP]6F!H=A\0[ +MK@10WX#AT8DW\G'_3-8T"*;:VGEY<`IIE_0 +MX;UFQ-INZY,1)ST=C/IF'45FN=*^FL`1OF%3=(6)14Z'=:U +MA\4,PP/RKS2-NXQ/"5%K"V@C#AGH;:9>4R5#'B(J\K17),CGPUE4@3^7#*JF +MPX&:OC=HD+AK^C\:7+;RCO4)/0HJ#;9HN+($FY5)GX,=O=3GI7/)_=C>R?#2 +MM!J:50*_L#O^3UX>:FV9(FYMMS*"8M(EK1RZ]O%'DK3IQL,86YO/5U +M1UT=H<(WO+*1E]O8!E_7`194AWN#"=HI$TYP[S`U?%$!?D[>(3N +MO^I(.W[S1N[^BM<=YT$<]^`T:*."K]62%L=38OR<)`61(A@M<)VL[LL/V-2WNN-X/:'H5UM)9G22>4'TRJ>'/@+?G+=_!)D":7MQO& +M3=*=0LRVU82:\`MFR!CI5,7J:>8-)[R&<('B0=YE=&%YA$=!EOT9=FD280:D +M(JI+3V7`;/R:Z6V['SV#9GE`D*03!0&GP'&+/AVGT?\TZX1KW2M+\+G"T+M^ +MRAABBK#G"J&L=.I\2=/G-MDWUY1YTEF5P78[]HT%FD&53ZLJ(L]">!# +M1'<+(HL;:0.B$/3X9S;+=^%,(AUGA[ZN"14(K!9H+&K@*)EV'R4"!-3"O'<5Y#H;6-D0-`!1M)_YXY&E#L_BU\%6)LW)_I9U._8` +M1S9_99F2Y21+(T<;BLL)`9"=XWUI$TIZ,O0C]XC=.^H;K)]4241^6*H&]$N" +M-R!5H/Z4996PYQFSL_&1?B-LF(3M2;OZ[@-2U]_J.IBBA#N[YD1,!N.@TP6U +M':+I35SR$RI_W*1U;EEF6O+78[")RG%"NVNJU'T76KE$B8Z56[ZBT8L?9_=N +MN2@\S]I'TN63.ER*ABGZ!4&FG>!Y=R'CCQ0+L93UX"P\-!^_O6(,,2F=''?( +M>X?@*PW9D5S-JKW(]'>#>UIXS8D.1"1A?Y%L6\JU=8J:VTQO::ZC/;W)9SA) +M^:0)UD__.9Z29!"S9,X>?WQ[S]$?JXWVK6AE;R9Y/O:)"_38\?T,$I,]=G1C6GU:L!"*TR7.:5^LD/LO'"BZ9>87 +MN58#WCXJ(V'MFGP4BY^^_$;WC$7F1VLD8EU.VTQ]]>9.!MAG]Q>Q24WP`,&K +MWRZ2U8-*WKS_*L*%K2:@$*D;68TCF!G*E0^V<4*H4R46F2A56%;NF+D[B,Q^ +M,R#1]1@"(G;@,0-806ZX]J^)P]7T!<@9NT[Y0V:(EU'_B%C&K+F(BKT!>135 +MBG@,2"05AB2%H."P1C0%@ +M+-P3::TY,4D.DA^,CMA(&;O])%"*"(;FM$KT!`AKX3EQI8T8^\1OL(CF/'"9 +MFRK7'6-150]\K\-U6P'C0U_\=$T*].X_IW*.QZ&2>UQ"8EL59LL5WR"D9VZP +MW.2N?NSM.41&2MFLY_T\2\[EA@6>M-O6M\V\Q2I%S:QO@=XEE#B6$4^*TW_" +MS031OV?T1F5%34^;0*[`!1#.T[]M2N)`+@U+5Q"AW$Y5JE9#LGFG^>OGLLST +M"$H@PGD20-O2VDUSU+6&6/'M3W"_&*%M2F,V`:_R$"Q7XW+&?:KY5W"C2!V# +MR,HKP'"J#H"MO[G7/(5;R%V8^L$F7U^&_]7,2>0?MCPRPXKXNM/_E0RY[O@G +M7PW?>/*Z>PJ2[3S5]FB7?LGOW09/_]L=(3AO:`F6-6)Q^=>,V94,13[3RYL2 +M7$8=.N&Q+%&M#>O5R:B700)KRI;XJ;Y.X2,FS])MJ?.?Q28>\1TG:,26M"A: +MDTU2/V28:Q;YK)>Z[T]/@8L'4&W5KRB+QF%,#6\@IX%Q6]0H]PJE*A4D@.#C +M#_2*B6`Y;FO^'(E28JF[)#4@VM=$R,H]NMT,->>K(0IW<$@XE3&IUQ*M(K%M +MA9F<"RF/LSS&$](D?\T=880Q0J[_NC]':A%I\9>(%L21"D'1+:DM")YJF#8< +M@)(5/]H0BJ]LQ/-?612?GV/[Z]<0UQM<4O2LVQ3T$[,U:'0 +M9!GP(4S:158Q*2[4X'?@=;09)U=/ZGCB$MTG[MS29[\@LR)1YI]`&$K*$O-_ +M*Y!U&.EQ)!6O1.P2:BORK`KI;N`6"#_SKJLUK9F][?%Y<*/"$[&%^T^9B^4D +M:,.F!7OT>A5\%__$;EAT]V/\X(@E-YN?OX^8S0F0^,EVE(F8`1,7]D7.8M., +M=YY$6GL=-0$TKJ["U;J^6?JHTM3;+3A?;0)5T![-CPM=KK-W.@S>#=C#BMM@ +M5]B_=E_[K*9]C!1.:=1$W!#VV_B!J!W;'\.:"$>^#WSK$F(3"2A$4P`M7`_P:.PYP8%7QJZ#Y7.QDN?@? +M]`G[WBX[C\"3S^T^+[]W4?FQV:2GNI1^3./NH('D,JVV@\@D/F$Y_M;)EJL3 +MN,YU`I?X%E*_TNI]YN&V#GUV>\:!WZ?#RGI?"8,ULM?0@ZRH`9$ +M?=H1"BY9%7!R1>#T:)J*=_6J@.4R^QMB^&`IV8NMW6>T\YY._(;GT^CA@T"C +M%?\6D#M@IBCW]W0V'H]7CEEI$8`A#([AB;)E`ZPD1]];SJ6K5*(*AS]2`WEJ +M'N,!O*'02[/LU!CO>;@649`7P/<1HI"(N&9Z+>-]J="+(OP^HX+3O.W#*)WY +M0$NEC0]P*[G94_B^OER?#<.U=C(D6A?]5TA3;&7Z/K^X`/@1"C&W(BZM3`.S[D/Z#%J7N)V7I5Q;;Y. +MHEAD#53@89J$9YZ"6,M9B^:-B_IATHOHYQE283Z(4H*_QY'!.Y-G@QR;6;>D +M>+PQU0E''O'?CQU!GP9/JM?TM183#?TM+BJ<7T'8UQ`>(/9%",]Z3 +M=.YWQ`5MA=-%AMM:91ZKOR)+)H3S4E-(H[0&ZJ:B)&0HHUZ9PRPU=DCI\[D= +M*0U1M0[F@3CW/7X8`VY9Z_61L0NK)T[`J"3W$(,=F$^V!B^>WU[QC17 +MM"<[?:LVT;Z?.\O(,%Z>J_)NBM.@R/]%^9U&>+#C9NASW"GU5P]Q-QR2D'.7 +M)9TD+'&[5YQ83;M_??P)))'BIO"H&&(R3436[(=O=[')N_W-@C;L/?@`P`GR +MK_Z/2@VG@_7%?MFY97H'5*I"]$OUW[H+9`7$O\LU3E0>[$)5CGS]77]PEES'M..*[B]O\9SD[81Y6+AB8'#A5QEVZ\0)F+YC +M?+3.@"97]1R>T=Q551RL_5:96I7'-T2]?WS04F"#7:/1?WUV,\46]/K +M4=SPWT5/3D:+8KE@`1S2^U6"M\8EU#A<6N?3$=#PJIS=YQ.*>YHG@&)8N3&@ +MIWZF@8WJ+U*%^;^ZSP>@;2JOQW]4OW".!D'!I&]+5UZ?OF0NR===H,K&DRKC +M:1K:42&Y+$*>>%D"GY$5!Y<.C8.3HB7M]L#XKM34XD-R\ZO6XHDLE_%2&R>1 +MQ\!";_N;F,M3^FCUY`J6C73\"X-9YN;XT1V\1+"J@W5E0`?^+VVA1_/A$SE$ +MM?D@F&Z.S7.F2K%Y*JPN^9^LJR/6$F899UF;&:V<>P* +M$7,2^Z;])(&#P*/@+BO&0"YD48_JALJ4]Z74W3>!"DLXFC!QAZY%N9WAE+:X +M&\B?SUFV,4\]8P*\MLE;]$FN%9ZFNNYNSHXD/#78@"6!Q-S:J@%!M^U,7Q], +MD#GO1*$X=FL_;:(4I5BJKX??Y/B#-.>E>FD48W//$]:(WK.B*_JH$@[E&Y]4 +M&?-\?Y3RY0.H`3I?H\%*BAA:Q.=N"*1%3<)58%ZI-?L +MK/$14CKE-0C8T&.BY +MC+%Z&U#47^EQZ;:HZ-S7I9+<7@ZH`8D?%]V^E#&49VP`IFS5=#0<<2@2R;>\ +MYA7_AD!]8F7U\A/MQ0^/:S84:B.S&`@,M#+:T8!S1,O+\@B'A1+Q%_@0`?65 +MH.`W1,^?C2'R31>%X'9=@K>TCT&DD_U+!X5DK1K&5@<#N/1=STDF3(*F^5"! +MXWJU]'F5N9%29CP24W(S"%?;U1I]9<%^R08H.Z.JZ'F@@5;RX&B_G`Z=72U' +MI2@6*GPR4K'QDN3^=P_V]X:OE3&14=EJ>:+4>LP.Y+_W7;#-@:C4TL%Q`5PO +MKU=SWP(@#`9AF`U_7K@U/@VQ[`R*$Q;GILGN'PC#=F^AGEW"E++\7F(2W3$& +MX^EVO:O_05K"](SG(IR/#>.+_*G,3I.H@G;H`'?>""BA[^:Y1XF:<^5.*%U0 +MXD,ZA2R4'RAZEM%C$?8FL\2]CY%N)JA'R5<\Q@G4,<",WOU1:"<8]G)^,JWP +MP0YJ<^^Q,3Y2C\4_^9#3";@MEE,$OL[0AA54NF)[I_)_.__]XX0DH#^`L +M7-DCUO2GYKG*ZS[T3V\NYI[//FQ8WR!4VYM=]HP9R34AKYO@.'6ABGMB,+]7 +M22%)>HB(`97PXW@!X]V!K>^7S:FRV$.3['GC+SX>]B+,(4N3DX+'JEL)E!C(]_:_6*E3#?8;>=<*4",<[10W]T7 +M"[9RT<*=9Q/39N-PMT7*SZT.R&EFBFFWH0'`#ZBVL8KR8_[XA]"^CL'H5#2[ +M"3U22LOK[0XUR345G'WWQNHMF5<1*WNMXQ'([(1I%J169:S&_68*E%R).6:[ +MT39P2WZ\AW\[;/O)%R8[^1:%H+ +MZ+3KBCNEE&NC&H[\G'HZWNOKOAU>J"Z6M^;C&2`)+G&=9MRC!6;9\F=.EK@W +M-M[$B&#TR;0.@:!24'#O:T9WUL+OTJ'XLP2(S\PYQL+V2*>.,BS''+ZU5:$& +MZZ'%58C,>%F("?ADVDW'$?,\`(CXQPW_]YN6`PY"_+=)>W0-.(&Y8.5#O+GB +MO]$K$XTXQ4!>3G[7AL$M86>Q1-3+N%H4R3&>67]\;%\L&NK/;\MVJ\?2?ZLF +M2%.Z$;Y.@"0PZKGH)8O +M`S,Y74"4T*IW6C^2WT%!>U):#`O>NHX*&HI69/>05?PR3>.B",X2T&UB[:ZZ +MO!E=@.C%)Y$+9^S"_PNY(Q3[(M=EPG3 +M^GK?=M!>.+$978,%.]#?[$+8K\`VMP(53HH?'19)

HP$3\YC!.(R!865=% +M6=;YWH4_]#M[1T!>$37U[VG-NN%8&,#.*1S'`3`4R[AB#OC]J`Y0 +M.XA(,H"3:RG+.NYU`2.X-G^Q!*BB)1JB\=+-?*GQ"@BVJ +MZ^IPDG6BG5)M?[TG%5AQA/X+8"02'&IQC55H-V1W#QG&R,^!<#W'!TOB*4I' +MXP7EM[3!\>PM.VI249'8E;GH;*(T;;"N#_(S$X(Z]G[IK/"_2-N/2)0]08@H +MXZQ"\RJ+]2;OS9;J1V!]MYJ9?5%AQ/TEASI(3UCS,MW(^'MB36C'7W23E#", +M96R(?)<6N%YN;!BY%L\`9WP@G_.R/$#[]B937DD\4CACXO&IZX43DF/_S4-#9[^M;&MQ,7?S/_GO&9!KE&K +MO:S#5=5.B>8;5,7K.%JH7WT5N-DCG7=%5SE&82Y&FF]MU;BI&?VUWJ*MX!5' +M/E'K[8.7/6[^\1%#B_-KYV_A+CN9.11J=AB3TTXCF>G*;_@RE!!E2#D%S%2" +M7+C%,M7CF]9&*M^Q,XYF*Z>17123!&QDJ'M8J7AL@DI9=7EG\-O\%3RZVGJB +M1B%\VR9G6K[]6HIUMOQL2JIFR.FEI[QX)I0F!)$?](&._UZ"W`SKCH\UJL[M +MO:UARHEM43%LK`C*YQ,RM&(73&,DQR)G$P?V^LN&L7`=,CM+C&M3L=3PL\8C +M]'%3Z'0GP<5&-<,ZVEV21F>UUAN=R]+I/] +M"5R01LJG(X*9^>D.*IG!IA5;Y%@`@<`39/,ARYYG=D_"[INE,>2W%XV!3:ZA +M%"YL2$;W2+^R;BNSC"M]O6&,8\E#P8]8*CMKG,:'FP_`@]:FR6B*:TAC$M)Z +MV<@P/K":0@R*[9M=?>R27V[,HG)RP22$;LY5FF@]S2W98DC$UM9Y>X*]FUQV +M\XAS.W\@(B>0B-"-E"^D)<&:TA#%K1NW4D'_10^"T`A_NP7>R8!'B/<8#@M4 +MDPWC248(B_KH40(609&SX.XXP!"9/4%!GPH]%]PJ6M4Y/@1\@I;`WKBI/@%90/%!KLB"T4(_^< +M#L/=&8)"YEN?B:HQ/39!+S"GR1%7&-@B[#!P_&FM[:#WRH](^M;BG=%T":G1 +M$Y2[_Z]&!_!Q($>XXT%&5Y&ES-JBU=Y+8LRP#=;R%<\7L/#8N:1U"CUXE/#$I;<`3*\XW:;Z(>!P/DN4(`MZANMQ1^RMQ#OA +MD_LXF`[_TJ;#<4JSH#]TN$N%"\B1ZR@)^>KL(59>6O%:3XUX$M!FD]SQ,>CI +MK1$.[I9D9!^=]0D-.2^6LE_QD@W7E;\T:=1DAS@/,.%Z!^H`M<:W[E`<=HP[ +M)TP)\9H*MOQ7;F^?CG5J5E;E>[>_8"BI&OBPL)924(DUA;VQM`#8%+R +M_D-6@&_Q*`8]T($'BLMZVG\G^>:,I*(DM!\&-$=N&?BP\A^$F"-W2'SDOY5\ +MKN]^S/:2?BFU\MQ^4B86T$_*HL::JJ2IS46N!2!LQP@T(W].I&XHMC-$H>,9 +MBHRY,2M/@%<33D%4G+E[[?Z\&)U"@JXFVKY)\4%CF;%!J"!$CIT(+SYRS5M]6) +MKW@*=T;0TT3#Y0!U4J<&,'T5K/ +M\O6\4Z>A#RU@W>CD/:Q?%G&O/\\O2GY>MNR4D.G;!D.>QE2%T\*GE8Q:<1VF +M=[&D3,'7!DZH9^ADFEN>6WWYM5E=,OUG'!(+5_BF,MU\;#:7%UY>GA\=IVCI +M>KP=L^4]._@!ES&I7@B_D)AS\;O5LD<$)6$+$<4?807OH\_<_?]V,P\6P$,6 +MNO'C%]!*AIY@DVKY"+A,6_2>(LJ,N'-`B]=@"28B$]>^+UY(BC11`#H9(*5I +M\_ZK=@"EB,6Z62)RSR&.!=K'.%N7(7Y))BIL>'0$<`@7XR&]=Y)5BX5KBAQI +MJ4HYI)B-6\Y6/VTYP[?)@;K1":6#37MOD,F7*"E3RUF[OS(I"3S]),9`=R>4 +MON/"#Q!IFPB>F%F-9'DEQA6HR= +M'CZ%!]$6U\=YSDX+HN/`C&K,J&-[Z7QM5/P-JDU8V-7K5AOW8#"6C27M0!*? +M%O09A`U6$>'<-BTSBO9Z,WPSC:-I)]!CY/C#!(2%WN07OK4]4@.56NNG,^$] +M7\HO*U>7WSC)DK.^QW%J$Y_(-0?ANJY.I^X1?A1B-7CWV-N51+?!U%\9MK)% +M?)F_@+7?(S(]:6^4R\HZ68[)A%_,\1/:FWO7?[,?:GDV5;A7+*9NM822SYZ5 +M2DR/HM.:/55Z.4CL-=^RI0S-&AR,LT44Y-%1,G3,]@,YLL3_[GD;P +MPI+)U[7KK9E%KV7$6K@YZT0J2Y=-#"X;#[YSC +M<^"KQA439-EX8Y]:)5M9P`'?Q??WESZ73(C%<&+F,1+!XE6U;QN/H)R*["E* +M_P.,X&&;ZP>[,:'$F`4?9M>1E+X)W>QN?&N3CB@4)B1:"O)\QKC:4CWZ1_*YZ>0!=^]Y#&+1*C*5LL?0HN)/*G!AR;,,K))? +MECT`5VX?Q6^W%I:0OBP34##ZNA+EXB?94!G7YC-7"EWUQL01]XFM6P,Z +M<&U^\"=C>I$8JJ^_&C:QKT'0`)9`4R^9DJ.)H$Y\KXA(0>OU& +MO3W4*`4%+;-VQFY#,U;0AEY=Y8H[)HE6;B&B'<:S?(9>NJ_)A^)&K#H^D"?#EW+Z[-17*E.M5L_L,@$.?2PZ*V+?[ +M*G%I[7">L09_HXH@$^J0==N8(_A +M(`L;U@BJ5,&VCM]9"_Z`L8^:FSA*LG2YD:/D5ALX!Q];.KV'$DU/)8FMU85- +MLO`')N1GD9!`Q(`&_QI]3I,G=$-_-G8!Z1O#J?,5L:O9H.BY=CAL,8.CA28' +M%0.@8R>)D/SZB1&41[8R]&8:28)"J9,BXXD1N7T=39G)QZ5Z]>>,!Z.=% +MX@]\2H;,"6U::Z$H1RYLK)@>:Y_8)Z0CD*0Q]FI=VF&;$7/'."UUG&AZP:J\ +M=*?[8>:J6+'?5/0IZ3MA7CQR`(>8LJT@UPYT2E[.0J;D4;^LN48?7J4FR6B, +M&DMCZO'0X/""CSQY5$7"@E=\KXJ*6'XI^=T^FZMXZO_+O"3$F\"=!VI%"5M\ +MZ\L'8KL96B].-9%C8MY^\$DXCH(FB*22M2[7PD7CL%<;S`<]K32CX0T.B'6W +MT>'!%V"P2-HW*S?Z-)>0X7NC-@$?=TT'$4$#&M]T_P?J"8[D=L6XYY1S:@,U +M+ZAWCP^T!@^,8(AN,T)UOKK+:<_'36ZMVM`*WH`BP,DGY"\5.^^YA6XH$2JR +M0[/4N)RH"]Z5U.5L9E0=/J[S;XK4GGSZ8$5`5=,15D.",#V/DLJG9.`-(JNI +M0#VUXN$?N-F4S$7!M!K@>03!\`*01?G&O/+:8=GK,JLTK5].`#,`-AP].9\2 +MJ#'JJ`W##I0(ZG83;8Y+,RU+-4NK=-9B#G:*3OS,B14Q[7&0.&;'"1B?6?ZY +M%"/]NSB^$:0#/D=0=QU"?"Y%G<9>N&BR,[N3?P>*\G!6C'8V+H5H4Y8$F)(2 +M[Y?+)JDC2#R>R5D'E`9K>=E(4IEA"=OR8R(-5B\1'S^L@6??F2LD8D,EC2)R +MY+[`73IW1$32Y0:DN;3R\+34&6':BT;;X2F0,RJ':>ET%/U^&Z?US:EDI-=V +MT4-(SX".)&7I,^F")X@<*.B(;[M\*30B4OE%F6-7>I&!1BUJ^=MO^26DP@CF +MC,LF-Q##66]F-BU[HYTQ8IJG`I6BQ!F07U#G%UK$(H)G\)]L#IZMLK&IJ$S0 +MS&IX0[FT&'ZVV7.ZQR%[_;,GG/"@_E@9TU>GCJ(&ZS01LU_R8+<(.FB^4C%J +M\7=[L>=UA+B7QW%_0:17,KBI\&)1&=A"W=HFDD^IO!"*C;U@ +MC9"6'I64O*^I#XMLK*<()CA#.]IE@%!%)4L +M*P2;C?-AS1J4=.HAF@4*:F>?$8)O:>X#B`'9F1?6R+"J7U8[T`=7D8"YA?[33)Q +MSZ;^(#0HK1*$U\HWH7NHOA='>MYIEYA"+($#?A3EI,D6B@>^0UC5Y16"R,R0 +M[%XG10Y#B"3BW&N:))'WG21D)B>;EF'>E'=,5'$9$(IMYK6,PW1;7='AO<78 +MQ^E73$8#8MK$OU=EL3"[^MZIK-5'OOO.;6/5U[]/@T?#7>&*+CH02OJHKVE> +MTW?\$W`=&W!>:#P@#+=YICOY<@?)/YY14S:\/)'MXRV(F$?.2O>U!NT2&7BU +MBY)&1ERA+G#HJ]05[=S+/;Q@)1B-U@M*DS`MTM-P0C;.CN,EL0,A8QX]I=2$ +MS^J[[E5&\<&$8KY"*'R>(%M!XO&D`,;U<2901(7+FU-TS@.>19;7U$*1XB^Y +M?BT>BT6X`84'^8"*P-UMW8OM.K`V>%81Y6[;U"2'5I&&=YUF60DOA2)Z+9OT +M0S6_!$>1QI1G1EYN/H_$I,AI1(!&J$9J9U:P'"?$YE_+`AO&U4F +M($0(X>IXF>E2\"TN)/;/L%>-Z2@#H7V02$_F!`T*I)H_=,B'J/77$R^HL\LQ +M_(\5C29W140W<1Y]UB8,L9R')8`<;^MZ:MBK0]JE$:UGIMOQW&!UE7XO`70M +M$956I&!3ZXWJ+X$JST@^ZZEP9HH#_&;C2!M)C@YVV9GU3I^J82)H(85GU&GOV^L5`)QY=HZ>U65+D[EJG +M&U#@9%6EPNX'AW\L!..DZ_(!`Q0!O-B,DP*7B$_:<\?&E*\YL)VS<6DX_8L$ +M2O%JUD8:^ET_8%GBS;^+^2X?#I.[_9.8QP0P-FRG%(*5?CKN;H%F_!P%6AL; +M3+%1%)R=]-^!#YL80]FBSZ-$'D/.1/EH'ZVI^S\W<7HH->$`2G^/,;TB-2M/ +M]3.(J8I6=[!JZ+I5`8SKMS3_.^',P'Q(0M#647A]L8R9Y(L0O7=N"JW[0AYJ +M,&0,FDFM;:91[%Z7$!+)!6<"!T'QE81-_-"GD4[+L8ZWKI59;^TS:"SBN&^) +M;&0M'[^Y&)E]7;SH'&+"\\L/L8QS+7(E/`>CEML#:/%K%Q0,,(_#EC;*-5*O +MZA>)W2^G5(,'$C=_:X6@ +MF6\P-D:1`;6H(CX6XB*"HEQDUC[[>$I!5_"_1&Z"/JZU]8%"O(1]R%8C=CT$ +M-.2&0K?3V)9C)\^\O9@'5&'KA+"H2@TJK-%"+)4S2IGM$H__LW9.&EAH3-KZ84U:6?B9KJ^U8R'FYYGZ7LS/$&CH>,!*T:$ +M6J](@.XJ.4',RJFCA@3:IH]T`#[/L_SI20X$W16VPP=7RV;-V[\K>D%IUH4, +M*R"(LM74AT0V883M=Y4R5G5<>?/!@,9N+\JM[9+SW_ZG^!IOD&+V0=II:.NK;5Z5-UF`43)UG2K.?! +M,=5O'W]7^Z-)AI1@*PD75FC*03Z4%KB<8A+G)@R1\G@07W-(Z*&/AN6. +MM<"6F5@93`K(U_=B[9],/XL-MGS^W.8(4M]7$A$X":$I-S,W"*]M;CDH:2BK@<8OE:0ZEX\^$8],@,$GWGQBW)#%GR*7,)OAW_MT0L,$!>$@+2 +M2OM^H^(NO89:+];N^[>Q!L3I*[?YU=+9)!C"@9*D$1'=115-KFMU$-;!DSVU +MOQ#].K?38\Y"EN51 +M_1=4PE1L,FCP`M>VHS"VM2N^WBR+A;%70O107*N$1C&3=G.3"-[*P37:IRG& +M'B[,#@)0C;"CI:>*C`47-<$18OLVEQP\3NOX0Z3W$\$J6?#Z$+$!:@VMAB_U +MDW.2T7AR^O;K.3_A=;A1;N`,G_$Y#1D +MD(&VO8W0+DC_+CY0"1,]A-ZG8)&]NE]^[>D5*BV6=]_CS-B8DBGL +MMW$ER$E"MQ[UK*23IQZ=>&V6*9^*WL+'PC.Q0.L&['(4XUA&JNN@ +M._\J>2YLD<]E(5>AT^'##NFM%W3+:Z4&N?4P$(]`F`&$!4?/2@I]8OG(Q5?- +MY:NPZKE!//"\E2[E%3N/X%SSGZ0-OJ6OQ-O;E,9H6#`9C^V58)!L\P9_A;'&-V0JVK2[%HW]@N/;:)91HU +M$`[O+UMP$SM`PQ;=(T'[3J-V\82TQZ".73'AK&C@2M6PC$Z2:-7\7/(_(&]&]4TCC#4CF,"T@XE +MUZ.#IS/=<[$^!ACJ'2Q4Y/"03'L$?V76\5(8*(TD+UZ +M8??NR*$O<5[N)CSH#Q.O-YAC]2,33+\Y*UD>?'67!Y`'_ZG#?X2=TBLY@I== +M6!A&]3GR:$:3_E2&#[2\H\-Z\+5IEWPT@HHW>7&F=XELYQ6Y)H526_@U=,"T +M""A3MZOW;(Q11T^^@RD;M1*$V,\D!_\*]`S$^@6W#?>&O$9P+<*?$T"JLZYL +M7M?Y-J/[A$F,\8`%O:#VK@?TU@2?VZEYVD5HWPYQZ$EN?WD([Z.4LM!\#F22 +M\HW*D]RAH[L!#:LI+@PG:D)W/HI&@A$C3:$B%*#>(L<'_H*'4MQN\TQ@VP;\ +MR?=HLFKU:@+^MA>*)$6V)CCUV9`;*?*?JOHG]ZX0=5U0*ZX]5!$XMSD(]_/? +M:8Q*$3DHP5]76WLC,V7N*Y5H;N$:@LBQJ$H5'8LH#JN,CUT%*=1.&KCVAT,T +M`?=J=B()V`5-F_K( +M!O&6NZ.)F;=71TWBPT`B3SWOR->="_7%1R>T+J(;$ME@[`FB^]!%!#"LCK+$ +MJ+!40]B->Q"SO@JQRD$:S9/EBNUF6>+TFP/&%N5XQ2"*M9"?R?'+\,G4N83B +MQHK]?B5?F'@.&\,$@\57V;<8#KND]1_L8KYS@QZQMXF5#D-@'ITR2V%RU<,6B@`&2S0HP1Q[QBP6IR6]%4>3$ +M?3(/@"H=K17H5XGD]ZG$`NE-H,CJ>&,*'/:;5V,K#AHM%9I<`)G?U9[_]+KH.Y7]MUR/)MS=,3@JKT +M71'QI:;&:BQB5LE.;C9-N9Y5Y4Y./K6'Z/'7!'Y,^WN*X`)]]%\_<$T"AQ +MK%(O$=6SAFY;A,WV3U;CFN/_=(=UBVL@RR\5R3C-A.^OIO4"1JGB-D"7>;$E +M'4E6I!2@\$",OKR=O=V603,5,BRTJ'UJ9%:4[>XW&I_-%?JN+(KF`,WZ]&L` +MGORBG(K07WYM,MI`LK[P!:AA0)!H^]XUU6^`X#>]8)659BZ]H:1_B4C*-WM5 +MH%$:%&0YG>J_L:M_0A0CLC[S5DS!'%(\,6V'<9I#5-`Y"XTBL]`1F2[1ZLX3FQ7Q3^A@XAD*G5;B.NE1C7DPL+G\OF,G,\P8NC0 +M4:ITMSZ5:J?*088_.=RO9I@=[506C;KH7\;66P1&Q8$V`G1QIL!S&G/4V+U( +M^38S^UUK1\%L+510B/I0Z"F`-Y?A3%$^_V/H+Y-"CN#6_AQYS/4)B2PON+N( +M_"PT9J>V1^/9)Y&_X:V^CRCL9KURUB"+99'+82,EL67E&4SQ0YW)CT+%F#BI +MF=FJDD)Y`B\01,S=#@1Z",`-3Z5,LOFNMT':6U%'*D4TBO^GNQZ%L@/MC>?L +M(+B2!O1Z#RUG>^OK0?KL\\]=/G\%IB>VPFJGMS3#K>583`>%*]E&>WR(XPXR +MM'R63F5KYW?B7!HA:OX59O-H#2CW4\,V&:H0\%NVU:&#>A](T0WB!N^;:2;N +M'@,9M'5?/\>@BF,TTN8NJQ][XE@73EL\=,*9#>ES>22#H?7#W"=\BG4:=J99P/$@"% +M;8Q<[6<5A_U^3A@!@B3VN8Y0('C=V<2W8V[MBF]+Z%)$,7/H89*31)O7P]3N +M#DI\`2=?;FM7VVN,WDGAH6'$24N+C!A;'9_O?OW'UK_]W6ZS(<)3$\O,&:8N +M.82NYMK!8(&8Q'6$;,ZPF+Z0*VOQ\C3JZOFWSY?@0&0)3*9@[_S4$^,R6&;G +M*3>T&YVH@+!&67?&;R![+?>K1],8US0@I"W=Y&I?O?_AR:5;M>VI)P+;MN2B5)XGSYX_7@-A;0>!XP.ID#3`DU!<]/#.-\(^?JS"4LB! +MOO>"-4S75HSIK'^.'KLWD<^!JO<")=16A$ +MN5VI#`K+C<(VZULV%3"AHE.J.':,-I +M7F?&%&FX&\6;HPY&)/#!FA?CL1(Z(XQNJ8DNI3UC5!B?1+Y+5P$9]G>4SUB1 +MC-Z09":%6,^:=EY$J]N*';Y:G3D+CM#BV@FDLM`<2""Z+EAGX&Z^P;[%^^7H +M_G:J8;Y>Z/GTUG\I'!Z!V*.G]^U?*.KIG]I^(1AC +M8%LP`2T&^PY*,.>2R,>)8T+_^Y/@4J=R$>P9M:#/JGIGVJ=WF8SW@35;(E#9 +M]QPO'2P2(YH.TJ$'6ZL6NPU59GW"A-.Z(,;P?(J/.AMK*"I7<(O?;@ZRZ0]:DXXNS_MJ*<[/T[_'RM7^0!K.6_T=C@:).M=N +M0[_11Q\?AJX06UMUG9G1R]7B$/$5[W-R3L/.L9;L<&F2I,E\H6]@?II^+TUZ +M*N>/W4`1S40.Q\$3WZU5S-E]H-*\B2][F41Z2^R:F40TCU!C!\S142%C-JR7 +MXRXQO^GQ!XI"O1#A:Y@_)Z5I<7U74S@VOQT^PC^:V\X0V^)+_[*9-%87.4V* +M;`.&%G&F?!0"!LS=M^@F.6X$>"^K:'I<$>A('0="$JN3&>`$T);#M.]IZ>NZ +M2()T;75(0H2>H//MUT/YP=0JE%$8?_U4NC`0#G#(-.'=P/T)YWDC%*KWQKO/ +MX]%]:Z!'NIHA6R4#;RA'H@0?I=N#NS#H2\F*U:(+T"*/9BKUQ^J$:2TF>YMY +MK23[1KQBGGC735E7W4D^/R*.P2AL(-6'[%'U.7:ZP^)[Z;,;'7YW&8ZQI +M>&P%*H0NR3YT.(:9?%=C&]6I]B+.-<:%;53TVJ@30X73!<_XP91?RLX'@[[ +M*X(7(4"@O5.>Z2[:CTU%^ER.7$#M?TF@G;\D@`"]D`@M(O@A&H,`SDCJ+;LC +M?OA"F=(#E=>`9SFFQF]`B1TW7>.D7H3`5=CWVY8MY%W!*TG!8@HK5'Q],M*T +M2+%.Q3^!Z,7CU--Q]=9"#W"]I)G,$\L1`F,COK!!$U(7-YH9&![(+Q02P,$/P`#`&,`C+`.10````#1*```K7(` +M``0`"P!.15=3`9D'``(`044##@#_I<24>1-K#Y/0:@3A^65G:C)AX+TN0J(6 +M4KNXC%N^/JYY+"KM7"#QGBIT3V[S*PGS`4=BVS_EYW^BNM8]GYU.+?N4`W/Q +M%:YJ/[QW9(^B5AF!SV^AUH)E&!E'G>'1,`2J\*Y_4K9#2BQ`MPR,LRY:<%VC +M7C&]R0U@C)CZ[[V<\^ODK`_`D=I@.3+F(@=O?0JQ=RUCA,B$2``6FJ%BZK]F +MP/@NY*S(84\RQ3_'+;`GO"`\GI99>D=;,1O!U!<-'[,==4)HT!(M\D8J +MEMO/69F>3O%WIZ.*\:[;31J5"?II?,1@%SC>F(:IU3I`@0V($\NC60@C&)3L +M`7S!T(%I1/_&9UURP_E05=:+&+4I(H7[&N)-PG0J^:.-^]6'<3(?-[I\<@SY +M64,:.S:N.O.2,0\JZ=A9U)'@4UUQCF?`*)*'[.!R9(O+A<*>T'#4,RHO"G*E! +MJ1%?`P7CZV>2PG[6M%)FI7'5<%693VLQ`4[XW4?9S_X(G9#^_?*K"%(+PD1W +MK13OV0\NG4VX!0RRK.\*,N_%T7C,L8(X+-O_X54,IY/?(/-8 +MA%4G!#$/TD;H1NK47$QB"?#P0#C)/&Z8$(D?5I_6N%4#I$.2;9,JZQ*>Z.G$ +M[62W9J<:[NXZKYV=RH_6(7:]S)UCM#M5&$R@(?=+V7U'>EF56'7I34GO;@]C +MT)Y]8QP+8$&M.\(P-\>#`=PQ.%_*;IP*@]2?&,I'O4P9/H[26@-L-[^-T'#R +M"='4DTM0\/&\S+,L%+M"B@94N47^$YGX','JC?Y08[]>X^4WGCI7-]E9_7?J +MW)V"DIXYCAQ]Y-;6??RL$7V^A9.#_C%I:CXJLHCZ8#-N^W3%$\^X[KR/<,DT +M=M(,:')U;77R7J3_>=\^"F=FC;%&"`9!16==W']/FO6^1*?40F4O`KE<:0!Y +M5^F5#HX%339[]6N2.5-([#L06!L9ZV#DB"/G1[4,K- +MM+7&.H$S!(^OB;\"M-B:7R6S.GJCZ+V16]'%RFU[=.7%:DWA#DID"/09<.)V +M##S&SO*)I?@JI+*=-[#`XCL(&7EOD#!`2L/E18V>4T`^MZ$%XC.U\.(4_4M6 +M)S_(O9;JJF0(N]UN'OT9S<-VO,G@(YG3D,(5S(V78J]&B"?_>!40M-QM[5E0 +M]1%8>?JY.9SC"*]DK7K0ST?O0$11F'<_[HRU'/A,%[D_+@O=-$27./:H_]"K +MRH&TWW.5L<5R'J5]^6G;K'P\9V'6AL5)#*-KIJ=_AC_T\NT09;73O7@(P07^ +M#&@L'(E-,1]F;5-\UA3-G\A;UW'E4\L3C.H?5)D@N/\/@:;[,C2Z/L+ML#E' +MZ"DNI.0X%V7"^/8%HLP#CYI.TUO9]*^29-"A40?3IR6X#6CD4B<V`/)'[Z\[W;%3MYKZ)S;SJXNMK:(YP. +MXHL$Z18DIAHL/$R_;6$0`[O,J&,M3Y_%XVJN2Q/CTZ[:^02)81K!8&>Z*W4= +M8W;&CPM8Y"C-OVB>E3.+AZV3Q?@42WBWGS]"VT&/Q$^69203K?>MQ4#(M+3# +M"_#_2H`XZ]&:EA@-9A(ZR*\\&$SU!)7^R1@+@!"2>^Y00T+@3CD]:3YA;,5" +M=Q8KA4(R<-^4'C'A0*\L!N%BR[VXV*:"/'7P]B%RP8K"E`"!>9(<"V'XCJ*33WRK%LFT6P8$+M@A@4"_KT&!."/U,*2 +M^'W-P!E?LWL,JZ*S$;Z\D=L7,$8;406IU#DMX#RX^BFKS#NP0J)59>=IC2:+ +ME(8"(>%2$J,28;F]4G6;`;U(C37(Z&^]R&=MZ/DDW/R`J>.>_F3UE?+GS%&9FIV`WN((IS>R3*CYXD2)VX3=X"OQ +MEF.WD:RK<12<&4&922Z.1UHBC](W#^O0[MJ8"($]^*&5$9,Q#=Z*3L7J@O=` +M#%&VE?\\)@#'4[Z`%([Y7,.&(K%LC"B"'C%GFR/H)8%/R^_7`>E\*&1PN8D5 +MO-OH]1IF)7VA+U:HYO&Y\87_GW7TT^/(T@]0B_\5<9CA=6V[H05=5Q0FC%([ +MY(/;?SVU1N1$Y[[7`VYI_F2!P9WM+=N74;RF4FP'H&R^_44R//BY?22.\N9; +M;Y\,DC&;KHO54,/1GL/O4Z=S10AD0B*$\?D:4/.N=GFI=;11HC,R!3![-!3V +MK\4/\3G59ZOXR?`W.[;)66$E>'.WY48BHUT[L+>U#F]@\YAT5LGM<(/.D +M)0E=%"[%]DJ$/LN_36KG/_V%@P4]^7GDL5$_KOF5^,-=YEB/[@MB%S-&,Y%/ +MGI)"8ZMXIFBE2+R?SV"906OH7HSJ/"P#KH5@DSF@[MH3B*0C_N<'J'^.<5V" +MNIW"D)F2ROI(+A>\.2??G0=9]^AMP@?\O;;.7/R>"EMWY/WX-DL+FQ^U+E%L('K`H,I[ +M%O7HJ@O*%\JS&O\'AO+_S_$V/U#;?+80`HII>IC'S+%KH<55CRO_,@$_+1'>[BF%UDEJ+A5SSSO8!K +M9C%-S@"MC->+RV7=G^&W<:%TG'`RO5>=)'1YX",U[P,C@MD&55?*PH:>D>NU +MNVC*52\9LW^3'FYN+"/_$C[RO'#'0C`T@S]U?_FQ#,R=PN3 +M--*Y,[!_5I8=MW>PG/7BN'&SDM(J^8))X`Z:[,B.J$&O`\B_!Z@;Q4IG%AG. +M<^^G[6O?U512?SZ_O?[!Z*W`_>A8*@Q@P+U<V[R7,6:/QL)0LP8'6S +M8R/M_`*WZTI$807D'[[+4DQ__Y'(`GT0&LAH+%NA5BXV!M@;U'P&PL?7DN5,/M/ +M67BR`6_'%DQK\/C"F,/BL\^#,EKVW#%D`"%L'.IB1Q2H.Q?H=?._+IWH;3;U +M@ZI:PT+$SY:UJT^^TZM0C!JEI`]>20XEC3*67%&^(,B>JJ7>CMM$LZ/I;YR4 +M:@YY>7-D523J)<&4,;1_5S]MKF<.`5)/(0-.$&;)[1*X\[RNW6`&.1V,>29$ +M#0[0J_:7=BZ_[,)HD6[H**<1=_<[-8*OMP6-7E2-:O +M#N6.`LRPO,U;$H;YUGDRAPER<)Q/O%L1PZQC.>&EXCGA&'TWZ#\9(-<@"Y+S +M?F1TKI!`YX?(8G&AAS3&I_39OI3I* +M13_6=QS(:73MK,!-E?K)-9F +MOUJRQ]T+:`TVA2%!"Z-N.R8][3QTEWG-(1&8E'W:^ +MDE);*HB)K8G/'.[4Q;C^@+H]HY$K5^7#V[5PUL*">4W_Q`2,1Y_%#<(Z#VO]G#A]H +M]WP?%%".B''.(EC]*@)2C9L5&T6F%L\US8'6W_]+I"-F>P_-YR'3]LJLC(D^ +MI9FM4X51Y#*4W1SZYS4B*T@JW1,5^0@![L=`DT3N2>NA=1B$Q[QI3>>E&+4M +M@;AV]X6I&P*4JX:\28T0`Z6PZ$:$^&$P>V'`8DICJO'\*=94XB>/$MO56CT8' +M*%X.F")6DKOM6AVF%LYH[>%-H5EM\>P,9)&=.AV*ZDEJ95(2KR'BF<1.C7`_ +M>X90MZ*&U>Y:GR(;-`2)CAP^),649?[R6\V4Q&E^^*9@HM-H'Q(&A2L'N2\2 +M_)Z],LCXU<@M%P[>/[#_9<.,P4,_6-91F\%[@ZW(\!,/2@_SXB"NJ,5*3/E- +M0+]Z4::2%#("/B"),T-1OD_NNN.> +M0`YA[]Z+`7-"GU.H*7C$5SNM]R3ZH,4(BI%Q%'3)_D+>0(75\D5PH&&'"I:4 +MU56WGG`=)6$_5*,_@3*F-K>PCY0UA1JPI>.L["M@]Y"HVFK3?>:NA**2KY-, +M27U+[>>$6?TN^:&TX5\CR#N&)RD*;X8?_*H^5+(Q'FZ<#5FBF5T@)54JO-CB +M0<&S-_%?N>V\;/[9#_7I6UHY?5[=,[M!%W'M9H,F-WCQ,F?180+$IL02=61] +MRD+ALD^CW?VX4B($P1!7.289&B:80X`7KDO:)L1==Q[G!?I*ZR<\1+,%(2TN +MSP[S4L5S+/)B>'\182G>6/7U99^1;+EG"6`\\7 +M@3:?O.BZ#-,6$:.N66Y^QK+C6@$;[7V=T!@C9YLP(V4U:`CO=C*R>$VR[0Q7 +MHGWWV]0>T=")M0EEB;Z!JY$AY?I=*G3R'47)`&$L%E`Q2CDU() +MV:(K+TF[WT=5V\K+,$_>!U'4@)(=&X&;'X\8ZHM +MEIIOM^BK`(G-H)[0D'^*%K**=8*[Y@DLZ=GHK@BVD=FOUH?N)!BD+>?^TVR# +MH#Y)_@'S>N(D&/P)*1&VDV*!.1(F/:=?MEEU>FA]Z&N']]ZM/V_.P^'K^=(U +MU'MC(/RQ=]-A]V"%&S+]$.(2_];]RX36`H>?VHW]D:ECS:,$/K%]?L$*KH)N +M\Q-Z2S;FZD#_GK+.FZW-Z*J-$?>>;.Q=JTWB+#T1TF/P,;X,$G)2"A!24QI& +MVS[]F*\=F4@B)UUZJ>!G85IB'3MZ6T7'GFG*IW(!^I=FY;C,_#'TQP,+J;;U +MS=Z-+\)#=1(_O(CG9M6W)$Z&GYC=.)V#M;=$G@IS)FKH=M*K0E99H/ZY@=A. +MTW5G:$!T/H@KVT^H[F`I,B0YA4WXFG>H<5?V%(`2?[6$7_!P%?WM_6FU87RL&4HA#I^O.K'19]HZV@Y+`T<]) +M9@N#I5?J,90Z57MTS`D^")E.'Z6K;?9N50$RHE7\D!&Y<`]%N*+>VD5?=Y6" +M.%JCN')\DO9.:TB#0_2+HU3Y)XE&0"WD<&?=S=7C2$F,,M(?/Y!3PDC.EL'L +M'L*^KZ/!'-SN@`?;@HP#E@L"\%WV^7*TG[1"=A)7D/ +MFZW/$"5;Z+$B#B$!_\]_!8?$_<#628X9*:_/6J>/M#CK>=1\EL-&G?A2H)>G +M@<$5NUWZ4J*"D@HB>%;,N*=6`=ABGV%:<1G4)T?!X6D,5U2">MK3BIEL7C\"IMIK8$-?%HM`A5+=ZDXAWHGU#\_U1C^;32=&2Q?S/V6>:+DJC\ +MT@0[I%#\)\4]@`[R7I5?,:W/!H;3`6,^M3[XBZSW^>Z2TF>5HX+^<7OLS<;( +M;@5NKN=([VH>L>?=PU//(F?L>:38"#Y87=`?L.[ +M(P6M\I"LFBK%]T(+0LIS2K!F19RP@F1RE7J:ZZ31S7_N6PO!?'1:E<3.KW;B +MX,-))HRVH^7&/]/Q;)`0QY.^W.6REY0JH6[_?!6T:9UGLNR6TD$M!<9HF]FH +MC<`T]'^T^HIDDQ3,M!63N(C%_P2[`)97&^6:7A>:&=LJX2@;$HS&<$O:4T"7 +M&E-!$&^'*]'V^!S!0]UTEM89+%^RP_\FE,P_DHP10X])G#-0]Z$/WPXHK!LN +MKGA3%Y!\6'X";RW2N9R$F6)KDNG)\L_)^Y^&C(@F7I'8SYD+%SP6B%*NYS(6?;V!&TXZOZ4^ +M6>)`@P#?[,I#UUZTC`L7!Z8HR`3B&1G;LZO98GI=+_HYTG'=)`9_N0(66G&8 +MP&9Y"^XE)N(,Q&.XB>6CZQ%845XPA_ZYT4B%OWB/0)HT.\[G3?Y(1(PFEPGC +M<^#M]@OC`AYK]RO7"ZC/[*_;1CWU'00:>Y@;5ALY[O%.]CWNE_9.,AHF2WJ, +MQO?R5?_?=\^]/7K&D?REU.+EW.VHFDHW.H&E_,DVX2834$2M,Z8@BC]N_(=, +M*T9`/F12E[88&*][W=MMTCZ62`"C+U1HMZK9"N'!3M&Q*HIZ? +MOJYHW3VYH)(3,Y!]]0F`*UC;+TOX^T-"MHC?N;.@%DOW!>NS@N32DTK*=N5N +M(!!\)W(DB-IR@R!LY$,KKW49R@)EX/T$72AJ(S,]N?^&H_=J>FAU.W9QYAG\ +M,A80!=."+M>]1C@@O"!RU1?7K@B\6`3:RL$`E56'CVH+LNN\@`9RLH0YV$/I +M3,Y9F!YE?CWERS]6G=CZPWPT3P]D82U#/S)7*UF[K%D"B6JB7/B.,B/Q9<&Q +M36&DS@8@2PG.?[%N4!'$#IOP##`B0#<88$D>NS@/Q)1`-R/`RI):?$%#B)ZL +M@_W,+>^,P\X3XLA3*O-8,I_4B[VL,Y8QGR&2YB+G]AOI3/2K^0!$@3!W%A8' +M9#@-0L@NJI^231RTR!H\JKH_P-Z!Z!,Q3T=2.;;O@+%3S7HRK*%[MY>?0P`) +M9"5_+"5$/<)#X5`M42`I`SGT\>R"&,1UI#L?(OJ8CGD=<5SH827S` +M(SRO!PQ3_V$DS]AU*UP7$8<_F.WV,:;0@1(/K9?.`&S+(T+=NAGJKDY*;=W! +M-(SIY^AM=#M;%`K?*)E>2]@\C00HZ'#&`5"7+\Q-&E-Y5QILN$:4]8HL0-2N +ME/<%VI@61.5["?"4`-HAQPA&/2>!0_FX0CZ/&'7+\(;C4^#Q$X.%"]_4""W& +M9(N2ECFM^FQA:OA(2GS6-SU=AVQB2RD+4RE[%&,T@9\S_G; +M>^&>B7LP2L)?YA:'W&VW?G<%A-JFZX1.O28!!#E='^ +M]"D9QKP1:7H)HTG[TU.%S8!S->'TP^3Y7Z]+NV2\2^!E6A]:JZP;8"]_F$B8 +M^:+Z($$/N!60]EUWP4?XNVHTIWX2<+6+`UVNNH95>3:W]V?X^[HB"=T^&N]+ +M^4;E(>Y0!CU9B(AVB8BVWEXF"++/RW00F^3E6H:%GB4')5IO22*W0^,'ZF/=Y_HYO@E'`_ +MP;ZW+/ZPT/2-8)V17`S)_BS%4MT3L$%(4#GGK[O2,T^S@5S(Q+!TW4'!IXB4 +MCJP&9=!X$E80/L$!ES:^<`GN\8X$61V,X.]4M@EG\%G7K8_R"UJFQ'(%YM1) +M"I6O1OT:=90^!\UG2C@_%%?8_>7)V>]S/0:ZZ0&JC],MK,$-CP6]`1<5VNW1 +MBRRAQ#G0]4.4#/=??VEX)*BM'D#R.),[NH:6KE\J15+W99F&$%VWSAE^(P,' +M0BEN8AR156LHS%1IF`_'91H!,"$F-C9$JCH;H)VC@3-ICAI%.LR&%:E^QGS3 +M6-:&$V15/:IGHAV/*X(2,$L(GP!9"JH60S7:RM;*I=U@6%U.LQ?I:'^CMB>% +MDE7%[_[_>`UM:-2.QW@.7:05;,P0*B,R2V<^TW2T62MH[6T1)?Z!JBH9 +MWU6EIS5]/'Z[`3XK+/*BKBG,"5(RH4V@&H93.CMQ)+V7'T)"HE?<28M[P@U/ +MP?NN/6S;P-R\DB%/9B63;*S`H"T=2)&=-R/W:>%E^[8VX+4XM^D^A%MY"1JK +M3Y-^.:L>:1^`Y4M^W9(G[P01!4(K9GD]!<@2N4!1J7-G&]QZ] +MM[WXTZ1_.4<_+6X(RY'Z4Q +MOT-;[@Q[IA=87=T+B1#YP<+Z2U(3TQY'8$]Y7HM2JC&[M2AVV7WZ)8'SD\51 +MU.3,4?E?9FBJ:^#CW\1Y8V$GQQN$$@&5,0]:3]OCPFQ(<0]@N[2>;A6U*Q[3 +M*057V"THU`"&"P2/O]RVM9^9H0C4:S..GJPC29CMQ/#(:[G#SV*2XC$Z:L^L +M%!3/UV;23BVA_Q/QS(]U-)MPHA,]N)YE"#E8%U/'P14_+(X`ERP.(#?'&1;: +MQ57-D\(,P;\C%],4G21V4D%,!H4W]M_96GVD=._6EZ"Z^#\Q4M +M"A)9880SM:-J?,O%;X;']M:8/JR+PBK9-B66I1U'AU*+G%G)M7]\FR$I_'S/ +M*BYZ3*I$S9W$/@R*H7@YA_$2V&1-J89JM(5+6]B3P,X,"/>HQ1?"`@T,0FH6 +MERRCKWV7@X8"A7_QM*:STU4!W;CT<55?EOJ3X3PI=NRD??4P9U`>FN?\:F8V +MI!@E93_#\D?C[U-#EA%O!>,6B"TC;6('Y=CK\H]5[TAJHYD&VY@Z[IZ)4[7&FALT+OA2C`)LE-Q?5^1>Y0 +MGE:6N?$Q)+'LG2*Q^52W/\/=-@86FM)Y))I%G5:Q-/S?Z5)/ +MY/$&4K1,,>4!.A./R22ZW,G2"+[O[`;M$P6BW4#U=:/EXQV#XZQ("/MCW"KM +M%M5!<=?H_H?@>$K5O$(MT$-5*EMMG0*7Q9^(3HU:0__^A/9Q0WI+L`:*Q!:. +M%44Y^ZW/K7M,D@\`MIY4ZM,_9XOZUIBQI3:"C5$B!K'$#C/57?>1+18(&T +MG+"KCD6!B&A-D]X\MG0`TP*L<+0A`X5G<[[NW!TG\*A'5,03MD'%H@#_%P40 +MV4C_4JPS9&F$DT!;H=6]S2B3BY`DCVK^9&3HXD#5X5T,C\$$C6/K*$,ZL-?Y +MU5/2Q\M1!>J,6T4H=:EM>ZX4[%AC1CHI2-M +M?C]>@?"8$C@PC\0RW.II3PPJ4LN>B`(>(GS-J'BU6#E,W:/:=@`T1Q +M!7/_I=8]9*A]TA#X\D80\5CG(5$<16(P(H'!/I+RS4`$H47D+=;@\8)^O*XM +M,817US"_CAZ-TJ[$:F.V=H/@PA6--7/3)*""M378<[A`^*L>`1N\GZF_HC(I +M$A'EV223:!5`UD`G\.8.[C!`4]-&CB2:^!WCLG7EPM%M$@KTV.1`<*`?=V\7 +M\+`ZRLOD](J3_<\2K.YQJTTB:7N"RR*(181DXG2\C4<+7F%Q_>Q1#F!@;S": +M(:T(.F77J]VPBR9_-+`S8)HF4,VD20%56I<\US0I=^/D;OWS,;`.IZT)EV#@PP060:.9L^3L3+XFHHQXHH2]?]XZW=G]X.7&&,8VJ8%[+I:L)6Z&@I +MUS$AQ;N()P>Q_\JA?=^CY)4/0F=3FI6Z@.1<(8&IO$6+@_C+[K>>1>QE(=V7 +M'#QK'3D%X#KA%R#"M9#_D'!']0AD49VL;=4\H][KXY(F258;&L%5O#WIZS;4 +M#S,V!\8@LAV?Y-YQ+.2TJ9`)PS]5K#G]KD2`W(+Z-9B'=J>ZQ&>BN1 +M@#`8.IN3$V9>,TA-(_9`(%0M!)(*<7A6N!9$F*TI+QX\?(4^O=O;CIK%XG+W +M\A$>32AR[_C#*A_X=L)F=295HG=">=)VW9Y3?92@2858]SM'?PRN/M?V$N$7 +MXGVS4U+AW>W#T!!Y,/.86:"+*9%;J?"EH;?`YD6A=1RPZ-L-B$1:5&/N4IRU +M[,4G8LNDU:!Q7J'6$OLM&6`H41C86:!-U&T>>F4SNG8!@R&##>O^E/CD1[4A +M;7H@J[$4T#8R?X+*'+1OBJCTR39XP/(H[QW1.B.8>/!WPUL8Z +M2.U$,7L#W`I_"+UQ/QR),*)*:\HJZP\JF=ZNW3\3,5H/S[8#"'>KHX(=[^2K +MI:`)O(;E9<7VB&8#IE@_>IJ#34X),;62I01/A&V\G!5L,NB[\BM(JC*16U=A +M3]$$3=RG/O&FXRB#O>?@`M.62OKXSH_"7`>W72R=4047UTYO<>3T+*>RV +MODSZN,ZY(3"ISN!L+@+91GL(!=X!_%;P)B4B*CS\)4SXVN,.M]/F83#\*E"D +M)/;8K3B#E!#:H,MN$_L_B1+_=L1)W6:,T;K5Q9QHCY+9LHH9#:I!FV98A>EN +ME34#<@Y8QP=?K3_/#E*!.7,5H@MGE7_WM6CY%HN]LBD0L2,8>*FQ7W;,F.U3 +MWMZ+FN!*!OD+9_&=G3W^_A&(E^SBZJR-KCV7V2PWQ-^]('-^X>P4RDM?V\)`L +M$NR41"!%T(+JEX?D7]B/92,Z>^S/G`ISQ31!W9MFGT-9`V>9@79B:=J\&7BX +M[V:&V&"^VX7)%5;F;.>62*B\$*'U"L`+80*%U'#@+FC]6;6YV@/WDC6Q:IT= +M\+L\M^&QB2ZMBQ[+VP*Y4-14BP,MWSC[@HTI0F\I'!=T@-M)T`!:9DK".N[H+>8$V6.CL8V$@OG4/)U/KCH1HL_R6:0WC.Y +MG^$8LO9$SZ?`VVSM3R/:=R5#@"V@PO,.Z],6RKX9F!)`$ET6AQ+3+-\YV5+7LAFX$> +MA$9/:Y@6D:;@;G7>GD!F[.?$R#QMJF7P6(,=8M+_+W8 +MN1`46/R!C%H05>_T#3C+0N;X66?VP_[8H?P0W\2Q0:X8@CFP@BGS)M57SG(( +M_E7<]&R7$E9ZD`GL-L;B:#-T[E(Q=>@8NL37`X!M[5ZU.NB=DY/732K +M+>'V\NM%Y;9,/95*_LU8@KXSN74T+9@!=M-!/:P/'/&(;OT;Y[VA'5EOT*C5 +M;2B6TMZ2LAWU^Y3\E!/W\OG%L(=+PZHN%N372=ZCY`N:7]NY6=@*G(_]*0_` +M,'$;I)X60*DO:081Q[3;_SA#%K5S!.':?(U^D/"PHA,C^FONOL>I9!![W7 +MQ3]?^G06F%8V&Q2[C?I.A&1ZP-G682I\)5P\88QP+"$L0/*GLJ(:"&D2$/80 +M,>5F%$<\PFVX*;6>(UAJ?:N?=1=A%7_<>48(U:5;3WLA0]VAZ\^8P>9%X*YK +M=!7C$I1",.!.]OO])XD&6L)I4:&B"@36\[,)>N9V$1!N'<7^S!5Y:]D*E(T) +MJK1OT +M[J)?F,#\T\L*8:1A;$/,:7J&@!W4`R='MYNX8>/DP#FPL:JUA4+-8L+143\T +M%;8R4!G73]Y#T,XI/$%X6C6E[@F1".XJ2R5IA,Q<\6/]8E?2A1)2'&'[CA=( +M6GJ\E3RY4K6*%XOAT3);/\YB5(3A3YK6O";%U5KORIAQ$G^UY&>Q#1=-KC/S +M)R/@&N1^]0A\:8Y(X-POY&ND:2A4)2C&4GC9?)Y)?NB0W9.2M +M^AG]<5NK49QK6_K'X5RJ\DWZ63]Q<&!=/WD]=M844K]T2ED1JP"^#C0,#9?> +MME76`A$,;"5PQ>DDDOWEP.C$+<0#5^"<>EF2`E1KLZIC3D277F2XVTIDX`RC +M:$:D%[LB;7KK-L!C_=`LDO93G?9!PH&@]TI(J$YYK3MFKLANE+([A#^IU3;Q +MI>R1;\@*]S>0$C45KOPU3R_:5G%V*^[8%R7YLTP9W3YF:4FH6Z19,>=Q31`_ +M!X&/^=;1@TAZX7X_$G/VN#V&59AOLOO:2 +M_WOT\JW'KR3<1Z?#@+Z'=Z^C?RZ--:[MW']0Q!KU]@]8[OSHRQ7YSAOA];`@ +M&W"`:AB$+<-I:69O.3$^]9VP0S<5;XK3EH)X.-GYVE&2"KF[ZH)`"8+H#Z.-4[)V)BX&A+]*)E%G$@0=^EG9$9!B)89;GF)^=Y +MK8L"A=3IA8Q"E=?N)U+*]?K^^O*?O(C#W[`:HN/[9N;W:KN$TIMI/+F,.>:= +M4K^\J`S%X+O`:]YBA/;8I%4R41[LZ5;Z.\Y3]9@?.///9+I:<+6=/K3;R9L, +MU'=K:+)91CB!G)WC:NA-B_:CX34!KQOD/V;ZH?K%`:>/5(^B)6*F\KS%OK?R +M-([*>=?PRJB"T-K157#3\>P$3VOH`VNEJ$O_O$:+V?`L%P7G_@*5Y/#"4379 +M8A4BTY`^Q:U7"6)C]AA2##ZH_42$TBG<%VV9JD/RGQVOX2-I`)-\MU];":^[ +M4TYKRDET!NMF+H/L)=<(PHWLAN#PP:$R[-'P=(V:VW0XJ24+R[3GOC@M*',[ +M`?$\7:1_%(-994SXOQDN1<9I39,;#D#J*[M9?A=K%##QO[.@!+1_ +M!L3:MBDM#&-0;.>KJ_>@S*#^6;#6CM)?;K'+O45?6QP*YLU"8TI:@5C)FS^6 +M+@'3E9@/H%@SXZG%MY<*#CL?SA=P3R?R`1+@25-O,MZ-76VZ9FQ'+5VCN*[. +M[AQ-J;]&)QZJ0BE>9>$-O(K%S^O7#3W):'W_,DG*`U!1FIYTGX^'7I270EKL +M/-@-E60H*T`G3Q&Q$8HQ4H.@_#"X>7`+]Q8C._"]&\!,32MXNC48AGG6J@#H +M%<;&H`4MSX>)F`:QG"WLR8X6T=P_[NJ;%R?8SH$".Q-E:OK$_ZRRO;S9,!2\ +M'^ZWV47J/OC.?">_,7&B"W`VW23^B*L'#L4Y2X)[`P>S4!&P%FT%@2KN3VJO +MLHS`:-)AGU.Q7QVLPX"!ZUZP\5.R5QOA0BBM_H0"2W\^SYF.3@))T>!IDSZ? +M!E.A_UV#>KW.5XEBVV?"!)/LI\;2C'[@L20P9KCU]`J4/9R6_)6`K_H"4G^D +M?SVU]<'\S?_Y&XCOB(^8?=D4@%OU4[.6(-AAT8'A@\Y1H1=;(E;HD'I\<3GD +MS5W%$%G1>T6Y&J4[I?VUH+]LIHS0*L#^BL8]S+UR1X.GQX!&TJ"7@S)O2=W# +MM,'7"'O>=3&!`]_MOUB$F/4QK"I>%$)/9AWJQRM:KYKU+)B[.]'=]8XD/.D$ +MJ&(C_%W]4,K26CV+A0$71)RF4-3EC"D:B!T?A,98MIREF.8MY((*:2Z/=,(] +M,$,)L)K?H,CJG=^_;1)$N1BB#R>`0H10Z?G,;;9'D,(3(_&F0DNPX`?#\-@+4_8XU_H>&#C\O.K1+!(P +MB3_8W,L^1MK_Y\FP1JG4)I])32U=;J!'\92&%B;8"]C<][+0E;LGJ_!]VQSU +M!>DFT:-TGH>$YO>RLQ<'Z(4F,8!,R",#+M*H]92>4H@]A$^'[XJV=V9H.N?+ +MS>`$N'7.?2N>VFMR!:GTE+/$1\>86V=7%W*U0-U<*O-NZ+[,>7LFL9RW0436 +MWAK\LR?)FJ%:F,MM1@V.G+89@U[?%6@V(77P!"7A896(^YO'.$_),E63:.%[ +M]-J8S/U"?F+B+34WX,2HCA07^=2>LU>1`N$[ZLQI$_LU5L2+G7F@4@7PKE*O<2.W.A3XNJ3M$>'M(Q&B;%O@?>+4>VS3T?8)9[$$8?T^4.'`E3S +MCA-3Y:,:%.AZH-;@T,&O)LF%S]ZDKT8I#=)&*_T,-P$?M;F4% +MD;G/W758K21K"3N-UHLO&2]W$"VQ'/4)I!/12W6S<+BH%0POKMEMX>H:1M(3 +M@.I,I!DT]EAA;UCNKF&$:6%Y[Z6S?:AFM*1.8E6S6=T%_Z1C>O+V@``)`LK= +M&2N"HLPQ>S<5Y@K*!N&HG[[9QJ$)K7;ZX#C%#'C6^2*0$@R,M*8KJ.?&50G, +MA]#X7W4EV4$>'$\QN,KV8$N>3>[0T-!34,/L:'+H*X+M>Q3[`(328G+O")"Y +MU76Q0JJ!]DCS\$'LBF'!T)7I<3;PR514*[U?#IN.(__Z5Q@L,>>N>L!H.E"> +MQ:+1.@5A5,H'`S,=^K^<**3>+BAZ3&T[:Q/^3)$39Y=1Y)('2M>>5,SIR2U: +MZ2E5,(K`4^$)=U#7WJ*%?6;^@652.+SPFTY7)`.9I%KW7CAQ=$"S+)24<&F< +M@R`UNHLD86BSGM0G_D-P.D]>9$\0;<>^H$F4H7..39JXWRSTH=`N261[RL8RPJV2(>;I_G +M43N__-"SX'00Z]-\#=17&"[A99\AS14;?T>28D`6LU<#<;HQP&?H<\O_'Q%- +M,U@B.*LZZ<1T+&BN4KH<&@28SVFZAE&A]N*TC +MO'7>Q=(@S[5W%+VI^+B@P:.DQ:X6O@_8*$)(PK^3G +M)`;R)?_IV1/%TY=Z:;XB>\QGGLZ;4YV;$<.\D0,=[8D^`S+IA@5P_VHMJE0R +MX-5KI6_`%8*;B(F88\M]PWK5:L7?_H2C-`X7YBGMWW\GP$AUL9`B$8_(X$F>:0' +MT-C#J#5N+>9X"NO5+KVPX>XJ<9PJ<#DQ]]EKK/W$]O;A.$Q3))=!E;[2G+RT +M,'D#U1GA>DSY2$Y!CLFW==^ZF&S'&HP#H(>/[OH[!9<@^86_/MQV.!F%*$[B +M0-4-/L%]NJ:(WIH/RIYTD5SQWY`)?7`8MK=^#701>1_);C=FH+_7:+K;8OGL +M@#%]`'N53B?>M?C,T)UB%M?GIQCV +M2UC3?<'RL$`2LQ*X\#='00?GO;Y.#R8^3Y?V3@QT(36S0&'4YE5_PR*X?X42 +MF/HCO0#?_/TG`4'H3GD!H"$B]:PPJMGM3Y58K7J?60Y-N^&Y]7H5M?1VP^'_ +MK4OEJV':KE`8.BLN&=/K2BZ!M27122`_XVT"\,H$@,_=RRP]GJY9PU+E>:E1 +MWHO/P.;?4MAF/31)+KS\:`NAFRD]APW+>SHPX0\+3^#7YLI'D:=/!K$A0U:" +MD5:F73/)@EF$@LVC"S-,9=2Q1H"H@BEFQ9>?SYJ7,]S/CU!.G]LYA4UQ\W4SO4JB?![XU,7_/=!C5 +M+`-"QY-X4U;::^UKE]Y^[DZMO(Y/6F7]OO^BW'%VV?(V9*W[4I8(UN*IS%F( +MHJC0GPA#&0F+5V)$RK?8CZ0%<4,9F"D1L!==A'Q+@$XQ?T@,>O%[`DU[UCH; +M,=>5`#"U73$TCV(8%H=VR[[*O^(,P)/U[S\PY+<-S=$,`L9Q7OMCF-+&#MQS +M=Y#JR-=92:8%_O]G86G^,^@&&L*K_):QPV\4@996YR\EIL`$]^V4_D=GUQP6/H\?6!LHXT` +M(O(K,+`G9;2V_A=6'RS(P`T!P9U=B3P3/=QM._O8O!\F8#B_BQW%16H2\_82`\H9@GAZR\`HL,P$:DQ +M;=*J2JS.AP2/YA&I&?[B%-_ZQFN(]Y%ZJ?$0E]6=`)*H9Y>[,;C]=5"^O>2# +MR^LXH=46!VLP%X:NLTG=C^L'L;'WY8,]DR2$$33KBGHN+IT4QAW-H7,\#OMN +M`,K,I-7E+EZ0)EV%M(;7F0F*2JOXH68E^T1^L'-R^0"&@UWY#?JF56D4F.OV +MF.)OP%TJONJJM:!(2YASPQ`T-(CA81>FY9S.>VI](!IC#-ROZ4YFBI5MA(7T +M]756[;N";;Q^P"DGKM+V +M5-2C@70OM"N8]!E`J?,_0-GGOI1/8ELC$K2-[3[=M5W&34UHL$LE)9Z$DOS. +M=;$4QX^QGO@2:4@$S@_$['&&N/3\K"L(*-S"#U[0H,9+(R4W0Y?#,/(KO#H@ +M,Q("_GQ0]W?YAZ?U6[#X(G9ZN=:1X4*$(9T0$MN&GJ-)I5*(T"+J_I']-JL0 +M[C+7S]B54MJ;YF'#FI*IV&U8[E67DGK?%93`&3G)"MCQ<+Z$A^&18NKRH963 +MK= +M]ZN!3LU\TK`#6&+SY+5_-;L]F'I5'L:9*M19]#K:5O1U'.%O_%``"#RAH%%!S +M0<0:>>#=ZV"OLY_*?X@&Q)O0;F!_*+7.T]49^..PHIF`+%?/50QD3OVQVJ!9 +MQC5DTH5VCJX652R9+]>>QY!9U&0B>H;]43F4A7:]]&9Y3$K?L\T$HYS;[YLO7\UA[>C'[4,4P.3#!("<_9^57O@NRG +M:2DK[2YFK`EB<*YRZWT\5/T19T^R*BSHEEGF5YD(`;*@.?N/%`^[G#JG17&J +M^A%?$M,R3;?0[_+B(HRJVM0TIL)X>P,POSOBUK)%@P$.@D-'VFB:*1O*F?@< +MRT$ZM!W7RL+7*;/&Q5!"L@=:QP4>-3W]@U^X`/.61GM*+=?X7JJ+L,\(:9'> +M:B!6HX1%8IXM2F-D.=&&)4A_B:%]#&6#"E$7\-N@;0H'J>OM4/\B +M:3SRSM?<5:Q#?#)+:462HV.!K4QZZ9#*L0RBZ,[7+!:V=OS^A#IT1)"RZ?K0 +M[IUL0/S.Q[TB@[)XG*6,^Z,`IF^LMQBDL%OI)3$HF$,/A>@W%(F##X4P20@M +M;QF0EMK%%SNQ2[1"<*6/)]RM/]'F()P0,XRC2.MMQ^.'_D`LBV]7N'M4V0$ +MN)``$M+4#92JN(U1_W3\`X5]_[&(I[02R4!%TYA_]:KQ/1I$`@?8)61)<=+' +MEF_!P2FKLIC06E;7J8H(E8'U=91Q^:Z+)7CW1UZ?8V1$;SC$H*<,RM=P/[*1 +M.^XES_-#$V`9R@OZ1W'/TO7\(R4-']6<.9*EJ,6&SO]WNT2\.`QV1L1L&.EV +MSEI=GXFJ%]BN3VOG4QU8N%V!2#%%CT5"J:Z#8D09]]0R=_Y*ACA&2/-H\^>Q +MX@D@(:&"^;ALS#X!M-^6,+L2?_OFS7TC>9"7&(I(!\0L'@E"?!&O5F0/CF6* +MJX:G[W12A^O4"G/JP"S3V<$]-?\6^>M63B>_@FW%-0..>SDCD"8XE7$_PQ)B +M^C"R_?HGI),A?IP`FSCA]V8N;7#%TLX/`ZG7#SSWF?K7V](9ZIP0%9RA4=#M +M\#7$V(B]=J'GF(D]9BQ)2-B2$HL`\,S-F>:6#HR^`X; +MB$.G'.T2S,2`)FM].0*18HPFN.DTH>2;`190%C#,:PQ#VW2&;=^2_$M9X;Y= +MQ*7PI9;),H&`I9!-4)VONZM![V,LJP7ZK`6MNI*\:BR<"`J!7ONF]\2.AGT# +MBA.S!0I5%J-0*F".?U__JTMR]*Q^XH`_@G;`"$4O=:4DG\0QR'02,_:CR_J7 +MJ61E,?KPX9->^V41DHA:@M.?FBPZ\C]'?XR.O?0/(*3[+^.G*$Z3SY#9>I/X +M/X>]8\@B![Q$FK!2;8:7]Z0*29!?=,WY4NB_%N5IU]0X*R/UMW?-)`1A+E00 +M>Y78I[P%,;I%>4H[WG7N6MO2JY9@):80-&Y$4:`Z27,?.")U4SXTZ%O;:E$T,75"1E]*'9S#`I=5LY)%`6 +MFHAUVE^O$+4EV*7"R.\,8-RR@!8,_%(P;G-#`8*77RCEQ`_F@-`1];H3RE_H27Z!I5MC0HSR:^@,B[YH8 +M@-&("PUO!PG@2RMX5:.VU6%S`3=I^U;5C/.<6?E.-'$$#YN\%!A-*XY$]AT/QL +M=[0[X'\N?7S=.LK^$J)7!1XR`2D!R4Q6V\!S!1`L1,/9"&W0B +M.K9N.ZF@U&YEW;3F96%O'#9.^+BAN7Q\4L[QS-`-%)\C_V`*$"Z0?4NSFYYO +M\+B"A)\>S#S/$Z1)`P0)LPVP">!C!SX'XTGX4@/@!)R!&%`*T9V?U^#<'AO.:.GPEGOWP-,[UX&\H5+.Z\025)B^-0--0!+A.U#4R#F6+'4DZO.TJ,[N;;+ +MY2J%['S\O_=6[_<`>NS@QG;^4]M*DS?FMK,[T%P36,#/[_UP[)]HHRD(6)5F +M^3H"$14PX>?LK.1*:=)KTLJ97S]6W=7H%Z@DUHD/1;[\$QV[1Y![?D*#KI@$ +MB[-A.[Z36F=P8C#)Q33'&E.#$[7,&@KFG^'E].;X`AN;V'@VV!*K93EHXUD= +M'>&?`R*9&AJTO1"NG=W]:4KULRPB+]6PS$"@$[M@1FG3'1EIW$/UI)$LQM]) +MV>@]5='D"H=2MWI/.<'?LV7\.0*>2;#%;.&L'A91;X+D/RJ`#Q;%:$WD"<-` +MV`JP+J=3^CD,(ZYKR0;1%);;"@`T(ZZ5/B@,#.GX[$WXR%5CHEBH^=GQ__81 +M>YHZYRJKM`)KS(QZ6.SEIGV8(^P%;!0@K73KN&A""NT1$K_J@`.TVU,M>3&( +M4B=4!FR?/#ZS,&"H4&M^2U_7XU'7PAL?2Z,<34E69DIC?;.JYI_6TK1K8!V0 +MP:]TG^W$EZJ1+I7;6N=[A:V`>*C>V056RA)Y6<+\#7##7IUH.V2(7=#E>LY^ +M.C]5>]]-$#Y4?HW(K.':D9HNTR?5#/01N(,H+$:M3'V8JE'HW+>.NMFD*;X]EBW`IRLX?`V1HX3-FBE%\Q@-;T9606 +MJK4*VR$X48[:9U'&6M+A7O3&\"1L780[:6KZB37=UL>M[X<95K3O=UDD^Y52 +MRE(6W:+@4_JJFHE='^I*?3QOZN(E5I!?P!P4ML(`#19='X&?V^8C;W`&)/%;G"I[<`0&9!P`"`$%%`PX`4$L!`C\#/P`#`&,` +MC+`.10````#1*```K7(```0`+P`````````@@*2!U`(!`$Y%5U,*`"`````` +M``$`&```/%Q3`[C/`8D\5N<*GMP!.E56YPJ>W`$!F0<``@!!10,.`%!+`0(_ +M`S\``P!C`(RP#D4`````PPH``*(:```&`"\`````````(("D@=(K`0!214%$ +M344*`"````````$`&```/%Q3`[C/`3I55N<*GMP!1FM6YPJ>W`$!F0<``@!! +M10,.`%!+`0(_`S\``P!C`*>+#D4`````F1,``)M_```(`"\`````````(("D +M@<0V`0!C;VYF:6W`%R<%;G +E"I[<`0&9!P`"`$%%`PX`4$L%!@`````$``0`C@$``(Y*`0`````` +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes256_large_ppmd.zip.uu b/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes256_large_ppmd.zip.uu new file mode 100644 index 0000000000..b501b07da2 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes256_large_ppmd.zip.uu @@ -0,0 +1,1399 @@ +begin 644 test_read_format_zip_winzip_aes256_large_ppmd.zip +M4$L#!#\``0!C`/BN(T4`````E;8``&LZ%@`(``L`36%K969I;&4!F0<``@!! +M10-B`$FW(O*7F%7MT6RY^$=5W"*P&R95;B4@\::&_PWT(LWIO=BQ,R5>J8YG +MC:$_?G''Q[3]QHL`D9#QZB'4Y^#B=QN13.8-,ESJ)-)2I^.+&GA//+8U/'UR +M3-NH(&@$&`9!U/0%2\`]$X?AWE3KU^E8J=2^3LMQ@XX#R.WO0YO%?V.!L79J +M_S4&]C]:^+KB^/:E1OEE('?CM#XOQ*(5']NO%+XA>95ZN`D'<0F5B*G!#3@N +M8;F@I3,:^PH;`^F6,`9T=SE#)P7?>Z_)@TNT-%?;BD@]&I7H\3EXK+V\DV9, +M24RK4(ZY'U6,(.R1)<3JL16];\,5F1Y8/'?DVEQ<+)[`JG6S/9S-67ESV74S +MI$$B9;*55!6`&Z`WU4I"*KJ'^B3B!YB]O@':=(UFH(Y#_JFA)4"NT67'DED^!P<,^OL]OP_G=KP@&W +M8_`-$*62`ASQAQQ#RQ9PP#A[3QUA='\;8JV%>&A3R05L40=^QG#M>^I4ATG3]8#O978)?(_&Z1(.SY0:#0DL^SFP'@\X:-JPT#&BO"S%U9 +M!HJ"9LK'D8E64FT"#-%G_LSHFNDC5P7$7O-38XANT7SJ?N9D',O2?/W4/MUW +MRVAQG#IGP+#%[V@!`#KQ.D#.WQ1!'];_KOUV$(9-?R)`]I\C@01.^@3;-Q-VI/;/G+*M:J4>7MEM4]FNL[E@W$:NT@Z]H)"DH[O +MTW5?NHO72A6R#+T4?^`"MRKYZT#.*\_L:SOF?0F8(Y[*HKT+6R?>8($:/MI. +MF6%78G[16$`2847B02_YQ/[]^A`QM +M;MH*_5D#KHA"XQ7C?PD0#=?SNO%AI>HWP+VV(ME4%0-QJY:*IMY6,/J:)TR' +MNL0W1SXK9\T\*NA^=I7V@-$R94G1@.0=Y&/W@EF;@Q]\!8F^MQYWNT>;0D5< +M"OK?S4QQDD#DYQQ&!+[O.9C2J"/?1=+]DJP9`&"C(-M8ZLT)-<%0S70O"4=P +MEAV3ZF";Z?QH,,I*^1263X6%BTA%60O)#T#Y(91I54G5PD,96/&ND +MS"6L$&M*J=]F,;T4\0#M?/;=\?/V*2,TZ@Z#<#">1%FL86\+2$`IIJRL%INL +MY<6()-O9?)SOD/H1U*N592JAT[]/2TN4Y&C-&%%%UKO%G=E#,H=R9B[5["(- +M@7J.GIV:4KG2#1S[&V7/MKX?@,$3X4+"XACZ+W3"H7W3G:K?MT@]RN5](K$) +M5KO`J0,UGZV@+@&"^GPR:@8QG*Y6J."1WK(!]=J4D:D7RYOW/J>?#Y8$SD*$ +M(('/#XUP]V5QZ\WAO+(^_A!AS>M.$08<;,_!M@^C71]?=<[3IW6%JXX!;<&O +MI''$H[4NY"NY6CL2&FICXGEC7?+-%U'MY(WB@=9@T>A'^AB4K^N8$Q'EBFB6 +M-0^P]P*SRQM1HX/B(IHYYUQ#4_[M-D1P"ISU2+[1+#U%I+N.=E2$HK')2V\_ +M+T.&*\>$Y\AV`=ZK8QE*1,K#,D%.+_E;US5"E8^:%JWR##'&OG_-=\J'>U<+ +M@PC^RM'JQ5+P]18993]8/YT+.L%&N"E62?GW_/?CCX0)/-G5LKPP^9.F0M"D +M_O)R3]!&+TX9J'%B-P^53Q(OO)%QS:KHK2CSI_.7ABKNZ`B9*?OZ0@$CQ[G$ +MO6[`I';TR07">W>!=K"X`R6/F)]"EX +MI5*$N\"P>BNG/M+QPH-P')6Y3\::I"UKM2H>8;\XO,W'_)=)4J\F_TI`!(*8 +MA_]$=UQM?\#F\UOKR"N2`^@Y0)+=`.%[CL`2Y(8!%#G%$YE![6*:6)DRJV=O +M*;,[[>0R4OSE*BN"IYQQ9Q-@UZ\AD_(+`A] +MVX1$IKH6H:\NPK)&G=T&HQ1VD:@W6'":"'.?-`BK=F8=MTR4)4D#0,/*RUWW +M%:="W*BIL059%.D:PULH2@,BL.\G80G:<(T'6_TO'XE]5;Y-Q3(W +MB<`R_`@6@Q@WG)6)<8SZ9MQM:=XJZ;!O3X:806$T'#14S9RP61$$N8L\8;2G +MATJGIH39^ECKE1D;I\/.DQGB,?-2E>/'[IZ\2R_GM^"Z8%#EG\5-B?($/T"= +M/Z?GB>G("NQU%K`K)M&%>.1!,%_\Z3E%(+1B;$: +M1%%Z/^Q$8_*<06)$1+O(B_Z@;47OT$!=XD>!9@2#M.J>'I2GAS5O7B1A5.HN-=QI6C6= +M0*/K;N;B@!2U_O'LC`7+@WAD?W(Z@U4;W_4/#GMOC8P^@=#0WXFW4[ +M]E#R!/D(K9X=!M/XM06P7=`71=EB8[DA&S*QS4)\P22PX$D/8VW)G-JJ1D^0 +MWK",HO96'M+9W<+#ZVZ-GM);A>XZ=7W*9X43C[G@J:D#/2)7+\+!,8(\[9:Z>_A-%M#MNBEQ9;%8!('VZLZ8WYN/5]Z*]Y;>V&EN-"7 +M8:#>\PF-[49;(GM9`GIVPO/_7O,TY^0K3A0NMW>$GP(I%4WSB.W],K*6W=MV +MQPEYM`$7,;GX:PI>&;#+A$>8,B/7:`P21G856ZOQ=/&\(T;LN69P5?/,;Q&Y +MPA8[)BICX/8+&XV1L\RA,NS'6HI0O`4YJ%K%*WD>44?MQ])%V,K^)BA55CX3 +MSZN]M;1B/'M+YUL"U&UAO\MJ_+%0./XAM'MS$4&0Y!HZK(J?&X=>O`=WG(BB +M4KDT>*#H,187A'EU?(%,O1"!+W!J^6#XM^`H]<8WS,:_0QH]W0?-NJ$:J_BF +M?`:M6*L<.%%ZZ4ES',K_9B860JMJ2WG221Q7=KR\(NPRPAAQ4?+)>7"72YK5QTGP<(Q1UH_+8:T5$CN]Y7-4PS<%U( +MZ!X3ZO?FTF6HB`PJNCA,QS[N!8A"$:)SG'N2T/`L3#X9(K=LK`7/K\OZ4GL& +M6G<[AL_*0J,\=Z9"1SCE#DLHSK!=%F#=$6FHJAB<_^H&L#R[J`:$(7]/&E7N +M$=K;P(A&OC=MG<-8L'S"T*+R4Q\0U>I"7\/^I*X_7.YY8GK_WIJBJ$:$#Y97 +MSEEV6E`+,Y-37[LM3MD9S\SJ@OLP(KDUJ06?^Z](&N? +MS9Y$41)(V3C?GG"-GYDOH\^D#M"W7-\V359BZC\O)9.TQU&E\J\6\ND,8^TS +MRSI1E;)T0)LF8:'G)MXT!&],2UCEFLO;1Z('OLV[EX:;8+FD][(-6/CKTK!I +M[4Y,XMHZ]\\LPGN8H^D>20S3UX&JDJ:/+QF%95]@=7,UP`W@=;3\P]TC9D09 +M&C_!(2KDXV(F`=[G,*,%MJ_H>0$$/"@EG;?#^`Y`'KOF&V/,^$R2I9$K9LVI +M-D>6M1E_:@4PL$V*?73X$ +M1MG04A0=!84XEXJ][].R@7(F:T4_2Z'-.5%EB,M@`)"\_4#FMGA+5["$#&1> +MJ#QL[]E2Y"M[Z&[@S(S+%H!8AJ3X2>$2$^?ON:Q&3XX<=V&38KPJ5W!#WFCB +M@=&[B,3H#X47>%<8;,5IC1N.FNGFX;)"GB.'']:)VFD;"+&-(!#5T'U<)(+O +M&J(5QBUZGK/*IW/\@7G)`2=(BH1='+GGB9"84HZOY?UOP^$Q;/\"^G'J.`NF +MDWWF2ZZJ[2`A^I4U+H2QJ.1 +MW]`]D\O@MRVP&3SY]W3]*0;O2``]['8>,K-=.\.IEN>A2@0F4U[/VG^?X;M0:PAH/%\P66Y\[\? +M61`G?2*TI:\FK38]3"X>H6F@;2=#>X@3C46__"J-YL68\^C`)[=,;\`KLX,5!]#A^:["D2]062\R[%3V)_3]4A`H@P;J.A68):J).`1 +MAS-)W08[8[LE>0:F]P;?74PZ`%/1`VD#1$6TX#$J@]0K^$P8VE..7R=P-B<1 +M;*\BF"U:D86.7D4-HG"DI3C#^=4@5U0FGOU82'W7T:/K\E/NFHG>J]9TL9>& +MY53O?PLL).<$'*'U3+3^TO2T&+BP@D2MZ0255J)KX7SXC9?>JK_ +M:.U[VWR=OM5+&>_I,RU1T?369X\BIG25ER0NX\K2T?3\)5Z@-)K`$+8SY5YP +M[PD\<114UNJ<,NQ9=2J]?9^+]YN@H3-C(G#G'! +MA)$.:)!1)9U)G(@:L-64CYII",^Z$DSWQHIELP-PY*+J+4WM*'*;.;:%@^>0 +M^2"-1^7BU9^*(;XH!#+IR3K@X8OZSG?T>QOQ^WXEFDXIF3]#I[`*G^:/"T_\ +M6PZ(NK,^/3LM4O`.&:)DGM$I'9/Z9#AR`SKQIO.<":2P>^(4># +M4RM[_OP;0=;G6[[NF>'375"HP<9*@C:3R+!UQEDEEWFF +M8'43S7_?8[-1U@_NPY,\WQUN]'LC1SF%*X))?+SGME`BHEFUC2ESL5`I_$V: +M%O2*PU[KR,*XQ>#N%;#*^9B,/(M$A5JUUDB:C:B'O&Y&P>5(N6[5DK>I+Q.U +M1">@S'+;[K\2!1JL[(!XK),S7_$OZM,87>%Z*BF1XCE_^:,8*:61;N^Z#L2H +MY^X#[O0Q.0?P,L_G.%CWQB>*WZ4$:P^H>8H-;N[$6DOC53LW;#"M1)%7-[EC +M6.`AP9:P\QZLPB#$`>QL%),MGXMF=;;H!;EZ/$+/J_4P#5_FZ#-RTW2&,>O! +MG'.'VTP_R:*?I6J.3EWJ!U_+/82#!`^6=L&1'ZULT/3HLK(<.PQ1XIJ'2.C, +M=,!+'_^&FOOM3Z>,;$0Q#F!QF;IONHG]=[UA'E<;U/?"K"&O#HS_NV<[1+?N +M3Z%)/Q<4B_015+BYFI@$$;MW\GY#5J""8L^*>IKC.N0<+/A)%O-7FBFJG>L' +M6?LH!O*BG11'T*V/O'>&9JP'I87^&-15A5"`+O'&E0M0']-94CG.[.P8`53XOZ3*\_LYL(-&V+BI#K7 +M:O`-B6CF5R)CQSK0:=L[MTSK,0:#RY1(,,5VK"KC>%%3NH=9&`(2@W&USK>S +MN4.[B4:CY777`O:-XRV_EJA=>#$AV-5?#-4AZ(WRF@1QC>`PCMR"K^F%.EDX +M-L#4+/1*.1FK]YHT_/%)6GG=!V9I%"TC.;@R7[XD[R[)1)(C9OHC3(GBQ,== +MX_4H]YR.?/60EYKKA39M!QT?T%U%:SOSZ=/=PYNMGUJ#;!,S%`OHX"@RYZEZ +M_[^F1_G+@E1X6OJ=:B[0Y/*6A8%/#1>DV:*6K5OP`25'LM7XF&O/W3N$2[5T +M,S"C&6R1-#*VH$-M!9-["[2 +M&K>)6`_M"&NX[*_?.3\;C29[M463I[(4V(6).%I\??P>R4U2+^Z3% +M\0A>)_Z0NY=EU/N]^%7:WR;-LKUS7,8$P(WE;<\OT0=,PY@S>M[;UF.8=X/\ +MH!;\28=GE9R2UMP,"]Q_-3^FL-#]:Y`J7?BFNP[K'\'EF1@+GY;T!(,GJU/J +M,]*:-C'Y)H9UNQJ_DKW,OT=>4?C^G%#K^!49>,7BZE5H`->&6NN6RIOW/X52 +M[3]Z`B"ETS44/PR<;UXT%PF.YDDF_2*]T?2=S%NJCFQ?^27"70?_A6*M*\%M +MWK.!-7R7"AX_"HW>FEN+$SI?:ZB\),]EX].#Q:/>"MZ+S!"OM'^T!1HY`O+^ +M`J[K9"/W>3M<*@UUE<`NPZD_:*Q:!\KDD^-T&[8=-.0 +MU$5@!`[[)EU$-AI!;Z]8TP>9)_1SS>@MHRW?L(3D=]95:]M"562VXRZIT(B` +MRR8.J1L%-:%CD&:KC'R8FQ@L1_IHT3_J0T9.!$5-XJX6>1"G[8"SO`81STJJ +MT0%::GT2GA&P53.W3H*+;RUE=(&N>EIF%`/R1\0V;KJX`];HF/[0>=7RH=0= +M;0JC,AV2^DY'-'85\1X37!ER=S,&RSRQ +M)NVC8%+LH)6Z3\+Y\\B-3-2&7E5R<^`I<_K1P"H_#)SNKG*$GG?T.+3.T)!/ +M40E^B)R,(.$D"X1ZS!+>5O@5$/@!_W(E0K"7R?=V:2>>NT3B.@O5G[B5W<%) +MCCS>!MGC4UW3J^E\[/M;/4CRNVGZ_@'[&<9-14.10"O9"NQV/MJ>#H,B4,)< +M]W1FV'[E*I\J*)Q*"TSZ +M.=-PU\@I^/`9L*CB==D^#J,;#\A*U/5"8SI_H:SOF]7Z'FT;H[6?.DE,S`Y* +MN\F0>'J4I01"V9HU2`('I+=1W@0Z6;P-:B\X>YAUALA48'7=\,,Z +M&R/-O,'A`QQX)W\]M.5S4LGE=""6MO`V9@CY`6&-3($'!=O2_"W)\`2WPFAC"*01T6MG7=&`"XP_V?6W%X`8;!;$#2_'J(H(NQ^;,7>L\?/\B67 +M0,Q1>!TG\$@\161Q`973_,T6^[X_$E."H/JW4<6:]R-]XHY`,^!(<%W@_TQ) +MPG`GXP;8%S9HBS>%[1!?1+[VQ$`YNK0VE1!+70E27NR'#UA)Y)%M;)1)EGNW +MY;9HD'0G'P,??T-QJU@**]#/I`(6 +M+J7,L'+OR7P`/@FRA#`BPZ`1E]PO=59=VD8\_-X,*R17!JT")NIJC8.1$;C2 +MJ%[8SKH.7BXQ$R6K$*-P0QJW1V5XO=C]F@K@],U!64D$U80L+-M`K20RKM(H +M:S8WYTW'3)>Z`G5>?MK)WR"LB( +MP$EMHZ9`-*L(CAQ(3\UUL%/QD6GCKY\-S9A;UBL&K90H4>)+'-;A[W5VC:FZ/J=]>ES5- +MQJ)`^DG*!".9`Z3_[1&>>M"Z>AWC\=#,A/S]M$HDJ'GS9&UFOVWI3CW +M7=7X+M4]Y:W=*;3I6\:55A!M?7!&X[*S/&EBMD3%:ZMIT +M4EG\>GE,7WF8L=E,'$=DMS#[U='GV:P8W"-1.#3<^"7R-]H"V7]4>$3RJ;86 +M_U+1RA=I&!\^GHE#8,YSCR%(](\;:O^F-;)%T;W33\Q,*"6G\`>5;JX)RA&D +M?WYJ;)I+ZK`5HW`F89`R>XN3V($@?=$R3Z1.]3*82]'ZR[^$9!:*Z_(`Q>M9[F"JJKH7$GDD6Y#ODH0&^ +MFSG2,V"'P^'8"TMOO;UG!/:6G?5-;N!V"ZERHUO]\U]VYXUJ.V3'!`?MM%5+ +M2II8>P3O(*BG6U\!;^VC$MDT5T,I:^:P/5(.=',BTE2S"^YZ2P?3Y0D7/9P9 +MXUJ<4+9'BXEJKX()%;52=&R4QEWIK;0\F`*?,02>7B'U;"GF`D-/.^\NEP!I +M=)*`!QR]?$4%"0?WK0 +MI!NNB^X)O'PBN0'Q?E:[6L.B/#EM^I[92G]67"+ABFR&C,WCY/WKR4AT*#;N +MEYL3I"^NLY*V4*94E3T[=XT\LVNX&%#@7'C\A24B!TMN1XW<^2OF\;@:=3RZ +M"*-AWSFAWIO)MK@Z'05[/R7YMN!'-.Z+WI/1.H@ANIHZP6\BY!C5Y()VO[>W +M[,-@7(LL\I7O(5C)D&DA#)-Q_#'\PG=5I(*?]4RUJ5\!!HS"UI7BYL7(8WUY +M'H723FW8[%M17>]^"#'H@6ZF;N`X,):=@*Y@%HJW7YAV>01G+4KDDSRY:KYR]\O7\K1O\*;STB2S +M>I@MM8-3Z;R)O4T?.PLXZ/XB;KR(N%P\L--6M3BGRE>5B_+PE(-P%H$AJQOF +MWN*,X3(^`(ZK/RA+\C5`]N6"?[V!%G2<)$M.`\)$;X5EN8X3?87?K)L>09T\7\]:V:J^%AC#:B'W2T +MU.>-#LV(^^?3-X:(F7M9Q_]&B+YPJ5H%;IE(:RK]5<;DK/N#VIFE+M`A*06> +M-H4LMW1N?0O9]K)I"FD<@I?QFZ8J7'^(YFEYP.Z6U#^[[`\>P(J&,'R2%(5$ +M13)U*\YQ6%W%"Y=9=\]L%%BH1O!$_,N/3P%42LC'1K^MH$6,#1#77SN;QXSL=MX=OHYT?EV@DB4X,?9 +M2!!AMU_E@OE)R\86SLK2\8W?-:ZY]Z6M32]%VM[J:E(,.XB;F.)W54/A\(I< +M1.")(+J3J+=!`JB&K3;%8=@LO'IC2>)!EVN3SSK>USU%[RHJ_"+,O,-K]B%^F(E10C3*O;1-#Y9=$-MXCU']"++WR7R-CIB$;O +MMBPP$(7*XI-19<*W`;.84E4V3^RAHQ*G@9[A)N%4%+H\"L9ONURW(P)6CI56 +MUPQ5H-L<,M;V2J3HV5$(F,;T!JG79JDQ$8RD48V(>&IPHDXP=`&KMEDR=9N% +M*-P1'343C[]';+""2=L==T#%?(]*O!7HA";_4H*\';,:S$I,_'',61P?07*= +MURS\X8T9Z>_/OF/_-OWY9G]0,P[0/^>H<^PN&*D/YVS-3SR20D>][AE`\HM3 +M,E(W)+1[2SY@-WD>D$.]-%CSS$E>6<7>1ARR +MB4?Z0^VA0I%^O+2ICBI`L/Y,J\'^17(-+MH#I6&SI""Z+5+VZBY38A%<:T?B +MF2:@8%U=-3@94WJ<9EUF23.SE@%-E1BD8\+%W_EW>L[&4BN=$V>&=7LV\+U0 +M#>"#RBOQ>N$V1P_W9=V1JIYHDJ=3):N.L#UFUN4:2W<=+C]0&KT\TFVE\$'F`JD9O\#:(NW +M]6S^P!BI-[IN?&+.+4NY*18);F^38!=0XJ?$CG`(HPC'PI&:/#BH5';>?]2R +M&O*)MCK25D[0#HI^7A"3.B?S>'B#\["0Q_.9X/0OG"NDI*K)W_J4+6()@*7# +M%)[06D)S>[MXVH+$"+2^[Q3>]-4UQTR]U4ZY?4U'XBR/3-(BT/W&YG?C[=D" +M=O2.R#3_''@/SFS6(QJ7N`-#/5]T0THO0.#?T17`URNQ6WN\94Z_X+$ID`(F +MO:LJUY'8R+WT85B?.6C/AD0V$!1/R.IO!>&4I:).+8\<@TTVY^Y2>@*AG:K% +M\@MOHR](%=7O:@T(`)2_RDI!,@/G2C&$+W1Q3'"F;J:N+F'KHQ)=RN4^I#!> +MKKO+SW7X(G\J)9(X)U'[R]@$FE%_\2&KR-[3K_*7:!@1,7`E.-,EXC96?RPD +M'C_B,^E_]EV8?*)MX`^UA%%=2V??K.\O`2^Z:AJM]?%-^;]=BR8O?I`DJIIU?PT:*>]URUG+/;86G +MR@6?9DK/YRK[('R;JVQ%G[O+""[$6]08H,*STF\5QR">356%/VV"4T_?=&FN +MSTOZ-(32T1P-UU.@VE=^FW)_7*ZE4,$KJG@HJS>S'Q+R(87BAR%YD_RN0'D$ +M>5UTK=CHD&>4-1"V1.X.<9UR09M6FRDUJA0!-YB:*NZ\-9)X6$'Y:"\BSBWK`5T2`;I +MQ7#G@\%&:D>5):&Z%PHSXWX,4GB&6EF@_XLLBBQ@F?AHOFV@U)EUTEG%0BM? +M2.F?O/-P'?SV.DJ4^X%$]->]=6Y*JC[&P'J]\3_1`24=+[[CBJU*X:E>S-F& +MOW0%6M9!!7KY?6#9$EV^JB-(T&FQ$_'VPQ;[4@UH6DD+R%PN1SZJ?$17VMA_ +MA\[D%#.U6:X?73YAN+=33=;IA)>ZU?E.'5.C-<])'EU.".:U"3F1Z3 +MYL8HK^%:\V1HW%IGR;IT.N;AS_[C.!6OY>S=G.B4#B.3102O/4-6Y6-J`.(; +M(!1>.DR\&?*[S(AM>/71`G&W+^ZR3\ORRY=0<2*`3LT64=)+@LX#D4=/$?(I +M7A8?ICF*67#/,APS4]_/\#!$#M>( +MUP4RY<072HA-84$WWEX9D?TAD2_U4]$:MEGA12+LE/.BW45[X6?2H\:D\F4L +M5$()%'S:&MO3#8Z<^Z-8[\'5L1#V9][!.3(O):Y!L#%<\:0R[.Z(/U@_04*T +M7"4/0JF&V+Y$Q7.#4HD(U$YI;IB0!?_T7PO``K(@[M0\:']W[0F4YB89;X=T +M?//R]0!RNQF?A$=+'S]2*R>\A1=X2Q>W_"@UVX7$_.P1*K,XZ>-N,ZI%=LK] +M.Q+:'!"57XN.Y74CZL08Z#7O!]:EJ<9\^!C_Y9E9B-L]&4E(]B;M$/B4[%^+ +M.8;;O-D;"T6AR5;)>6U+%(@C04S<1BV<1E9%C.PD +M]C9J$+.A(T;UHYSJGSVT9^9A(!5=QVPY.:_.B"H9ZT"&(.KW1_')PTC%RV.[ +M?PO_O1U@4B`XMA@0RC6\3S@L"AQU6[T]$8U7R;)Z)DTCK'&9#.+C+^&&&DYNP@(GK:3_N.90@%)9$HF7=637RZK0\9[BQ@M=ZWBQ +M+4MVW#7DW_\4O@C#H67A`$&F0@Y"`EB)[UE:`LG^SR`'`/,/G%[OC0?6PC;3 +M83LI`1%K!`3X$V$ZNN:T##NL&`"\%Y=6C.3-1D2V1VR79@E"203VQ"Z_@IOE +M!.`4^'6=W\WA/\>8"K1C4;@G%8G3H&_G\)XH=QNT76(ZC;NVXT>/\V8\P%2R +MO$"Z[>('EE/F0V+U#_2OI]?]&RRGS[!C*F_1EW^=@I%RQFK#F99,)Q!,:-:F +MP8\!J.:OS["F\OD_>G3^2!X6T*7E_1-Y1.JG>*&M=-_M=41HT->^V:U(*A$W +M1F[_^,GT8WSVA3W8(YX/1,Z&,&(3)L+3DC3ELC78"(ACCGA6@5>SN +MB^F9BW\>)8-'\<9D%6(Y4Z=9!_-`DO-1@6_$<1O6;X[X8I@S0%953(_'V&=A +M,H-8O)(S@V\CNWEFV>$CPT)F9FC +M)>P/A\=U-8Y9*^:9-#[,JFM]Q+MBXRO8'M).(!W<.+7*-6XK7DYWV1!F9XF= +M^:WH#9?D"1Y('34"J!V&J%Z-12W1#G^&1Q(^@;C+W"6TP.I(VDHDR.3JE9H[ +MR!N1W4W0H/7+A0^PD%\"#D.DP&ZQ?;X46]QSQ*X.3>\LNP=/F;KZI:;T;N`L +M;J^6D-1H17($I>]H%2SHW.F3)P!M.'L!S_$*!.XA_F/`+.R;VN6H>\$Z9",K +MYY9Q6B3YR2\]6MBIF+]/Z3WF,_L%#.M)NNI:&;^6A`V!=`R%0>Z2,MGB60.M +M^VWXB%J.$D]NW?%EAH*?:2`4*K+XGR`VQ:5L6%TCRJOUG?,JQBS?B!T">>"/ +MY%ZKY=8YCBZU\@OD%M/IC\R90*3EV!%;Y,T:-&@_":\`_I8S)UM)7L)S4^WV +M>#'Z*E_L!61$1'GX!TTI:U_++;[#NG`C'RE/ZX$\T"$&ZU@P#67=& +MPGN]&,@9A3@[9"R)PU>YY%H^'HSK'YZ<;.;W.]=_3S7,A3Q-26]V +M/D7$`-\OW1[?6!`;9SN5V$77WI?+8J2(FRY16F!8V9C*&5\B`$S2KS=2+3`_ +MT_=<1.K=#KIMQADA0J=ON52%BX3\MW<$-S0/.=++&4*DWY,?W3%VBOJOG:=N +M_J>_HJ/%C:6;@VKM@!I'>)4"I,MI8I4A);?HD7FCU#+**%.U-=&IHPWMVL/! +MFC_130$.[39AOC?`:QIVX-?\#VD#C>"((X^ND9&K_7&@//A=Q-XIR-'(>K.: +MTPH7TO5O]/+29;(A2%VQ.=75S!#P(]MVILHI8DGAH`(([63/[O->*?QHW%VH +M2JFTA6RS$P'KOVL2VPU@OJT[@6R#&0E/V;]4RJ<'"PW'HLMVGEU:X8FKDO:1 +MW!R)AWR6\';B!3&MC;[:PP&Q-G?:\?9558DYJI28PGUD:Z[JES%P4&]93(TL +M=,.P@RWH'7K]L6)RQ]HPLH`!JC0+]@@#=N<$].W`^.^"'3Q>D\:(#W+GN;T* +M$7LN*B38+CTYB0L[N)#[\6]*\"%'W.?OIT!P@5AXVT4A#"V$6)$9\8GG#? +M+!O:IFH8&-_YKRL +MEW$$.A,]P9"]><_B1\U^YXTI?.L1^!$[&;,*L?93'^V_RP$?L9_"O_O&ZS1L:&YNU_^!V)""@D0SHK +MG&FB0+F%,>.//SU4D!CA$S"S]"H[ +M&0/!AS_2MR9^=>VK\6'#Q;B6_]]A+4CNHV2%##+=?'&@/+5E?#AK,F1JY:I" +M,^2C3!D@$7>_^U%46/*(F79F=74B0R*2-&$EO)2K>4Q9*"`M\5[1YII3$'-M +M"2JJ)HX.^Q/7*W+=55U\2%]O<9*!>?H)U\P]0Z1&5E4I1V8B:?:!W8%;NW.D +M:TB$%!F:(SZ8%5HIT_?F,!;[A]5P=#4"0_`SKC'E"KR)"E-K)+'.D1@=4+K3 +MCQ1G8>L*3NBF;U5;!3#/:X<8;EM'B@>9%)_[*>@I1M]?(-RA$EQH"Y-4./4I +M0Y``,MS4SR,O!,X"6H1/-;?]O"A*WK-,&24+A$:&,$C$W8 +M;O/O?29Z4O'/D7RJ`^KMJ]="&-]=V@$PLC'3=+F^LTVF0W.9$90).33!1YH! +M?W!$[L2:CE"NOI8AD+UV$8@P\UUH344?!_]J!SZ(1;5`^::;8$YZKO?6[A($ +MS*I"!?.Q#4;EY%%<-VJX4V$1G4P42@ES]@,2#8M6L98!]O]`OR:C(O9WC]8TZ3NT2YFU`Q^M<2 +M.\OOM\V*MY:F,%G1;"D[:=474-)O'+K6Z'5.^+Y +MMW3(0-9NWHA"PC`;FK`=T6KA2A;3'["L*DBL*RG!.2^/PU_#"52#ZXV0T8K' +MK8'_%^"=9?#BI'-FNM?6)^CGR.E`+'+%!#CO]`4HV-#./V5,P$^S;F(=?*(% +ME*@?9ATU`(0P!:.\1%1.]C2>$B3TMU#RB\P)V/O>L2>8WYT5I4E'4";`5[BA +M#AORUC'*7Z>B@]K;=;X1E3O!AI9,5<#ZY4\30)IFVZ[QX0V<#<="OT4>9KNQ +MI0=&]7:O&R=E\N'>2AFMG8D*`==$NXG55K?%-&+*?0H.A].CNS2Y"7]8.P\7^,R820PHS`FV!@FU(6" +MO&2/8V0S>Q\!]K<+P?\TJ\&3G1'LKG$,F`#93KD#OGTU`]B3S^D.T`I_8+K7["LI +M1*\ZB`!FF$P>BBE1HSH?25;N>+,K4=!;TH98*F8='B+LVAS0ITZ +M%T*D0TV3E*+U.9=C'W[;$PTI7F65B@(]<1\#(^]LAMF-]G_W%H+,NFCTTB8K +MC\LT<(YN`J:-X_BI&)Q-?=[^Z-+0S$$*'^')B>WH,5-V0?N5.2B&+?&M%4]8 +M>FB_T556;M>RB")IL`^\\^*[T[5D`>[)3M?`@-5_ +M\&*-<=MMS:0D\J%Q7B0/'$C4?`HC7(P*'Y7J#?=Z4&^HHYEJ7G,=@\>Q-@@?B9UUF>GHQCM*`LI7$ +M9HF'$I\B%WX)"$D=TZ_1HBB\265L9=-3+5HY0R?F-5G90=[QZ+^@YU?H#U0Y +MH\);TS]1O][F#4,Q@<04>8UA<.GYWMJ&#G_C%O,@D,YSA0K(S>:"VV4-!97] +M?6UK\0C7$\4/;)&0(^.0WV%F61HSI[/L_[?V1Y;P4;?"7'EE9PD1(4N=?H@"D:>[-=$FX93R4M\'RAPAQ-<*N/" +MV3L4O0@H)NYW<*4Z^=W=T$]\MU2YD!ZC/F<@HA\I_E-QM4*4)4IC>_WW0V>M +MD3+S**B/65,RZ6WW(M(4*E4FNV)BNWH'@+/L\HO-X:@1[TB36GEJ;\E_PS2* +MQE<+7L?[BW6TV(F&&::9=UA>*MGR12_/I?5>0_$_T_M7^(":[8N84X)VJ2_` +M`O`563$&9BXIT>`)_'AZ!4X%<&1IX:9&(DJ6RSEY'_H&$>&:=H7\^MB^$\TV +M5^4-9XYD,(9GR]9L!T[*E$8EM*.#G71T^E&W&H!]K)D()%`:\J:Y]-J-E^"6 +M?;_E(&GZ*@GA%6^?`J_>+DG=!G#)3")K^I`E%&AE+X(0BYXM`">WF=IV[)`$RABT!V/1?P'N?3_SI[;* +M(HT/3&8Z..T)Y9MU^)_QP%3ZPT=DE`)-=XZ*7\E_)R@]R#.?/%-T5D&E\(DR +MG"6SZ^Q*]*\T"]$3UF:?2DF,ER;+;+>';A1H1DAH:P7%7B%("766/J7[!H0B +MU9*)"EHL!;\L19P1_YPIA]+=,JGZ5:>78:(++59M[N"C4+H4(0,FNEN<\V21 +M(`A,8B^8(AJ(1.>%%9\@/A4QI-EBR]6KNR#=X?\1(5ER,[/9):J<>[8DR"8^ +MQ#@.J:E.X0@6/J67;Z\Q)W'2[FJ,\3?$ +M@FP&\583^YH&F;3H:@FQF(MN0`_M(-UACLW)LN)4<-!') +MQ,LQ*P#^^5MT9SRJ""A](9Z92JGPQ(REECUVU#!WIAZ]M'\!N[8?/*WD,[<9 +ML_4LQBB3S<_/?JQHKA]+@+&>L"J11^P"@26\_M:B'`6D<\-%H"#ULLE>GO!T +M\L;1IC`!!&/9@UY!.W(8%'3#3;A*P9T^W"S,X8%'(U4+0CFYRK.&32`F)TQ1 +MJ+PG'S"C1!>->'^,Q/J;A&WDM?.B&(*YC0M6-L6[,C!.'611:C'4L,TF!+/K +M4>=);K2P=AP]0ITYP>:77WVCC_>RQ-?-NU0)4YKBHC'\M%V2J:U&Y/J)M6RE +M)1)X^^E0LTX>YQPV!2J`^L4:9G];K4[S&Q]%-`;[U54/#"/V4%6,"#MP6C14 +M=E$X1NSMLZLH8J9%\59<72%'JM,T`)R^U4R)WK2,'T+>@40S+K.7AW]I:G_'T(N^4*R\;1">O@K7*ABWFPD<\T@8/_I@V_D02\79%;ELZ6 +M+S9GW./[9`;)A@\KKLW%6^'R$]VYI=I2X0=]K##$1;?Y.AJ6WXJQB +MOZ%*W$=-_^'0QHE$)0^=]JF]XYJ]:(9//-L`>GUQJ/(9V%^X^HCB(PT!A;E` +M$`&E@Z%D6ZZU-BAD<_*%KW,W,%K"-V"A+7V^@_O@+E>G\YT%>UD$]>T5<#.0 +M0/\(2)^;:STU!2S`"X:2=6&MDM`-.95]DG$* +MIO@89)&8+:.\M;TJ5GN-!/3`/V:V:N`L+[^$T7E3?5!W:R])6>)4-#.)49!< +M[ZDY8/J?KWCMM7N3P@ZI80;#0P3+B]'Z>(>R+85W?WI>*8E&S'6A690"K5&) +M8++Z+^&BK7I#-/88))IT(Y`A##BU>?_5@M$(="6*#TR&",H/IQ['.9A>D'E[ +MCWD9(RDX4L4A8L,9'X..L#1A1 +MSDXEP7R^L1BU=5G[%[DE9"JB!=-M,$0PG)EI1+ +MTY0$^25.B016+,6X1P"_=\(/8^E`$1CY];9UO=@Q::/CF-[MX7&]@7]&:RU* +M@SD!2AP;I2QB4.KMY20"JS%$@UM"OGNS0%)5.RJT&9"=/$#RM61^^KM+X\?7PER%T!5!QKZW\X$>+2HD+/I8;CSQ.U&/>_XUQDG5Y.N +MAA:VB,MOQ^P8!SH\&A!M+`8]#?B<.(._%,Y;@DK7"\W2[*]4VI@)2F?Z^O01 +MB(S7%SV%ZUP/^--Q*!H`/>K3;NJ:%=8W3+_\#G,W*'Q#'.I2/A:]U5QB@.$4 +M-/"P,HL?9Q+DQ]F'H.H`EA%>NG$V%$$JXQ'3)WZ^6Q^/`)_RPD%U=&_0OU>B +MH2&$-7OT5$_>FF:N/X<-1X0+1RH-:4@S,EF`E"C.QWF6QZFT^EWT"<@YNPHZ +MQ'.X,.].$<;6KRL.]5=2*_*W>EFT:&P1'SKB'S)AE5?87'"D]_VR1^C@I>55 +M3P5FV581&!JSG.>@H-]J-@@&'/8I:_OQIMH!(\M1ABO_O%!P&6/7OZ0[B'[+F165YYKKP.>OC_DT!"B_(4%&(PR)RX?E4\ +MAT>2,NN#MR9]]/MGHGM"'SR7$RFN-U%#Y(K]2`%Y5 +MQ_U=PD?=.N)YE:8L1.XMZS.G$`J$(6;#+OP<^.:QFN4;>R3,GFD`:U:J?_EO +MJ!2YS4;IO_2`]UT)'Q&M+[U^_HJ]N +M_FUX5$1GA*SE:_8$RQX_-+ZY.[^G`T-D7_89L,H>FC=>WSW%F8@5![*RAB.K +M0AB.M,U2YI@@,PC-[%:J\C@@>W%I3%4=DR%&"+ +MHGGF_(T3N&)X-T4B#8P!TJC[_>J9+V2G,<3J0@\]DSD^3DT$]9T1\2OM$PBKZC +MIMK0$!JL:V!W%$->V>F*HI2ND7"-PQ,F5!-/@;R4<68[5!MLUI#_;\V,T#&D.$O2HB)-I*>F0"?M);9:^9!5 +MG6C'3JKX@'>F!Y[;L14LTC'Z[`#J"Q''T-L(EZ_Y(08]:B/P=?RW&2S?2"1526V]J]> +M@]\9ZGMYPG)J>;\#_>-1/"H@6--EL,C=T&)O^0S#GV%RPOZ:&]\NT<"S]OZ# +M@AN%?N$5+?,T=:7RWV2^4?[J5Y?(@048BR=9IS#9/UU_.%)-5\\T<89_H?(1 +MIG]=R^7Q#F?-U0--OO))J*VTN1!49&]LVJ#U[&"`.ZHD<&'B#'\E;G(&EI`= +M'0+5D36<\+.4]!SG%'\8HB9=?6:X'WC39J=HU'AF6U_/"5&)P9`4W.\TT[V" +M,X)PFX7XHM"AN^H0E4I4Y"G.5"<%UK[QEO?#;%L6#!0KE\._)DS&00861K1X +M1LH6]`34.(SCIS&LJ%YZR&EL_=5[FQ"G:]XQC_('3MT%*$>U$I6A_8>IV6#I-7J[N1-J/@/F-.PMG0*,!;N`-0[UNEQFD(I +MB&Q)^_NG^A8E+*0NG&?6&/($6HYPGH;R2LY?Y\,E1'8QF;*?SQC;M>I9S%). +MUR#%<)GKO?$[^ND-DI=+5N7`Z5$K)H<50.BSBNB[C:[3#1H4*VVCRPCG"FFX +M&"Q1,GC8ZUJ-K!?K23P.@J\'Q.J";G=XQWA;HI[KFW5=+SK97*RL-%72#L$7 +M^1"#K8F@'N,5E0V2!C&$<22D.Q-P,J.R7[FJ_6]^$<0PKC4&,BG(`[#=U%]8 +M%G"ZC*M$.+GF$M($L)$7,V]0U>JV:K>),/M[>P'R^L'9A_8#NCO\QAOFOY4^ +M8%:=>EKWE7+NTZ>W2"2--VZ.%+:5T2R0#,L[G;@K*7#VBP7Z'IZY9S1\.CBW +M#.3>X-N7K3Z7A,'N((4.0*Y&>T8Z4=A6A\!?U+NOWP,)#5$,P,?.JQ9GH=D$G_%190E,0D\'Q$"0$PC\E^J]*AI1S`!D +M<*?2S)`"_'K'5FY**?B6K#>MU)&&C!T<@^8?>J4O>H@IUQX?@$-$SM6'WDR+ +M@E4926.8XL#]%1(N6J5!B@E27,Y(YHJBDV<6NGO7:JW`(ED +MXV=QHSVV[/<">\\,(DS\$*<91GIYIE/CN:Q-XM/_73+6WQWD=@RC?LXFKC5) +M\+S+:2$<7Q'U`2A1,P&)P`7$V>IP*HGS4Y +M0^8,M2YI<^M93A97!N9$.7-TT*N2!=+-;=]*D-(2-2U>=[^K#ZW*C(KMI\ZC +M`:B-*=?)4$>LP4?VA&2,K%W%;5@_A)WN6K*CI,_37)IY4=I0.'Y;JZPJA%9] +M4D&H6_,7*BJBD7FUF_"1)WMTBF#?Y]$G#]!4MU"G=Z>8HX--5Z;WLSKJTWEM +MD4^Q6\X+EIU;<=XW&WS/)*7@PY'IJW\NO0`*Q3O-#7=_;*#M@RK#7EBER8II +M.XP>R@NCMRWBXNOK>G5)/[S"_N`BWI63.`NK%OYIS5+W/L +M>T2'?*J.6I[-8Y0<"HM&'18TA!K$U4@4S(X1('NJ1CJQA#.-1/:/\@555?]/)G'@*@9:%OE.1@*)9:?:U).I?Y:)!A1_SCM,A!N2M70J4/ +MEJAH+(1A.1Z#`['_DABT'<^6`!2)E:!5VF]6%H.2R*[<^`Y>P5(RT)MUNL^# +MM[E!.JU_+1#CB6)K>H8!1-\:,A=P@MMIT8MRZJ\5TE1I5#G[.. +M9A;?L0F!["40X_K<,1ZSQ:8A3KPW8?86;+G%D('9INV$M1V]^?!W6&1PK;O:AG>75L_XDW[&J +MF_3>?GE+4G-;I&2<6FI5_=.&8\)T]U#U$,U:2)> +MDIPF7`"VD\W'2=!S[ +MJDD<9$:'"+ZKU#KJSJA%75.HF4,U#HA8OBN9<6X>."0K/=^!H)E=+;<,:#PI +M[J0$MVS)2<\`-S-!6^0Z*&]`4T,"EG]R)AE7Z#14_,`Q!BU*DK/(O9`N8&F= +M,<;+/>MZ/JDY*,HV[;^FC_A!M)54Y/)L(_QH[K;O@!CX;TC>#Q3G6B)1MQ0O +M5*#RP/VZA=^;'[AO;$BY][V>JQ]).,)R)Y>.3HL-O05&<4,Z>RQU.*9,V"E` +MU#CYW-@,D00"D_X9E>#.!%[4`U.Q/YC@OUQY;+S+?R5::">L50SE<#`PK6KA +M&B[[/?*><;)-%]G?ZA_!YGO$=(>2LKZ&S[D,G+JX_Z +M&;OO4T7CBAL3US:^HC8W5]"GL2-]*]L$7KV`T#?7R.#NU:GF=1+GS2T#.GWL2F=1WVTC +M69,RH>T#V)*2=-,"'")C&S(8#Y8^:L#C!8&(.7R?(Q`2VP0X/=]NJ1,#/,MU?6I(<:P +M/K7L,Z;GB*K&"$`JANYHZF8-/`!FU)`_]5:H$>U%IFLU$BDQC+MQFGJ&F)Q, +M:@6?LQ&M28W-QZXG`J$M5G%7"T05.M4@Q'=OQTJOPR'1]KN45FB+@'",) +M5O?(K^Q8=H5M)WQND]Q\-X`-@-JTO%;$&:?S5Y00\9_Q(+.K![@QW&.BBBU! +M#?5H5_%(#JY#HYW]K&P]^@A3B':NL+CCDB5;E +MN)6%[L+?Q&?3MU"G/85&A+1W,PTRTP47N9EQS`@O*\M\?_?B?S +MO/M3K7=D:L,2G]GY8";S96+?)^QZ[[V9UXR8'\?U'M(TV +M3D?7@@-.N32I+\L0.D3)C3<:/&X:7MJ;T_L<^,\V1M>3%-I!J\S#E'JWB89' +M:.R"Z_WN,1LNC=#*12REAA2E!7#O9BOQPJ69N,>"YY-8=H=C(QDG6\"F,Y=* +M#IH=NXPF-E8;=,W_H)'I/V[',J/";=F!Y_5!G'6+\G[/\:.!;D*USD9HE*.E +MSA@,,8A4*%E(VPJ)AS>V +M%/@+*$]A^94RK7YM9@:Y*Y6F#F=LU-/U<5K6@BD^B'A);[O(X-(Y=55U*Q_@ +MBH1\(O"'<)<%`AZ_/1W!52;"3T'<8D"_H^,8-HNOM457D[T+D.B=%),)DLZ,P,($MN(GB'+2QF@@H= +MF^YQ@NZ=6\VSY>#B.F?0>%SK,'#3[*7&X"`M*38`K[\=P6+#75'@SQ`!S#'S +MF?8O/5/@+9N)?/57!A=T<$%]N<)(7!EXV'!5Q`2UY>IB!"(1&\2<8^GE^$^S +M2XZ--73P;L9IIMS,<)U^KQ:"Z9#`2[;_CP,^/X@+C`.Q2PQX*4>;*(/*$@,I +M*SV-0*S'ND/HNG>,42!@]89DN;2UW@E2-F10=#!OVTY5K\+_I,.L`,'PM3BQ +M]S$2AV5BO>-)5%BSG+E)0?WQZ+F22$,!_[$5[,K!J+Q-]354B^HD`NIG\$L! +M`R%OH=#LIOP]9#/,.U@>NT-^W70=XO+1\0"3K%`@?-_M?JPU[.I6X+=>4P(T +M:NIOF.XI+%]Z_-+'=0`:H1NHSN4*9NW"GQSGC,A9)M02Z8B4J8%-CM#ZUVP" +MZQT1.\^_TXR:"S#H#'#7)\R9AH`+-&B;"&IPMLTUI-?%U&N662="$9Q[$F9E +M3=O[2H3>DF9!'#!Y?3'B3P9QE'ZU3Y/EBZ>BAUIY_0*7#7T981+\QZD9YPM' +M9'),9H#;Q8M/>N>B'17_>QKG[Q0S";^E4A'<9Z%Y\G"^A*AN\ZY#L7HV.3+L +M7)#-N%D$&U.JCRG77X%,3AK2UL0IL3X[\H)\((ZXOWV%ST2=0G6YPQAU3>ZTW"]YZXXJ.))5$Z&K6!3YXHH/&6XI`/!9^Q@KJ +M;^L/_G6!&><2H*J`CW>(-E%*GG(2;8_\S8PV6]4IC'OS>EEI9D@NW[_`KZL' +M72@5,SR2>VM9/$8C^[J9+)V//JGX#6\'0C2"PZO-I*DD[X4%#)D(6.0U&N>BR&<\F%9UK:6"S7_N+ +M:[UUJW"3JO&\FJ;1BL/7(1F9T1L$[+*,$EA1KJS^A$0`>YVSF*1952=$*6W0/*ES^K +M#,KX(9=A/)Q9G--*HHL(W03<[EU%`<>U'O9^G[D9=H;LDR>O!?#;3AT1$1!Q\\N!OY?FW$,S43 +M@-B<:_^W%,7``APN+^0_];''NDJ>'*`J2S"(11P@YW^51]\M)H!G''7Y?],) +M>]@V%WD+3=\AT-&0(`C'J-%+<28[RNS=@AW18/4[`YX\U7^Q3WG+5HG2>TVO +M/I2_J(;0\+\'O8WRP\5[`<(WLS*;]RY7U^PS,KR@$*.L"E_&PK84W:#6%?)( +MV1L,0T_3MD%JO+>OIS@MXMT!SF!.3]X;!>5[8GEW6F*Z8-_E`0B277/EV,+; +M7.$M-_%:P4(UQ+:6DH9J?#UV.BI5&)I8[63J0FXD:\EX/`JPM0*S*GECU/YJX.))$=D>>U%FKUV5_^;!S,A[8L[Z!8]>[Y)ET6X2Z$-,4] +M=\C5/!\QO`+2I/!,HYH;-[]5&7E:?`UA"R97&68XT/^-P24HXK4DR23--$'*V.QZD0YP1C<$M>LQL`2&[TR$I65A070[V@!S[5.>`+DCLL +M_\1B?,)V/4,9+H,_S""[,;2YH%]FFL?DCLK,+S!Y%^^X`^(4K?QLT09MZZ`< +M*;_'`R@ZP[6P&1>>LW,\!!DB`;QW#$1[`;OEZ>/FG>/$V`QH5W9+68RSVR1, +M=<=1[K;[PO7@]SL@[FXE+4Q`L.:)=<4`GDY_H('S(HK]<$[$R0F!:Q4`H'YS +M8:L@*)W0_/+[303%C*Q'JE+BT7W+^^%3Q6KC*ABO\:1E;EZ'K6/9>F%WT-!( +MGH]D_!Y"25KZF8JV;O(Z#1C7]Q0`^$,]*((X?4B!3&QU/30QM\^+-8I=''>]5L)O`1*@V^WT9L<0)X4=;6_$%^1'#.>0 +MY?#?D56D)>)*C;F`$892!RDB[2"J7A3%*>646`[RM.D0=-_''9L-MN00Z>RK(S#E*7-8&!XYB->C4538V +M7L`O+'`+=0(UL:*21N3N5^`96J9KG-)R:"9Z)O=#\VQZDYB#2ZX0S/XD7MP" +M!Y-)\SXP5<5_4X43`AI$FV)KM>O-9Y8IGB'11@L&QT0QUC5ZNKP?$'IJ]5A/ +M5OHM>10;TI?.%K9J0$Y^9V3%HE^Z,QDP)TU!QCM!`2"'TC/#8G,`N`0FL!$9 +M<6Y2HW&VKN2._7W#B96:8^VL1]Y+"6._-S48+3-_2%>T(UOK-JZS6^&;)1;) +M<^V&+PP\,ACY0BHYG%G'+'+1,/!3@O_8KE]9"NH@'KVX'R/JHXM?1PP73N&J]^?X:V2`D#F/ +MX5D^W?@D1+=I/6VWBNIZ1`HL7-$F":#CA8V)QC\EZ%%U4D=)J6IY*]SI2#4@0O=6(QNFD_#DD +M(ODT#^V_B&)3U[BZF+V/@"CF5.(L&M?V^^1-VL#2Q]%F:3?FBZ'8S`E_`S5W +MN@H98PJ!#&1N[>9MA=4%(6\3;3>%&*VCV")=+V^@4?O`J"13C\X37^*Q]_W/ +MVH%A?(0$Q_MRMO?OL?<)T61SQB8ANUCT1;**F"[K.$+`V,56`O."S3/Z/_5W +MW)[,89R7F6%#IGP.D8^BQ^203_YKU@4&`B2M,G>!'`%5$RT>[(RI>TH;=LWFY6)`GX<"Y]@80BF.;A=1O-6 +M)X`3#$M+[U]B%BXE$+LW:+>:\5,&0;85?X>]YD%IP@STP98+K5P+'QQPA6@. +M26P_4_Y,1OTV'P8<)7>SE69QQ8V>_YRWG]A!X_#O:I\D[G.O@8(TT.477X&JF0Q-I*E:@A0<,G1X[D7#0']:4`A;>SN,G +MV.9;R$69ZH4Z##<)/9VB[L0O_;-5B0)'^+@OVM_0;^;W'^Y]3JQMC;R?+11W +M9`?-.3172.4V1^&)50-$XQH5>`;P=LO.8D@G:H`9P_AX\\"9IB`6:BDW4:F?XW,F5KG$-8Q-ZI.42 +M\;I%&JD&+X8W=DT-@=\!^3)*J4%?'^URY@]#=1J2"@FOS($QP3#*!ZA5F-N^ +MUG+"9?S6&B4DT`9(KD-%UW%8D*GE!KC*5:1UXU29MA4%?P(W:,WK?S!K[@_W +M!&4C)N).M6YE"->J=D[M_+P)"S>;6+'`7(S)T4/SL/@!31'Y3OT3++$$",'F +M:6%9&7[K96QVGS3%TAA"QTR]H-!R3R<1<`R2P'HOJIJV6B.7Y;.2]0\2-\:0]K9Z[U@,\]%Z:&,GHKLD +ML\A7S.D.8+2A(^@Z0K +ML!^Z;KY$S40ZH&U:_)E!^$3/7;QMLK9.=JD'Z=@_KET&#`6L?2SO]!8V-#2D +M:?RDJ?Q1#Y*0[R&R3YO\4I_]B4ON>O1SWI2/Q`0=6?\KU)4)"7F"H#V1%T90 +MD^-.2):=4C7='[PKDV4P.>@^O+D.#`;>.-8NE>"$V4KZAR/!F3"W$1R-5?AI +MT!3KS'2U[9T'B]_VQGK8EO=2]X.!7/;FHEQ^69:::A'_\QCI3;"[A&VA7/K[ +M_J.I9J8_!TB]8#L",NQFAQ:$D<2U2BYV@$Y?KP\?A!A.WIF&VXHE"L1I(/$B +MU*0U-&L4)26=KJAVU>+``[V&=GK?[=7VE5.J&,_JZ6XJ:ZJ)9^4TND5`W)LF +M#?_NX"A-5"4CE3H_W+FJ_9\>8^BZ4!6R>,]O+:O_"?X'36(U1X*)RD2"R:Q( +M#EXZ5NI**"5*:](0=JY+B>"A%ON2H+*'O7%`28-5!,E*R'$<#C@LKG]FITK3 +MG'GQ)W*%#[HL"GULYS,YD_#CAP`>YLO>HPT>GB]&3.8$8+4/7#TCR$QX+E32 +M146E#4[OA;VIZK'J*&)53/6O.QQZL])P_XFL`3-:`\X@.8!^"UF6QM.Q6-U!I]?*!AF])>J%/B@6$7"M^G_L,`%O&G< +M/TR&L:/PY$/G=BGY62T3$:T%JS@ZU^B#[]4&0&.E#FX<)N0W3BQ=5D!0`PXD +M6J"12`?,AF>0E(ZNXL-'B0FG_@-HO1K*$9&P#I\D@^!6=RHKK.)&G@17E$HL +M$^^CLK=/:2(,8;$"UL^+A7>O`>QQ7N"M,//D=5M(FC71'"6Q,QVL0Q#+>D +M+W.U\QQ(ZBYXW$[T6QIE@!F&HY!+3[/K;U@@='+!=03,XJ79E%2@*45Y$D#8 +MV)H''%F<$1Y/)K9O>B@F"-?!T;TSMV1)%6=19H^-7'R%"$+MO=#]+L1$L)%C +M^[+.SJ^AG'=@D;RN:F1DHDZW7:)$LR+P^O]\):B$I/N?3[AJD6-%SO_/9#M8@OER,L7K +M_PUAU0(F7I6*`?'^.C3MROPJRXM0W\_X`+\@U-E>J$&X>F__/6%/`2%F1B5. +MNU-G$.CZ`7;&-:8I\E=FJ;(P%_S.\V(1&ZV%87PR7S[>PM2J6S2"R%ND][?& +MZPYA6?_/`S+&SE$7[_;\`P7<)`0KY.'\W%^;$+L_E8%F!.EI'PT(#7;0C@R0 +M%ZC;9\=#WS4Y"#ZL?'U1BB&W#4&S7+X@@08T:\H4_,)XJ5_4.E[ZM"-X;%QN +M7,> +M6Y$38)2F4KC%LY,AR=>MD9FR1,15A#$@=F!0F'X/J-+Y;`9X_("`C])5/\*C +M@,TFW"@P56L)H3+D43-&)1N%VM?TQ0K;YA%$^1:&Y'/UV^7"*[&$WX9T"Z7& +MZA&G_#+V=R;3/1N4KA^,/YT2I+W*'+K&Q0LU_[';S8YG2FB)*2ZO9<.$.'!FG`F)Z +M4EH21"=JON2SS +M)S6!RXIC0I^]!A&J(MKN-UYL_M.\6LF%!^()XU]O',L4.QAMP@T5),?G=?+= +MPO$>J@SK6ST$`6LF:!D`<5BF.(U"`B,%]>:A%EN^'D[TT47D!/W:="="TCYA +MC_B$R"7LCW2$=URHP>F=E)N;X\G8!I*1RT'*:H:$M<".U&Z"/=VHY]B"3:^4F2E2\]"_,J[F2=I[3S +MRFFBU-+,U82ON`F9I:S)7[\?S7X3G%GJ"[D@4S-4;%ZM-Z7?6R74&C2=H/V9 +MUE_`D@P)GH_0U +M'=C*24-=N>^?'OVWN(E8,4DKXE^*W;'"-3=1!9"4CPD_M?FK4[;OU@*J):M6K63E4@U^7)L_ED350ABT%I<'9HB\?U_S)IM) +MT1(^]@G69VY`AJ),6"8>8(?A;C/8O=.8BB2&6=U(($=UJHKXR"=DE^3=8Q-L +M\ZA*]C<_PB;R97,.M(3V;8:>@1YF'T4Y-D68@0SCI+N@[,A[>,MS<-M')KQ +M)UD_SNMJ%JI#GMW410'`9DK?JFXVK:W_P&0C0'_H-UA#&*-B]X5]5F"FBQ,; +MV(1]0<"(!!IV">RBS&>=;D?I*>HY1I[S.^Q'0A"QE3>P!4)J-Z#.[?77T-"K +MOGAZIR\Y=GU5HNQQ'&@2/8R%Y?X]=":79F"LD85R"EA=M[!/,D]4&YX;6S,5 +M(T1K@ODVTR?M@=POD%7ZA=D8,A(.2@9P/P=X3(WFZ<+[-=MY>8:&G&T><&IHL:D-$CW&I<$AHZOOE&4WQ04 +MS4;$8?M!GIS-!_&CC0"*.2,X7E-"OPMH- +M4H^?]7C3(J7Y,OW1IJH#W"X+?6!)S%M;>W*6_`!,2T5%,P)U4F7C&I+2&VPZ +MVGY%9?A)"JA]K:W^7HE38`_1]..F4R_:Q';8QITD3?^1'0.5'B)BOMD6;67!-./Z`JU3>X3'&13J:8N,J\RT% +M.0R1OXTQ#.H*X=M'_6&!JRW+T&MG`H$KU0()&8'F!A0=:'JF_R4'5JXO.#ON +M?%1VXC)]A0;L&L6/7-[0H'&\)MO7YV/SY90G$1ZG4'WU=D$`Y@/GO1)99+N! +MAH92L/B6%SQ`4':94]C/!MXU9VP2MCXNF- +M*D&Y.&)DAGVUA$PR*1>`OHY=P1$(6%_5%Q\!3KZ$>E2_X0Q.BW?=@9+#11H" +M%APS@UZ0.$[J>*:44>1,8Q.J(*``AFL'5YDEKGNTAK7%/)FV^Y:EV(!$R>"_ +MV^>]JC+,OG$M'?3Y<7=B$N_-?4!7M;^7N%2QK,(FJWS +MVB<$:I<3"<.&$NNX%7:BC;LH@4]@?[MC-"Y(/\&K>I@V@!C4:188KHUOPZ*# +MR96+=[$SD"*@8(JZ6K0W>H<=#@*@?$'=8.2HU3O`>R1]S`D<>!"I&%.!&G!N +M\Z##P/M+W9WDW.K=Q.<7M@"()2\W]1H6E3,J5V8^%OB4@;K[&Y)LVRB3!O/6FRQ$OJ\DI+H=Q3M%L-RMP]9VAW(\H^S +M9I8ARZ.9:/QG;F:<-2%+4SZH9#7KOH&A]0$]F(-)1`F%;)L2*PO]Y3\8N%U> +MAWSBEF8>?9RW5=Q#K\9\BY+-_-DD[:^Y0J:RY)5B.'\^6(N4Y'U[RR6S-E,- +MQ)/"6;W8V^=XSTP6P]DTO*P'.:_K:#&H";Q(1G_5&CMKUD$!#6C"9=NSW^II +M4X@ANL3V;,_MT.0WG5B1A7*#`O'7>T"N"=*C[TE0M(`F+L9''0S9[1@DB>7V +MC'6W>5DIN^.EYUP!MJDDOB0\4`SFEAPQ)PEV-)+ZX*.QKZ] +MRXG[F6Z=>(H_0?GB'GJT-G^99O(PXD>MNABWI5?R`%2 +M,E.QUSMSV;%LL80*2/1D^CYV-\:'^'5XR_HG>E961&40!L(HT`P1'Q7D*H?F +M_]2^YK),88)]:D=Z`+:*]6C.3J@F7=8P,7S9@_.-&O.O +MF'92=*T6ZC86`J>V%=>&;%I(9=E)QQC1QWP,\_M5Y.J:2"KMR:WM+#,5K/[@ +MFBC;@P_NQ6P2CB[?VF`FK[Y!Z6_0QQ=ZW?%F)%JK#QE5TVC];I@QDE-%4A+< +MY5PYR^-S6Y.&O=[O7N:D5>Z"/((M9;$;>6@^G]E63Z)DM?I7 +M_!P7]%HR<@`5P"$D.>',8>_5-^VJV">#!E,CK\M)[!T\D +M^:TIK'K*4QRZX:R8Q/V@T'XN0,Y1$'Z0O&Q15Z53VLR#(KX^D50WX]A`TJ:> +MK1)F4"E)8S;X].`A*O#L/"=7D'4*,%BB29\VSA'`T$>:.]5:%I#0C^+IWAEXB#SQ4P4'DRQ)1. +MW!')UK:HW3!P-D$OTSR&C0NX[9`MP]O5WVZ;6ZC0*D((5HW'NZIO?&0_D608 +M?&U!+XV@,M3H'!2,TG)ALS$O*04XSOH$=$H0]S9MN-9[M:="I%;H +MI]9<\B;,FZ9I'ZT3C1M*R:5@ZX/`]#W-7_S6B,ST%DL%_[O542/'MO0T +M(+I2AK%35/KFS1M;Q_96R""RY8#H +M>6X^K0RN8(,_F=@!UUSBJ*8\KFQV0_3IM6W"N)S5E1OHS[I"?*0(?\E!.(IR +M0U!NMJ4:G_*+'QDYJ24'^%B9P*G!084(+(XSM_R3!?_N*::%RU5F21< +M<-,#^2O!LOF/0;*S\\.N:F8"Z3+]D22]=!DW^.4/HQ@+G.1/PF8;`\0,GW0V +MW@G\W;,YT>/,A2P7B:YDO_P(2:)!$-)H+`/ +MMO-KDOP>"8I63Y[E6EG"?09B-B?VJ?3LR'8,)EB^BZ)F]OVLODSV9TJW%-^Q +M1ND]U`VW5^A(7-3A!P&HFL(#+"I=OD)78!K5(#DE8E5.YAR-?VW3A;U-S"M, +M%0F@RT6J-!_MDZ??VN5<59'&TZ\Q2;Z+3@5F;J-DGL0 +M"J6,X!ZR*/.\]4*?\,D4?XQUDB>P*$XYG;)MP5Q/%FJ8AQKD)O*%,VDF:76Q +M9T&M@J\A6LRK-D7F&ND+)+V9[^RR#:G-U4;+AO%'0^ +M>!:?%4LXS\X,38)#CPU'L)`%C"$?,I95W/:-K$?+G[TU<'0_R1+'+U2\8/,_ +MBV3>_BABI@0O6X.5=;&5]I=`$`V9Q$NH90X7$'6'LMP&W+PNV2*1H(+<%]#M +M#=6O>`-#1J`Y#TG+OK^84Z3@UHCG+J-C3IOOL#$\..0HCE?R1'#!1PB(J-D/ +ML'@_Y.>/:?^@,8:V591QP+PB;<(C:\PYJFT# +M'9S;^):-%\<((DQA0-3%)_1D77L1DQ\$3E\9"8R*4\HFQ+>TX%#W<_*R62*/ +MH$C_)]K&I\Z_@^2KOB9CLM"F&(!]MO"FI^!;<:)N,*"HS_57^$AWT'R-#N0P +MI?"\K=O5D+7,DL"@Z^8Q^O:?O5.16'&K-+"$7(1G$DBZL6J+<"=LL\>A;'/[ +MHABHHL"F(FY=8Z6TVR5%8.Q242CI"R_"N3^N*$9"7XP71]:FC'Y7FS?ZS>X9HDL\./43^3IQ7Z-^W^A#K(,&+@S,P7N +M@(%5BB>B)?>/1`]5T_(H5AF6T%%//.Y"M>&@GM-]]0!A1G)7P@>L=.J;_WW" +M(-&FG%8H#98G]ISO>S64<.=P'G=?B/`7%.[22M\3,?^RBIKM_:<.S2#@=L3, +M4)X706S*G=;ICH:2D&QW:?T):?-AY41"X>5/Q.K,8G^Q8LRN&)S\(A78\6@- +MV.'0:-TD8"DRD*??]PWA+(MUQ!E(>3?B3_Q`%8ARB +M>SV[Z-#K?'$MGX=Q%GXAI<%^[R'3*@\3O\\IR[D01Q-7DA34AE$EZ.<`GW&O^[MV2U(1'\:8+G01 +M+_K5QE,G"5P)6.;.O@U6N[SM[A7=/CYJ2B-AM`L +M=JHZ[2*5\RK4R#6#JNPDQ^]0'N`LLTSP5BN-GN[`KFHA?4J-V&O&O3W">1:8 +M[RRU1KNVE3/(L+'5"#=@.J3,]U3#CMRR'*RKH!X#TQV[Z`%S'XIER`O( +M>(PV,.S]>2A$%^-PGHIY=C[N#IQ_DXA[@"UQ.NMX%C*]NP?JR[0OZ"DS`.^T)06S-B!O).&.Z-BB,B_=XA?XEOQR+Y06\L0*-C`_*7BS^OL`9&FT,Z%14DXK='# +MZG[\=;VCJ?3WTIE*\!:TT4CAM1POR>2W#@:PT+O<$K#@]&T'8T5TO(6?NAEF +MY7MF+3+C[O%AA-6/+!N1Z<<9## +M#H=,SRWP)\/1>Y+".T8N((>M`1E!M-U@F_BZ=M1`!^"51Y0-@#374?=5SB=, +MS'">9*GE@MEUD&`B+B=JL-W.J!ONUD/$PDK6*\,RJ$82M00+)M=R(+RY#(W8 +MA&;004A+[IKMC)@QZ-!::Q%N]0T?F3661.]Z1G&?%@&>0Z7`1.P?!JB>GTC2 +MFT%W@*8*'HO.ROR@'B=I*NQTF@2Q\_Z>@3^>6W_[`BP$HV5%L>+]`5S]5U-N +M*I1]^5=`V"5LY(+\)1(VD@>DCXPEEG=[UJ%XFZCB12Z-?^[XX"@O?S*%A='U +M@$VX$Z(F):?R4W>@&YG_)H&E$DI9[]-M1`@(T^N_4DS(FR:WQ*X3P^;&<%N3 +M:;CZ(,-3\H/H3Z;,.;',&+A,'ZE?K8+784'P.L/&'RG8&O2&->""M625K(3J +M"NS/';DS*JND,8,"41'OP:421S9!_-N>Z&]^RX]TVH,B[49.%/F+H=(TT8.@WJ&.Z464;WA?;:)O]K'?EH.&4`"^P\,K"[AGH; +MR_(0OZM7DV'W130*YO;&Z[5E1@OKHC95D/)@655/[\G9X`:-MJLF$/("[_>6 +M*'QN_SP*1,U8<"`1WXG((>*\:YJ=C-/7B`7(ND7^4Z([1&M5+L?@LN<4501I +MG'-<2L_L+C@N\FY;<]P>#AHQ5"`*>ZW`7T?=O3PO0#/K/S11(?)?B+1X2^'! +METN]=[-P1@!V\,#4DG5JBL2LGU[4$;,HC2:>`BD>Y/YN>*+_JYR6$Q&Y2A>^ +M8\_\K:$>D1WG +M_\,EE*$(H%XI&9&Z3V'*4K+,FB"3;I5/];C$;P_!Q1&X-86Q50?E&H_Y62/? +MM"W7:?Y^J-6E)5@NV[VZ0;!YH:^H+MW7=E6O:I4Q]1L=M8Y9XK(-&HJ8IA/" +MHFWVGEJ8=8G/`ZTQU;M*)1O#2/(D*+=R`MOU+P,@K6N%;V, +M:7_E)"`D6Z4,-M?;H;`LC=GD@F>648#:_57\C]6S,I23J2?,?3AQ:C*RNJ8C +MQG!Q$?ZH'W^^654;E)`53_/X0#PRU-*6-6YZ4E/2PHK,LLY&.-,1R[ +MFYEY_#H^FIGA^7:7\WH&PQ1>/BA[7_5]>6LJZP(J.DTA0Y\@?![&&E7[:=^. +M%#@N;7]35X0Q&K?[FS6.J=_N0H&"-W5*W0NY.NMV_Q>0S/2) +M7ED(L?1Q!09--DA"B-GZ75B#_\Z1%Z(NF8"74*7AM]BE=+WYC9SLB#;3Q=O +M62O7_T[[44[:RZB),ZYL&=E,OA2=N+:CXK8#7X1+XZI0$X8KRL$"_P6UACQ* +M9]HV\YIPZC:Z,';1(GB#U$XC,B%W=VSE1F_9%RZE!N1%!#&(%1`:AS?35'H0 +M$NAK1SG-";/U$0W#OH5ZE;!##V`NTY@3A,& +M>=&U9L9XXUVPFZ1:QO%L`FK;RHS;[I&'[=AU$\U/-K8R/QF?*%2_-X2_$,HN +MD+K4_K]Z1:UJ$;\`HZWQL7_]GRPQDY>&S +MFL_['I2_N&DAW)35R'+?24`4\>K6J1TJKS`Y:,2K@==)XBW-F7>]CRWCTV)8 +M4'2;96(,8BF%HJL8[JHD9>%IT;(0HH%?`FD6X\4"IG!WAO`E++*2R`HC&(MC +MKFLRWU6'SL^N('%[R`0C,4FHIANP823$F;&O$V6^Q%4*O;I:,'$3==)F"9/( +MC-E09AGA=#U=&Y_%,'BA'69+]H%B4(MW-#QC:/:^'"&Q.1T/'/MMO&WMWQ<% +MW$'5GC:5T_VG"-HFQ?HYPSY@4'YS];)&W:!QDS`16J(&;5TLD5F__O#K_?4, +MD1=PV$1YNC`YYEVF"4NZ_22L#5[.<%R0.YRB5VJ>`K,$AW!NJ2]X_/*$DFBN +M::2J2,WME%];8GW=IB6?@31-^3(@:I4$%.HV2E,3O?TL9V,^Q@6C:8/GNC(* +M\P`MQWB2U:::N<%!W/NDBNK*MW+6P33A/WJ;'+7]!%FLB/%OKRHN$3IG7+0M +MT=,:+F\*J]J5)%\33<-S5@14-C*V*0CY@!I`)OZ$@&M%"?&ZTKO,R\]/N;MXE]X"[R'Q]9!ZFS-0GD5CN!L^-DCJ@"0<8%0 +M<-BV8GOP3#F,W&9B;F`%ER8@/CNM[&_^M320JDASYDEG"=_)<+$!ZC[\8"8\H8YMUE\[[D#,E8S<)?E!45/F\U +M#^E6\RAVG3KN.6/[&]I3M3/9K_79JE$]RR2NRAK+%D8ET0^(FKLX]?O$.S\K +M!2YZ32<5"U*VSWW[^^T[C28)2`+]9.Z63E2.Z15F7P:6$GUMHP"X9J`(0Z=; +M?!)IIH9`E)GIP'\P2N&L_VY*OXT2/RD!5B%FCNAU4F(?[4IG.JYC!'2@J;TI +M\D5.J]XD6QA\HK4I^;:))8AGW]=@+>$UXGV*O#N?`JVW:>:CC:+EV\+> +M./U=%=.^H9?&CW-$!^1,.,"_:B62C6TR9L#F%L$T`U4VJ^Z&/RIS:M5^\7YU +M3C4J>0%#OWC?\VBH-%(>>?$H2NA#JL!0F29`+8&K:\F&#SFY,*KTZ*CWSTLP +M;DA:5J*].(OI5VN2B8G:DKSFXM

D8\?S7V,.[]IXB]$=0D0[=;I5Y*&O7 +M+0SN*LXD&S79_AP$ED/X2L!UYTG2FSULH@E@&"6G3G'L])I7Y*.X&"6#XXUE +M-D\G`3DJL$W%=PRMD"$0+6$(CQ+%9I] +M-99.Y-D'%H;Z"-;#TM-BN#"9@*2_"OKC7&SO^/JD]>;!()@O!^FIA6LAT29I +MQ12^)L?L^=^M/=0W/%HPE?2M,R#%"0'QFB8Z4D%WU4-S(IL<^G2K/ +M-8OL*Y=6)VQ231]]>3OV4:%:YE/S+RPN-SMM9>,YC*Z!4ZAE#@0:09WY7FG\ +MIOK2H_YRP4`C>UPY&TD<)ZQ,L'7U)J)_R"7\$7`8;Z>\/W?;PO(U9M6;"3RC +M36_ON>95,DY0$;\Y>@QTG%IX:3W,U>D$GC&QC^2MI*U4+&Q\PLJ +M"#:0H)`1CQ@TDH+6DB8*P_]N9X"((AGMT>RGQ;-RG/-YQUDP,&$6G+`/ETA4[#C' +M_:C,,&G*D3]5D1:G-/K?K%'J.K)L)6)4KB,:/*@8K%4N+3`!]\&S:3B5B$#\ +M]-Z_AA%'E7R1X%CRYHR`^J*XTDK7 +M%)9!L\`TL;$>_F"MBD+-^PD:X"9JK=DL+]^QBBUX`8C6R_]E +MM/\2*,!EKJ`E^1E,&)9\CT'5TY@(_1*]BKW`^+Z9+!++"XX;OTQ^5M57>"!6 +MU5"T:7J,T)<5]1A._9]R18`W1?"W@1.(,`2R(11VW=3MEPMX^)&)S_`P-@IZ5V%P1F +ME)FR]T*M@%26Y/B;Y:@]N)S5'!/\Z^,GIW(B/(%0XP5"=86RK+'EG6B&_V[\ +M&FY8OZ;8HRJCQ4@93J$+'[-&0`I&?VG3M9&+9\P[>G&T*`(:)(M\/MUEQJ47 +M/SV4-[=ML7I#[0/1)_JT;B5'!I54E`UP8`E9+*HWEAE:W@E+LAE+-OV)8*+Q +MD->.MU:S2L!0*0D1#SZ>#@M3AF#+YQUWR4^3=MSA[HEP5X3KO.1&%&CO/^I@ +M9X0LRWJ;P]T34T,82&ICSN-"G?9$X27A89/*-?F#J_OALYD.!NO55K<>GR\AQ"1_9A>-KFUT$$9/D.^V"/G_5 +M'WH/AIX-\Q9RKOU?@6Q*FS?//`KIXJG-]C6$7MDB`TE]4H9:4%[`.O6-)&RK +M97_+YUWRD90^#JL'J')4&5P"\1%0;S?`=X`)&O[W$,D#>9D.9SP&?-`C-:G8 +M[LG?P(;52);:3AA^]NIEW0E3<`\OBG,)E70A^H/R#K>PU%W(!CTSV4<&#=LO +M_(56E>0+QR=P,F4C'XU&SGV76PYBMV#W2S]A+O`%*M,17&91NX!Q+9:4O:3# +M]>^BI+X0&B#!E8(AZ%T6LW*/[>CB0W4C6T>ZL8=&82@; +M,8V#\))%0V5EE>_T>I`8O0->M25!H,K&M&)3C@T+>HMDKDS:U9[8QSHN_&!" +M/36(*RN@=MV]62=U5QHF+D`19..^Q<0$?B()CA2DWD>Y-D=$]NZTPA6Z%KMV +M*0TBSBI88;,EE9(G)9RT9S`\3,EZR,TB)K-Q3-@9GP*`>9\Q_@=?G,/F'I:( +MQP08]%^J]"X*B&LK"J%XO5:U#2;L6A5[QG'X[[H,_Y1]0U7DA$KR9+:)&`/! +M"@0B7*0`5YTZGP8J*?=370R3CE7-@&B3I78"H,E4$O['0B$S&'`7*2_-T[(L +MMEC5'+_:NNV(""=,@/LUQK+)[%0#&9<9+]=N@""W"5T1?7*=>'*-*FUSI*PU +M1P.IY1E"_5Q@V@/!`XS-4%)\0C#7PFN\7LF(D_1=F2,7:BW9`\7#,(NK(@D5 +MF#\?[3R&A:C]B_KL8KSM$P"F(@)^7"V2+%96QRB(UHD66C!LQ2"/EUR+2PY$ +MIZ8AX]A>:XN9/@CSJ^(3"L.Z)TG^K9R3W,TW<@ +M>-%OM;`;;<")TL(LQ70>@"Q&8T%H$UXA;A.*V!G0(GE7!6M#^\6AJ+D++\%D +MPTM\6H_FEJ?1'O�G1Y+BI68*,]$$*M#CF=E2+*,*'RY/>( +MHQ200^7J66"-;+C]23^WLG\ZD>B/X/9\;Q8YVWF+I-4.MAG;X,I0+8GLLJN4 +M(KF2WI[\K!$";JE&N\Y[LG^[^&U!:CAYX9#XWE[ +MB.R`N#YX,4_KA*-N/!I.5DC_\9&$BWOAY5 +MOQ'&Q1B^?C9WC_9:-^\G$I_H)'9)5RLYFB`P_[Z0#Z(KB&<:72$8X8!6D6<_(([-"8Q]Y5E6?_U5$RJ"&X8&W_^ +MN8LQE*WVQ^*)AV%!"G0EJ*5_!^7,JG>'@F<&IG6,J$:O`'G27K3JU- +M4!*BU\#F1NCZ'A1$I*I)?X8)!?X&B\`M[`>G]8F@8%BN:"@&^FS +MG"V@]8+6I^RW<%Y9/,$RPMN8L[Y,[QS\[Z)'K1!Q,T,;[T#S\!$RFM"A#J7, +MZN4;X-#M`VI&D[B*G#1U^(?V[A/]P%(%A8@6?L;7,[LVH)1[/+[FB +M8PRPH*E,,E;Z!G^)+G29WKC@Z&R/>IQ$!3=I=@.6_32>9^,61]&- +M:N*G4%%L=C(<3SZ+G_)UT1^'M+M/1NJBM,%U-YGDF5H+6M+_,(]-!5T?K4+ +MO/(8!ZVV\/<+\)ZEDX@T[.L43C5^":7YQR;X8J9KT_`,:.@?Q=0D!E-N6Z`, +M,%@_K*F]Y#,>0[>-TG5`;MYP_6?8"P;*XPU-73ZD[_FCQ?.2("LI:`9:EAF7O]`L$`>J_1A#!M/O.K\2MI"Q5"#4$ +MA7D+:3960A`P`0U17:4\U;PF6-Q:J%]-`CI_:76CUPX^NN[+5$5$[W>RD060\$CY^WK^8,)'[Y2:.OMS' +M,4K]8[)Z;K8S\L+:JC#R9S.6%-DMAJR`'#(U)C[1H]?LAR!PZC1@$@,\7^ZS +M*P)[$O0>,'N=D[ML^/GM4:QY\7U\\.1$.9W;M6V?MZF0FSSPG-)OKFVGL34)?U\: +M`$1<^'[$5U3M3ZAT2.\[D]B+3(R;0Y??"(;WSH[?Y/Y`F-:ND!CGZ:GE!ZT@8!N+-PW&ZVM +M(#[=U1-&KQ@I([/]YMMO-O9!V>#70"%EA*E[QU@!T*"OC`W5?!\%VL&DH_AJ +M,@>*P7%@'Z6N0?COQ&?W0YPT0WL=%E(#'\"DA@M.DA@<=E^(:SK`.VJ'NNK1 +MC>(8R'?U^)[E]B4)D`%\6[:4^S:,(]PK8XFEQQ'@Q8G*56^/$4$:'L>[87I* +M`91M487404U&'`**FO((^ZR&G>Q,*QB9ZTF92<U[DYL@2?<-- +M:]7_X>[<6NXMZ-VKI(06U&6FUPKU-3;70_(GS&.S^=V(VB712IO$DX25\B!; +M[?MIYG4;/`D@\1?"RARW^?*#_^T%*%+DN:FA8C0M.#ZRF901(61EZ"2-W!QR#3\.W +ME!@`$X1A"@2E`\$'/?4.'[&[9=G6'K,9%T,R9BL%&D)(%*L23'JX0$E/TDWU +MW**\7%'JBFY/1,`GY)I1I$3@JZ]#"KGU^9I`\3Z0"@;L1MC!V.2R5R.DM8ND +M<>=J^R'V[=Q5/V>1$$`38(`N3O.77,XTS9EKLZJ:/3G*%QOUEPD&FH'H<2DI +M1.A*RQA'J&H[\:Z1.5N4I'P6$YE%N_MQ,>F2RL_XB;\L>X25ALW?"'J)US9N +MMX,7K&,8PX),I@T[RDJ`D35 +M;4`D",=_Z<]7W$_CM1Y!XL%(<$0NY%<_H`>!7>M_0;AYCQ#=3O,'`(RI^(9& +MBT!\NR/`<;"C1[/ZJC,':%/&ETV(]C9B2/%_(Y$J/:%YSEY1U-SZ-^X8A_DM +M;WGNS78](Z3:C@R+WA@(4[HVU\XG9*,XLM5-39(QO.OPJN"+_PXTTW/__:$#\CDV\NXLP`436H +M:'[ZI,CBKUHSRL]UH6A^`!AU#WOB"DY'V5K>6&%AHJ*3'XQ?FRA9-PM4:4K5 +MAPX;#'"Y>VE+1#O+6*"TFCO,J)\]G$1&42:!E*A4!8*%>GY>G]88[]ZY#2!X +MFL_]7G7C;,.UZ(6L)#B!\(B%?VE)NV;N=B-3WYR7UV*74<\NU[J>'Z#4-G"P +M:`-BANB@/69\0-3^F[OQ&=-IT_\0@&UUYB^@)-9V^L0"C0?/11M!G2_"X4Z8 +MHN8^(F^V+12;0MR_R#ONR/5+348TO)/?0:$X#;L+4&N-UC;+;E-8AO:'5ZO% +MP4,B*,'*DI&M>9ZR=?*RC[0JIN!#_9U$+:&8VN,?Q5"Z\>N8#^V%"`A*_U*S +M:W1SUBL\Y+W13YU;):+[D<)[30YMV+9#ZDAT9CZ$P`VV:IUN"5P)4[P_GS+E +M#'WG#RE_-G(FZFMIG&.B0HLE$NVT9HD4'-JFDH9AZ7T;!A]Z!EJJ2X$F[P*T +MQD/K1!A:!G`!2D$'+J!2K8&W"K\C^$S7Y,ID>Z;Q8HMEX;E50"IMJ=H89&.! +M-R/5O9R$.*YU)X)E7)^(Z(G9-+I#%P/$ZS)9\\EQ.O77)&C.1#:Q11+):HY[ +M:,LA5P'A\NJMVE6+X?.R\!Z>>-5E\]J\3+8]&EVQ?IR1H4>=CX$\C/1IN-`+ +M>SVQZ"ZL#)M_VPY4+D*QY\^\T_->S4LY<+U^R49)B?./%$N]V"GYJFD90#V% +MB05\<'AK0YE'`(M=W*8_=;B,N*KSTIV*%D'FQ7%0`AD1>U305+6?))C7"`2X +M-QB$,"J6ZB=G[)&^V03BJ:0'N.ZGK:1@E3B)"V,,`(O85_4([J:E232M +M@J0N,U]S,\:7FF![T(!R5L^MA\APGMY?`3#UP$=HQ5J,XG,XV`<Q!36*7D +M9Y\<0H[50JS^M0Z_4=&WX^`F5P74J/\O-*HRKLMD9Z4^1BR(V.CV>U\M8]*9 +MDF!PS;[ZFKTT$5*!]7%/)3F9$6GR:%KX6LS[*7(;76TW3YY!33\DV!"47(AA +M@[4$>+8YS36^.<=1(R:@,[!C)$]RJ(\*C+0%F +M"H.5UEX*PC:P<78-B`R.A]Y1;'45FZA+6W@Y'3]T=I>JAOZHPE\5>YE.8)A0 +M]TKH>_SJEM*%_QK*)72\D&AR'=KP+MQV?!M/>\%.WJ1#,\@.8./DR_()&/?! +M'S*ICH=!_M<$NB!\W4"1;1WW?7U:*BD+Y[>6_L2FH_>+ST1MCZ=;6<+A>R*G)*FA^9+IRF:XW +M+2=W7)2T>P$;H:.8:^[GZG<1\K$IM*M`)7A`JY,2WT+*+]$X_= +MHG&=QN5GE9"V%DEY4=3LTT^HL;OW%Q73.Z.:-`=ZH&J?+LJJ="V)IP3!Q*!R +M0A],O@NJ719F5#/7+`S9WK;>E=)P]9?$Y!W7I^-MO*@\C5]#DG-<$33.1\M& +M)4M4]P'BIH;:[3%71LU!.5`8JCK5'":$V#HW5JG9KTB^?.=5"@AC!'DS+2_& +M`9,Y2?V2)59M)M=A`S)47S,)#9]>3'&KE,^D2^H0Z4@>)]_Y6\6-E\2R!,$Q +M4WM"RRP*&0X!@JC-@,(7\IT2/Z=FUGQG@2ENLMBNPK/PCXR[S\'*0=7E$81N^!5KS +MW`_6:]FK17V(8<=@.[YJF?U6JV<5F^A4@+L$`&O:M`"&+LF>-BQ(3L8;A8#I +M]4N.Q.8V0:J[>;]).`N?)F"6'S_4&:9\'[;:SB7,E;-'3=C`Q/D<@YJ&MEV +M,GK1^H:][XE*K.;!U0=.#OFX\F.)W/8-2_Y,3Q%K@(\U8/>PKI#?4L7*5M,TF;T[*R;Y,R"4,G(I\I!_RY$H?N6K`Y3FFN,G!>T%H +MS-:T*^8ZH"!_J"Q&XG%1._9G?C%!R2R"?^.&U[SCC5W;!_E=92)ISED4X2C` +M,,_H`I^2[WU#?M:%I1*JB:P$U`+$`),:2-G%1JWNT.P[]#0S<@N=CK#[=(F^ +MH,-['!U]'&,MFRMZPJ*-E[1^4<:+EA&'EU-`071LX@[2B<0V[$]/ +M"@T*'+Q>%5E(:V50CGF]=4272<)%W]T![#=1@G>=Z5CD-7E1&>:%_-+6G6O= +M@$D'H#?\8,5'#Y+%)B@4-V9.V/P?9.%+F!C;*.R[6J)-%A +M);V7:9+0"6^4O[CHGUR:.R:4IG#6"Z[]IO6P/]H"B"\IIJH?,9;NSO!_OBE- +MYT^U@F'Q!*ZZ,':L$V\"]CIQ%N`R!QW[X*'!&O'J?T5H$#\09EHV>.6!2G%:K,HC;G[%ARL8@'932:*8/]C(!6L +M1X-/EL?AIRAR!DA2WF4A*)_#DT/UFX`<6PX*M;-U-)T+)F,,I.:AMF\7[;^6 +M,=;,E73J)A+K)-EI1B,."O]24$:]K1Z11VD/UC"MD^6DT05$M;$F`%F"XDC_ +M\V:,&91>V>+? +MYRNS=;BCOF*!DD6[8_$E&S/+'%@J2Y]KME=?%>`U8GF;^A+/2W0VR?)6SED+ +M$IP3@DUQ[E)W5@)>F\FO/3H^6,)89%OJ(UL7G-4$^V/=)M!3%*[;+X!7B.9V +MA_%T/@DZ'#LO(QU4F_G5/?/NDD\9R.!QLL3Q#9S)!QR=89=YWEX':@(QK.?Q +MH( +M\IKQ5S%X(M8=A_[!\H#(`];@BN4PV@?%PNA_?I_*]P._294<@X*^;[ZF_Z(A +MU2>L%:S->BDL=3,SJ%B-->A[)\6D+G)]8/)[^PI#P/&HU%\N]1+K<22'F@0- +M7IN@*RC@]CW9I)YT:7(JW7QDR294AM#DA%'.6AR5PN6/G@[X+]"JG!+@8?22 +M@,7CV_PXG8@V:,`\CRH#H]<(BD +M6V0N+)9]"RQT;?%8-V0]D1!S*(_NQX?/1351' +M]:^3;-.H>&UTL'YOE9\$5KZBRQ9UMH@AAX.6#QH`V0R0:W&5'\/FKD9_`;&M +M"[1068%FO4O(`2:I`/\*6*!"Z>+-)+N^^ +M[3,$R^Y!$+%37,+*?@*U!\$:1Z"@BHL[$`-'%/!Y$7@^J1Q`1;8_C7+)4#OT +M&LY!KVE%_)D=K4O\@:6%71/1Y_Z^EH_P$N_[H2DM,D[KR_\=*B>OQ`# +MR\$PRJX?:N@'E3_JC[/5/L#T8T8$>YIGW:+I_V9V(!I!T2!0,U(C@?VD2!K\ +M6)4NBIIWMF;(1S6<3LM%67US@[:G5!9L2SJ;;QI]5F +MPOGAV,Z;NCI%EQW210\,9,G_#D(X3URSC2Z4$F.HTZ2PNM8UM/-3_PX#^6]A +M6E68..&3$WI7-R&CDS*??.D\F$3PDTFK?Y![C&46R^_"%"1NS=$VB/+?C5:] +MN;@N=/8:"V#0WY52QUCA?*FD(8]]H)E6HVF`A/V9JC1-41TNLG4W1U?]-;QD +MUR"[*8R_M(0M*L?#XU+<3_0TX!\&.5C-C:Z0=L@#NFCFGRC>'T3?7>EFTJV3 +M]G1RJID.-!G!GA*L3XGP[MT>#B;)JH( +MUL2QQ((A9-_I\V:__AG`0^E(6*\`0]LVAH=)#Y)1?.'YLC6![^+)'SG$L:WN +M.1:"Q:!80"G'?&C.QVI/?98Y_L4F=W&O7DN]7H6:P)I\I<>O?;<=()SM5F/- +M[/(3@LD_D?47*AJ>L&F3U,"L>;V(.Q&L<*2ZT&0I?>F);\NU-3V+NS$OT$IQ +MH^M)LV\MNY?+PR'_V9"ELA5$LG:?9;A=[<_CG,1UCWJO[2P4\%V;V +M@6[D9_P:"(!N]8D+/ER\Y8SJDY/6HNS$"=?7('3DKQF\&E1ET5JM-<@@^Z,6##X_J2(1R.U3/?#AO9>5CAA.#[4 +M\L>'-LY=WNP]YXEX_%]63%,%3I:2:!$X#P2;I=13_^Y +M`W`)JK"I/_P]-!%_);`VVMG#@TR`HZMPG(ER26T"DCFRS,0902@F?6%&T`+? +M2ZK@]<&5*Y+GY"]4WB&^B7\R_K53.JV6ZCJCXL.[BP!P=.1L=N +M8&D=IEKJCTC)%4(*-<6T"@S+N?Z$[H9>^FZNG;3JP7U%-8TOD!9 +M,]R".H/DDI1YU-#9@+HJ`3(R&>2^&Q)9SM +MO5)+H8?)BJ0S`QZZI9+%4=XPA^'$(6BUWV1LFN#T!F;6LN0K^_]Y"3("1AF3 +M0PG'#LUAC"BH&'_9:8.][JO"S!PI)0QLX:V.#T688[E!S]%-2T&^J2KY(!#. +MV@?O\L>[6?#-B%CRDPYA0U=Z,%G>MDLRWEY^QI(U-'P(-(<6K,@1K'_ +MH4UV;]JC/Y[VT;[JP1VA"(O`(`"#`^E;]S)%AC3$1)2P%7N$4W\?:5Q(#,'Z +MYN>9B(6!D[-,O`/X:B+7#1P!J[#F(^5XJ'P:6Q:XZ+19ZY-;7-66?K78C]&> +M:#O7KZ#%]@QH-_W5IC+;2:`::O+HN[>I75&#IN`14$STTFH$B)X"UD`CF+[\ +M48ASM`H"#1M2,V6!!GL474=L-P/K<*O&('U0QK@<\QUS[\)=M0]-3-*#KCBY +M&YIVF3I5((L6%A4(8NHFBR(YK:+4>3UBE82G-.6>[%9I_^"(17JHOT+JW.I# +M$\"LN.UXK=FD[3=-:@W%7SL%1`XJ<_I/GZ6DBUE!,H*1:\7Y2S9(FF9 +M_,1!D#Y@T,LRR?65OS[W]%"!ZO^JJRKPJFJZR:M6)!`@+8ACOZ6KVRAQBBV* +M_?ZG#4-L0[6E&3K#]-%35QD1-84IQN16Y-!F!M1Y&[4`_%8RZ=-TV\$$H=]H +MM)=;%(*WSCLP.M)#RYB>*+&H%5\*56^3UJ[5&DU09QQR/5,Z&D4LND(P(@T:Z0B\&)SQ@\X41AB8F +M)S,&(+_`8+7-"*I,_V6Y&;6=+9G>$))>6HX8G^_3/RM]%*P,[_Z?BY84LF*9 +M*4^-0V,KZCC6XM>LD$$]A6& +MNE6RG2?7]R3:O>EZ^+<=IS,9C];-(\_[6[I3[`0F1.)+0J$/..74%+8 +MDC\VB3*_5_'\O29$,]V^U"01.0[_;*.!)ZZ5A#KFJ11>R!$`A0^W9/>'OC="_OBXVYEG%L#1(;*@Z9L5?YU7K-C69!`W#A]M%>(LZ +M^X"[_@PTVR$XO]LFY-\V2@[5E_%V:Z74/QF`1)#$F(\67?I%/XS6/48)'6\>V8W5]9UI>J2%EDN +M(IG+>*$1'YE+V?#:>Y+K,*&1A]:\K.[N2\]:;'/;R2KL+[O(HNPQA^&N$VN% +M`=0C)8><>A=`D9&'I+^8CEFU.&2T+X:%^$\T_6D"W\S%&<*)`TI`@9S?J +M13H/RB73?FE8L33$.))/@6QW;ZXV"O:?_[*,,J[%[OZ +M^\'CC3GO].=-ZPR8]@1/+BC5X^Y?!E?70%+WH;N$S^F;ZUQF:XJ@H87+I2@$ +MN1;172D$X-?%8@Y=ZB@<30*+'YDX]<^%G9_]TC#;9A_:H^,/P&_20##Z?B%Z +MSF@DN+70L*]F]P#"REXX\[FWH#:U7.%&PYMQ.!\ES1I\^6UJSF5>#R@-3GH? +M]H=36M@N%Z7\E"232VN\19:^M,:3WP8R,^2)@HZN5\N1#`Y3F';(?0WK><'- +MRW^)WX[>--%D."^K.<:4:Y0WTH56,:GRX^LB3@'5H3-U^MCDKIJP+D\8B)'6 +M2AHO3L^]7\?(M&YK1_+J(BE=&"(;L**H'EE`2'LX)K$;\ +M5G.GZ'7#>/&Z&S3*J9M_GHOM26+(!DU5A)0T)ALSJ.-F9>\A_IC#8.14,(1ED'W0@J!QU:(S/6BBQA$_Q)3YF5 +M5@QZR%).)HN^ +MT.RM'Z>2*2TORS(P;`O@>L8'QR`A=YV6$0\*4^C0=5WB#9MS`!M$3SOQ51[+ +MU$8RV;CTC#=C!/&765X5@0<8^0==RZQ\27"HS\VJJE0DFDK(WI%&"SHCTK1" +M[J8/9%ODBB,:N5PTN<\-IQE.U>:6)K8_[/F"+B4Y'?$G#J-:T%KR3,<40R46 +MA=1'T]+_XCI0U8)5L48M.SVN;L*K.G&!XCQ>;8_BR=T8?!'<3^F0J1"8T\4: +MPW[]W[YJ&P[5AG84'.'V5!?&DFR>P0Y*'?Q\'<#0UDT0T*SB,)Z['2)'8;GP +M;+N$M:$)L_7CIY((N21*F]->:(N=D3`N[U\/51O^,U:[VBG&II^RAE9RWC`C +M$Y`R1E&!@B_S\>?8K5H=_36J3#2?P_[.%7^GDQK8$V^&P37:1F4(=3(4[=K: +M*4"NDVF?_#:V9C%8W.,1%!7VB +M\!VLP=F48-EW36EV(=R4VZ_=&"9G+C2('+6W=BQU\_]XM.6R'MK='K0JB>C2)T?';2"KM8U9PP2Q,W;)5`9+^&XZ(5P3_ +M0T+Y$L"XHYQ:?ZCA-.D;`6W:03O[:FUOJZ(H?V;31P5B>&O&S3%9D11/@K6'A8GI2Y* +M5=0`?.>WNEZ;QVF"9F2/@MG\`H-@&2P=M&9U#MZS"[&>NOY0_"J!:!QSF<,Y +MC`4-H:?UQDE.2.R/@/=954FL;E@M26'>A*4)[H^-4@3GH*"H:4/+_\A`XOD/@W"<)= +MZYSL$^?'US!6]5OW`/NFV,63-P4]!\!TCUQ(4L[O.+D1J!M?D5#]-J=BHV#F +M,_8DM%&D_((91N%=/"$64B>2C-Z5X&!"9_2,(LUQUT/,\KU'\\*LN39!@JBT +MT=Y'+9BQN\79J9IE-EC$X_MS^K^^:E>9I-1I^+S.PG(53"$,3$@E&@*SAC:X +M0ZW57ZDGEFP?U&!(0&-D,#?M=Z+"_,XCY2>S:**3L>8<4[NSYB_>,/4&?N\R +M.^;KQC-;!HOWH;Q=J+K5&0T=O*"@+CZPC(WB'A'T +ML"Y4=CRJ4R$1W0NOSDC*89X:Y4=\0G(`NI6=,V3_'3I0PG-B!#*$\G?MR8X< +M74,'E!A`;G(8R]"*2,@;&3SY.I@=`8-I9@W1O&)5>@UA\TYUD.$QB8XOB.;& +MU8ZAVK.YZ/B'$Z./L`2'SI^B'Y`.PS9*Y079&D<5^<=Z='VQ9O956Y?`V26N +M%"+#^E?WPOQZ)TOD*Y\*OU-B$&Q(#)2<2!:?Q-F_E:H:_0_2PDM!XJ"1/1UZ +M0B2R\+@T5`]WP_WPNUD!8:PK**X_UCNW=Q!Q8A]1(MV_$/D\*TD\7[KQYY!-[WA?"<)A4[/@[4L +M9V-/P4C-5)V"TPTO/A7609"S'J/>JX^=.=YR)G=]9!T-3+RE&CM5P@V[MR@. +M9WX8-$8._CO1/,"I$?^^G'XM&J9'K6[BI%$M<;I>`/=(:L",%OL?/D[P=90: +M.*!:K4;\82,F[>)\B;5[,4W\8I[*",(JPO_7\@(8\*0/*N:SMB'N +M#0H2*`0!#3ZE9[<(`T$&Y`Q(/89F<@-3&6>EWJ(,+KB,ND#+T.LH`3_"8<[A +M.>I!6#NHC_%/-,4V=Z,*;%:;-I]<5_(U[S2;0YL"U50<=;]`$5/)!'I%`V\0$(L$@=YN*F,7=BV,`[5#;+$I8Z=XM%J>*V#,H5E:BM/F2KW +MW[:DUJO[A>GXU0/>8!8,+/$;]D*:K.0YAFB]ER69,(X1U86H&D=MOQ:ONP/[49_A4?SLLM +M5A?4&G3(>&CV)_?W2>%DLUND)\ISM;L4,^.7L)).\5&,;KN\A1R'#LL&$00K +MK&2V'OMMEZ^CT'L(5CY.<8ZE>NCH"!B<04^CNL\(^C:\A[=_"G:H_I@\A:M> +M)F5G35(/MJN)+#7S'K!-JS&BSSQNY7?CM+T-*\/Y5B\#&7F0M=>+CAYF\?Y# +M.JH0NYV.;)@JBXNPR`LPD;(0ID(B$2VA$^*_;9>&Q.:!4Q/$$O?N(C]C^"?1 +M6]/2D^SNB8WSH.&4P%_)K^AJ3Y09@\&`D`_A+*QBZ^B^YJ%H7D-H(, +MUY3`FC"*]P\7%PQB=Q#)\(.14NF1.<+JFA6?./=CVPZ``J/27/2J9$:3$HSS +M%%,E3_\\4_Q@&`BTOPEPL"*XP=N=FL1$9Y +MUANK2'WEA&TKCCQ8VH'\@0)Z.>Z0>:;STL3,>'(!TJ?KYB#4K)XZ!#_U(?+O +MYOZG7,\BOH7`A51;2DU)E4PDRNUQO%1M%A6?K6K"DF`H*A[H`?Y>\C&&OLP& +M,;G`2O5!S6OR[]:9HV4G/]LA,\V_UM&]3WWP9W<,HA:$"P[,6DK0X_M1B%1" +M#S12BA<>"X`F+K@7LFU!OMQYPE>,'&VAWT`39J/S`WS24Z#JS?^A'?*&2ZRJ +M9'[KV=21RL$#$LMQ;$*F5O`++[R50D"!E-!<3TJQ/L"Q/&Q02P,$/P`!`&,` +MC+`.10````!&(@``K7(```0`"P!.15=3`9D'``(`044#8@`D?WCN$]"5W!7F +MI*0FWP^MMYDFC:IYZ0YCIL.S:#[^M[G?MOMSL5$1-R9'8@%2>I=M55D&M.#-CE>!+1#?MO6+]/TR116WCCG\FZ/:#CXTE74P<:"U?DBF?^:QG +MWPQXTIOK^J(HW,14+'S_[:VG5\LS6H(@3L`4L4]5N+4)+L,M[0K=E`=I`4DM +MSZ["X1!;.N_\B/)(!O9**)8D=YEM'8D'4F3$H'SC-8\'L%/H&1ZH:$NDOGMH +MFXF"UM@D$(*QT]5W*]M")"K78N9Z`-U5YV+&*XKM/5Z.VZ$.8^9`L0?/T5&1 +M%P6UDX'?R_=EK?M;[G_N`VX\5O(L[8JBBP/NW[6+3P=\.^!Y%X_Y7V%VD8]F +M[,VH=6AWSY!L;G/5';!YLWD:\BV@HRI_P+[Q^O/A$MB&BIK:UFQI?C4'$%XX +MQ1WQ&VRJ#__NB_[,49V+T')Y8:!0"00G*2.IO@[P1'A6;H;UC0.@8M,1,O=GP\N$U2MW(_SO!&"7ZZ%M)M!/'13+<)&F2%LH,EI@[6@3FY\G+!&/KAR&NM@6[-5UNC@PJG"S1Q9&V)@3$@,OG +MA:ZDKT'XQ,.5?2C__D'8(.2AUN7'EU:Z(4RUM^*NQ7)XY=7L<8PA`J: +M3`^D<22O`QY+^JDW`FJ1$0`,:AO8FKF"7J7OE$$SX0G<9?Y"0Q-BDP)=%'LO3]RL(K+7O/=CK?-#,[(']/!G#G;`Z,?Y*S54`28)]QFB[O5>@D0[#%9@E=AK_- +MN?I]APV!2"(JO9R;27OK!%_<4_5:+"H7<:27!JU]ONZ0L?>C&Y]C9\4.G%^7 +MKF?7&)?X#3#-355YAN3C&P*634A?J;C:K`'?N3:WVEX(,-Z7N:8,UT-JA;SW +M+U!%GK0;Q]:B2<,K9\6R@8VLH^M$6KI\MVSU_"K/:--9U[6G*#G8VVB< +MVEQ1'HFJ`K!9V^_^0.U@'#9\+)&C^Y[2&0?=8Y'\#<'`SNTG_L7W$@$>DUSWH56YK/E#A$0=.LM@.9,D.>:F%B=LD3<*ZC,\;LEF775ND1D-C'WO5 +M:2&4Y+RPAQA*$+OTT^C'T/TZE%%0%I\NT!^PI==_]#];\^V72Q5@N,C,118! +MB:]\TE3SU!=R=^7/<,8,PN^#.02S3G*I$>_33C@]4<`W4?R3'>:A90PBEI+- +MI_'00_$-A-7B5'T5S=N\"Q"G^OB/"R="\LD8.M!H=)MASF6NY[Q@.I@;(KP0 +M@`WR93#PGJF"?/T1GE*FOF8%B<,EW?P_<$TF;KA6"Z:>)ATT)O=.C#\5Z:T4^EQ-O)88R[ +MEQ199:<)%X!"48K@WRWV`I?2C8#E!3*_#$565G$6KN.P^L7QX^;F"K]R7OWJ +M#@N=,-$^%O3!%3+&+IJN',0S0+906GM(Z??(PA)0ZL1\MMDJ +MXDR#J;[:WG1^8R2!;Z@93,03!M$6[7@V$K0`JZ!7E3]J7P`P*J+2U8#G0&6 +M*PJ3M%RL))+G=*&)?SXD(D$\OTL\E/1O].T/"W^O(#X;(+:MDQ`Q_`]5HL2D +MT(J)MA;EW/(PY5_*&>N0MG+?]82B-`"MWG??4`9WF^&K?J)ONVRW'?P(ZKSZW"0,Z\]7 +M/R;2=*?M`@+YJMRGI-(*QF@SZ,:WA[\M<(*Q?.EBZ%$+%$[X2R#"=#SD90H` +M*8K/@.5,"^9!`2Z]'SF&W!-^F)7T8OI`1O3E+_U(RY#A\=9D,!![R\,$",#ZIH+.$@N&329O=E9:^*<4-BB5-LT>I//R!?B$W'_0=PCJ[H_ +MDTM1BMKR\:?3>/R=-@"YL=8^BUB=*\JWND%9Y,@HDH$8RQ5SK@YP^. +MEKFO2+7Z>P'$([=8UKP*TZV\M+H`[L#96+8FCKDO:$-E"5J]$.:E(B +MD!1$0,8(!`A%5`22TK]E;[G'D($N&\VY? +MUDZSP*(T"OB%RK_3.EQ*R8LPJQA>K/@J=1PI5EK/4Y0&R!PK%J`[>8SN,]%M +M^K/^IY^7Z]<+>^R_-^A'?<=;WIQ3 +M>>IJM"0-%(1=!=-@?)_PZ*.^,\UX5""HO0!:JI1Y8Z(L!E3UV&C!9+*87'?8 +MP/0(B:E(C"8Z?P.10C#R#I,VFR!D6#UE8Y;A:<-OS[`3]L,?DE+SM_&";T'F +MPE&*5LA^:6V[[6-P#VJ0B-]FLKC]I3Q4!1CWQ^//+&L%=A,FGD/BROEU\7O\ +MQ*,O4::'1]M4A?=1@LEMELR/S-.O7X)'K5%T`Z!#$T@3*J3\QNHN;MM'&ZJ(B.@=*RKVA\]GA4+$'ZE4NX5+';+(]*!`'0W> +M'+(%Z6$IXP`4X2*D=K6SD#`".HKN"+B8X$WK9GO340VU.\AJ/JX'KX6_STID +M::"Q(/)(1LB=)ZH!P1$[?3+H*((\!!73,+`%L7B6:,,(9Z/F#TM;IK7/*1-Q +MYV@G,R5LWSYB+0?00X_7R`1)U$N.;'"4^E)GDRNC?*9JOS,SIV_T$/F3Y]#+ +MF3E)H2I#,15-G)NB0306Y5GSI$^+Y18*(%Y'GE<(R/QI";NJ$3K%"UFJV6(S +MS%J.RSQS]7IV84%&P3ZFO3KEU__,K)\GX)=6('K5DCY::-25$PZ!)LI5^JGVSHBL#D +M&145[$92<%3UGC6(VO^)HGB':ZU,14PG6=BFGN"B&)&H\&6)X*8\I7FX\RTV +M2Q&W1Q6\G^6\7$DS%LEZS"#P4+Q%E]S+9`,&GN\4T1C.*,J5YE5?I0L5P\8( +ME801(;"[5&%!.F\M](H?`*=S?E.<1%/*D-)&\E?4E]S7('2^.$C126UT<4@* +M@0?SM6Q=O@Y5S3(O+AK"LS]@'Q`4^"6!D((X"8%.E!%.YDI29%!Q5DDDM?=8 +MY>$/*3W[U^=X+"S=UF>+W0-%7\699L-`;G'Y.T]2&S($&XV];5J5@0H!U!WD +M6LNXZK]7B\LZ.&F*T?BBPEUO.0@^R?]K-P=]YRWZ2HDLW'8"'2[ZOSN\^I%( +M1F%0-Z48T8KS>U#QFEIKE>:.:4U[,*NPR0^.D'H<'OLB5<-P"2L\9DCVB31C +M84U9'BYBWSB3&RM/D2UG?#33J4KE:G,DZI)19%7\H+5,R+3PJ"O]X>8+M%TR$O=SI'KGV[>C*'B"S!CX_ZW,QY%V +M$(FOG?S+(_L=K0$OQ_K>/``6P+GHG?;K+\C'*X&O'OKZ'$WL4^=9_8P@]9X0#VU_&?%*`[==>]JVS/>=*VV[DA +MKV4T=&R2T7)S^46])RZ!BX\RM>"@X&>>$#I..4 +MZF!5?S#PJ#\T1'BD]@K>OH^RQZ4J@FY#(KEP$G%W3%IZ@083`T>+!J9$_2IG +M=#W]6Q_),>Q_JYHHT9#7)=81\^'W8:+"N`7!`#JB["@^W8:GKE)'-%*!9C&\Z^XBX=_49>,X[IH4J6 +M5:,P?BTW=A,/'-?0(8-BB)D1"L6J^2O7HN7<10(7N!8NH>]]H2@")-99+^/X +M-22A#X\MD"?A1/GPM2IJD:1%'5CA_YHH![U.@^RMBN/>Z&CMS;&PO%9>T$EY +M)L#0=,4%21&VKVR73EHB5W^(X+.=*V1U0(.\2%1$JWG_23(JQ&XSFQR)RG#5 +M]]L+3PYG\^5#`2P-.&6C:0>-7-KVZT&MVENV>2]KB>W_.FL#O#R!#4E)7_BP6B<9G0B1]54;.8]P!0EGTQ:%"`JM4)4V +MN/U#)A'02;LB&VO,TXIFX#,V"-$;OX\HOTBX/.R!+S_E]$6G3P/><-CZV"<% +MI^NK4]OI`G4YAQ_1JGK!XRK?81J=HC5-!E:!AF#7?:)O5>FOESW`"#`6P6B: +MU[=2==5KSM%"^X,D.OV['Q9;\.2@"EC>CDV7A-G$NU8R05V(_`O4=2X+`@,A +MV=!V%^GYJX#TNPU07LY/C"U1D-D)>VXYI&028[<0FK9UG/3L!Y:J!+1NT]F<\K^Z=,J<:CRF= +M,)()9SON*5G5;H*J[5>V*`TDC^M)PN"'_G^?0TOAFZL:`-%[XT4_JC:G9CF1 +M.B$QRC?!PFGP,L(J?C=0T/NY9?=0<_35HGDQ@,(3;)3G&K +M7M3M:I_!Q,*C>3XU?4KN+H$YB_POMN5+,'W%_R1O(O +M=S$I(AT:JU*%]IAU_-$//N0:(\Z"R/DH\YP0=S-K56^8W)O(\]_[233\T3K> +MFG]$6)& +M`/Z+>I["Y([Q1TIMQM&%_K6A5X9)L(3Q?!HQ^G;2EFF%G7$Z1$J^1,'^DG'" +MSY*()#F*"5Q:374-"[>1%IH4PI-CM.N_/E(5#U6C*X'"7>/68_UR2[KYHXGF +M/&_BGEB6H#0<*0@9JX,<4OY2(FU?[1,N4M/]_"7@5NJP-=FF),Q:)&/44XP%JBG@?TP'J)6I@"3U(E#L[+)\)?S^]1?ECZD4W4E%JLDK]#`I9G[.E_1T%)W[K$5I +M4P+=PZA+F+MO),US0(D$1"=CN1JSTR:O9>42,P`44>KE\'^*(`'^:*9I>6$7 +MY'-N)L9^VG$$AX#+&UDG;!D1X#[G-/U>8T-D^N)Z-7UPM6EIYQ;"(X9*2'3C/5PM.OTD9F/M$TGQ,,/; +MTXD3:&#]#2QRJJ/#\D[CK[_:.7F^K%,H68%W9&/^V-8-D\LF!`BCD=",?$?= +MB!_7H*,:)=J9V&._6>;T'\$F_XZ@[@]CT&]%JJ@ +MXA\&RQV"KY'>&6VQO)6S;F=IJ5-L7$>8\=TU*1DD-O9=:DA)%7\-["=P[EI_:\#P`)E#4:`,3N5SKGH,YR.?=.WBPOHW& +M"Q=S)1J,]4^4VW6!C/@WPF<.'YLAP<1_MB-+..L^/SQ=9"LH?_A3`<^!> +M#"!0DFMXH(D@S+W:-::UR4=WQ@>M&5Y^39$3.^ZC'49*&A$/EY/P,)^ETY6A +M/\&TRU+T)&/F9&UO2S +M\@![?'%QM\XG'EL.'>:7`SSKX!(R*2GY(6"6&0X\=`&9=5%H$>!D,T<53U'G +ML:HPLP-6F!0P??MXIO[I:D^]+X.,GH&! +MYT.38F[4,#C4@3G#_(880;NHKZE)5]`4I\=FM6-H[&1>H=MA&X-I +MK+EM3R6,53VZWL"N<:CQBTBL.O_@C\5A8I<;@ +MFHN9VQ`#5$JV?[U5253/5Z7FOM`*N:7Y,NEC>/]I%86;!L9G^([SJ\Y=S#(+ +M^NS&)U2#Q\]4=H8<%]+@*A@%&E0YJQ)EL&AZ_("'/WNINJ'2_;J)ZY@D=3.V +MUDF.BP/H4?5[PPP/=B"2,XX6]TY3DO"@A/MXU%:RA3]VB;UFDT?M%(BC&*03 +MR3R[[=[2;OM*;'\3:68S:3Z0FKC)X2L%^.BOG1@7G@/B468"=Z&'@>,\P<`CFR1379[JSX# +M^'8)3ND3WB5A*7$LBR%5B'W*_S%9+3I^A87+T_+J=63/(]FR[;.>C].&)'$8 +M$.N!#LK)+BK+SG]0)X\!U>L%N;`EZ,"Y85D-U^8>!_/=JT$_W?(E%PA8`T1/ +M&?G(_]KT+Z`4\TI5JJY@T:#&[&$:W'ST!#X(#!ZCXGQ`XX+K%:M5[^BBC6'4 +M`#89Y`0O9C2AM[(\,GSMA<@M/JC+@Y]A94$?=*$EPI.ZN^[_E[NWT)7"%F>^ +MJJVRA:DQMI!\Y!"Z;AR+FFGXZ8VGW&94%+8:#V4"](PKA6+,F5A7,][O7 +MQY2/9.:Z]/>>5DBBP&2:JFW9854'&XHSF1=`/P`F-L'%WUB#+H')H.^`X9SW +MTME\=3#]Z@[973P?`ZT`U0[C=Z+\B9AR_TQ?/>7@=0R#D1F)(;J6[(R6K#,W +MMVZ&%'T++_69K>V"!_+8/S[=(JDW2W13/ELPHUPX>Z=@O7`U#8^L>5^I#,^^ +M%0X(UR=UC:7R2;GB[XAEEE+.>K_X%62HRO3?_FABS=6O&<.4XP#1#E[8136% +MML[E^QKI0]!LXKVXA3Q)(NK--N],:01.E6*Y#[7_#>=4"E["C./() +MT'830[N8>TOZI5+9+#Y,B>Y&%>_Y2WO)9TM5/'(/O2/?VTL1A]]J.[?(YZ(Q +MR/RD>"J%@B"2V!^%YR67T+LRPQWK3"D:,V&"`+\C95&#C[J8W!14:Z_R9ZJD5;Q[MJGX6!4#DBV +M,#^CO19Y2Q:CMRZ.IX4V,=;W6Z#J8R5C>U>S^HK8!"%7\=O\40#SCQMX):K@ +M#(W6>W!<+N9BJ+-ZE>IDFS(FD]+S"13#0\]C$66#;F;V+BOEQJ;'['3MTIEPQ>[?=7K.V^##=MHZ1Y.C/?NW5"?.H(! +M@1YLK*\\6O,9C]B7(Z;C)S6!YK$[ZI,=RT)F%8Z1P*M05Z2 +M8(UTP"7X97>6968X]PL41`(+0\=]C!5J-=(T)21N=%)XM?)"KK390231+=V_ +MX4[NQ!V:,K:?%V:@0V<;_NHP4$>H_RQGS/B>MJJ=CDW7!D>9M,M$AE.)^`HJU&21/7\&P#XV,*(=VNV_ +MA&1]WPZ4%[!M1WN'-I;WVHU;_`!ORG"2_H%?QLA299G(4 +M],2Q"PHR"A1S_"\#'U_I)W8_-<_810PL7LT-8?:+)TA(KMS!43&]FUMJ)B=O +MC,?"JC%"GR%`)NK/P:_:U\36DPN=J&LREW'-EV,#A9:Q@0<5"V4NN,N&FY3;\8&!WWZ\U+CZQR:75J"',:_ZU:=UG` +M!KS/LXBR$#H0KJO,=4'\2#1%_.$JEDR +MJC6V@LS%VHH!,&+K>(0M1BBWCURLY(.=#+$T59!0K;$TK"Z!J5U!]C#6[KI0 +M$\&[T`G>T^.3058Z">UX^]I#W!0.@0\^NHRS +M&7$/.K34H6S^B"E0P;-_O#XZ25]2DDUDG@1%\!O%8*'RSOPU\"C+P1J7.U9J +M0)"+']-@[A5I?,L'P!*7`C-)0KX4CM.1D7U'MX"[=SRW2NW_O+:PZ:_04)AX +M_3]#O/!P^L4":P4HLX22KR4CU*HWD1M@#HX85+IA1$^&*[R&/O)` +M3_@:D$MW]^>Q!AG-D`&)8JV+6`CNKE"3/;JABET)L.HPH`TO1FN&')48-QIA +M4]?]ZXS;&;;8*:_[.:UA0I6]24P.Q0@ZKXY\WF!.$<]S+*=>= +MJA`!H$G[!>]DKDWA)BSI^5RI<[]HOAL:W-91%WP)MF"%<+GDJ:TG."SED1]J +M=@JGLQS$'[G%H5$2M,E1[+S4,@=/@(F8=-;V7[05F_^`_Z]GV$]+91,!@D=7 +M5;>DW/YT1E](=(9I'0IE<^")#)[>H995]["Q*5IS5E&@=>6CU8HTZ/C&UUWW +M;&`&&2*R:8NX991N)_N3UUBCZJ;T7?>\`+QSCVTGA.:HTS+P96?V?:G>APK;I.Q&V\ +M754D'^V]#,I;>:SZMT,C,<)IA;_KS$AJ5`N2QF'<00!@Y\83Z;@-XY'P*Z27 +MVP'A[HU,_]MFX9>2R2YE"BAITJ`\EK8G['C"AO7"L--B?%*OF+5ZI>W`JC"7$VB*;1*&C__+>T%JF>&[+ +MH*JRT]E4%/8@=!J(U0"*%7QW9%,$=LI/CRJ/M%DQD%W_@P.W_)]#S@?YX,2 +MZB\>JD^&*`D83QR1LRW8-UN4.5MA$H1]QD'=/P.OKF9D-?X%V6%+$J# +M"U;R8B>+)^=W%)_W]5SHP<7N?K)E@G?[N=A_D>D)?GX+EOEMM5UY*_N+ +M)YF[:?F+0@15&9#CPSU?N)DARY,G*GT/70J7,GDH=!\SF'H +M1Z>J)<_%+3.]^"ZA)J/D=9TJX)3,RON[?Q\V'Y6-QKP,'GFIMRFS_O(&49XR +MSS<+,YN-3:M*M>C@>TOJ.NMR6.2U:Q(78[;MZ/P/X^;14P]\#4)Z8L=5C3"< +M<`;?-<8&)+7,)2DQD]RLIGRGTJ/`^#5#J@OQY%/=XT$/^=?C&NB(@!`1]K3; +MH1]Q1\^):Y@1P"Q-+K)L\],URFD\W8!:7:]G(OA%@,GBYENLH\E^-P^*]$<9 +M,1;),P>1U)>[,5M/SW@'6DWD_;$&)_62ACT7&O#T#AW0ZALL[`CN)TD(;F3$ +M\-04XM_J"PMT'E,YJA6%;I!18X=$#:N)!RJT&O2\W(YW*<"):W8&:5"8SG=J +MI7[3N6J.`XPL#SYO7(+S9)-_E/D`EF6Z9O"7_5Y`20N3H^URAAU++.>/JR[Y +M\RH8.FX6&!'_52H8C@U8!1"H#'\0SJ3#8N2ON1*6\K5@0?F03AT;8C2=WX +M$'1J9NRKS]>MERBU]M"^`I][);+!D>0W`K/=IQ;X!/.E*&G;D< +M'S6J5JK]Z.C/3U0GY'ILQG8%V2W\CB=EO,^?Q78I(Q]]%>4=;$^_M+3V7#9E +MEO\[W&W=Z0%TSNU_&0]9'%A6RF9`3?F-$N]\KFM63M;+TT&&[#")&1MD`08X +M-9CA?K"(VQ"[_>:R*\NFI_WT16ZO1/^$1(244G,YL*+!2?KC3(;:$K+)<'>6 +M\W(19/O>)KU8G(*.A$P-@LPE+NOB>;$R%P/?]P6S8=C57_"X/PS+P"WIH6TX +M[@F$V<2&-ZW<9/K$L/.]M'(^%J'_E*#COC@1\-:YG+7%3*8?3#?1IN8S1\H8 +M2O*L_Y9[@@G6\56&LSK%K3A(<7\6;OPG77UVO`>_%G\3TE+5KW:12?#^E+ER +M?J:)+IT3>O%VGQU:@'S&J._.K1X+IN+W/%$[T/`Y( +M?_LWO%6I9KP)B&F:DNTL!Q**Y68;V7M;5FT8+#!"V&W\YS\J/TF?I%L/+XZG +MU:X,T[#?2%L;=J-,5=&=\D7*=D70:_Y][WR'!M&,%S<))'`RYP=_GSDUW?QW+NY[J_XCK@I$J%L,)Y4A9S531 +M!AF+Q0![7:./^B#M*)W6\4#O+K/#GPDUAXD;))'O9Q9],'='!>6'>^^YU]7J'F(5J5- +MHL="/^+;SU46LJJW/'%+2[+&=52E4)'+T^R7:(0/KT*WK&:OWKD*ECAP!I*& +M*LX508"(??K@"46R1<9JK%EL()&%9*;6=L_#1PC/*"$W3V):XC:#1^S*&''G +M]A?ZROJ8?GK"2!`#1Z4X2CW\L.O%D93:'WI;87L#Z?A;< +M+P7C1>@BFA42CY?Y<[^Y__OA=\W2H(N.2VF!)8OI1C@A&F81!NBQBK;QNM/C +M_BWAGQA-G7=)=B[7#+LI,D_N+PB>8\(!F%EHR,_2WP=EJ*D$E#.AY-H:Q:$Z +M"2E:PZF^$VJ0HS,L;BI;@W`/L(#\8@Y]));X4_.=[GQC8`YV`:MW*[(LL +M"V.HS:&CZ9[233XFEF6+'Z%L'^P79TICN(PXZRQ3$LF'"'M&A7K@O+BV);'-UN547DHP!\VG9TZ?@' +M"T]P>4S>(Z4B1:_>;&A:;P9-R+/_C8<6XQTY1R0@2_S8*IB-V/F?^/[AF_J% +M*OZ0@QI!`U9MJKJF/%G30@UFZY^)*V""RB4T$LDHPSRYW?*$UP]YZN+4BYA/*N8K+.9+^*QKJ9R4A#-08NGP?K+&RK.V!+`B8^;:\7)L +MAG$'7]\-:I6PNF`:FUEQU+D%#I*54`XL$Q'R+Q/.4P]35LA2%B\)8'>PA)>T +M0QHW.&E^?KCIR3>MZCZVD+"L#Z>\&DDM% +MWQ<%18B7DH!`(2T2=%Z7[P1@RP[E>``6&#Z9FH&_JCA44K`G#Y:'A +M_BB7FPS9ELYYW$0(*S^*V@NK^D(KR3.`Y+O`I-/3\V +MK'=@7MVY_8"[?Z?H5X>@"#RBD)"H.[9%MH[0OJ77&+!.^YY(V:C`L,XW#&^< +MH-(3)][D9$;1SWKWQ*CTA1IC9(LCF?$AYLB(4HAC"V::GD.%)ZD6,7JH4J*. +M,UQL^":[9/)3L$_JI26O\XTT?F^,Z_N52X!PG7S<7\[>.X2Z%9,2#2O]?FKP +M]=\^5%7L8C2=BM/.:,##)+VZ0IX'OV\G6H8W>,X/@<_^@NKP( +ME(UW7;D"S2[CMP,2L6HKMUASI@HM@2@>FX!^ +M$@[J-#0L;[\$R-.!=HK!VB7D(=2>=WI6N=21>$ERWO4RM]_OW#KIRC)NE)K0 +M-#,A.YYC?6#&:Z#4=H>^R^TQ60AI9#Q\/3NMAW47%I`(R;O#'<[%<$'#.*AX +M6?"5(""]B?#5>PPKQ&\\7DQ=R9RHO:06U`^/;@5_8[K#7A(^!")'K6=FG9H5 +MW'I#U5R=,B_2;X21NVJZ8B7T<1$D&M5S)[49/M/>K,_#G<702&-%C%,Q$>K\ +M,/QQ3$+"W"W;CW,*T\@/*(K=OZQA,D(J6`0#/"Z5XT65.=I:K5H/.Y)]X1-LP)K0>O8T<#V#X:1'TW-EO"("23`6TC/9%#E_+>B)SE`]! +M9V,$98=7+;H9\W,/6SV<<.";@*Q^Q'?+X)9C?>5R2RQB927U3(!9]8;.ET;% +M.VU!43T4%O*,0Z%^&UM=3T-\OPP(WG'U'J:J,_858,ZR#;?"X_E1P(N3I4[E +M%[CWA0J`!(&[^I+#/M0H)=Z*@1\F?&8-P":7BU7Q:\D/>;F9MM?,Q?ZQ>5+: +M6`\1@^C3W$OJE[$ML*Z"W[FZ^>2!^,)*0>+NZM&03X"X:%0AM=>_=3\8A>JR +M65C$AR[XZ&QM$0/)%T:'_AYB#A1.K,6'13QNQDFP2]ZSGO44PD_[6<$.4_@) +MA=#.#2Y>BFPR(K167\JAW]HBJ)S;'$EOTE!+`P0_``$`8P"GBPY%`````-\0 +M``";?P``"``+`&-O;F9I9RYH`9D'``(`044#8@#W\M,/\I_FF^>QBW/Q#WB3 +MU9P3Q!W310Z9(J24<#H%,;6S#?9W8'-I\AGFD^31>KETL:^^VWK8!MPG8?/V +M"%6V1IK[H7#T#A!^6OCB`(6.&7DM/8!)2AM)**28"8]0^5IAW*7WV4^@7B1/ +M:"?>P>BO`0.,[I"C-4'`'`_7Z,;"$LA)8W.(6.[`1\"2Y4[8.J$(:P'4JMY0G"*V!6%Y.3[XZ'>##XEA4TA<,NV],9F,$% +M^(=A;!->6:XZ?;4"-U<@[0"36$0UNAB#YS]R +MV\SM(+CE.,!ZD0/+^8UE?&FU:0<`F?@RNHU%;EMRS[DF:C71TLX2+H@X1[B5 +MX,>6\?P7YJ6$_O<_A.NN9$K4;RHU1:=.W6WV$T6'$`BR*^,&'[YO'+77SR)' +M5AY@)`U4J[9'N6A+^>G6ES&]XAG5U/]S0?A+F>>I.B +M^AC<_J3(D@)-G"YE1XMX1G*,!'Q89:C@9O?<3'$/6`Y<2=(Q&6&B-SKKB(>\ +M]1#>K@5#AVQ9-7I7)V#U)UV=]PF-%O/X+ECL'0&#VUY#LU_J2T_S#! +M^V!C^UBR++AL'T8]W1.":9?-H=83'_W>=DZ#8RQ*O-=S"Y0QWU"Y+UTC9A86 +M\'CGM^';X!J+,6'0GZ5VYO#]'J,R*@8"SW6WNN/]HBU'A?XT884WC#K2%O[TQ-@M-PL"'[,U' +M_P1C\YC[IT!G_3:5AL->Q)Y;EA&IT=K\(@](Q&@$3'0A]R*80WO>!0"0/C:G +MZG42!A[)-!_5/.*"2SG%"/8#$.;W1)O7-O&Q+^8_$@6$;Z=GITIADBW5DFXZ +M]:OAV>LM]KY<`,JLYUQ'>=\P0+D$F?A::CPFK/DA85Q)K4ST?M;W;@PE[#*N +MJ$AN1'3H0J[$_[> +MG#Y3GB>YI(>HQ8/8#*`')&-Z]*+'YWEOF'#='!#`_3 +MU=5Y'(3&`E]Y>^*QU=V&)S^-(MY"([!D-9,C*! +MAW&P0,SGM9W[1`S@SG;1JN(BSPM_>.(RE-C89B)THD@2.N-:-5/"7 +MDG40)O5XXZ]9U#FL+TF0OZA^#ERQHZJ,EOV,94X$#!:ZQMJ'NP6.05P_5Z!C +M)&IT.GE@_KFW;"L9"5/^T&29$FX-+U:P]N&6KW^^%QB"!A]3*>523(ON9V0A +MJ;88JA"$].C=KA+ +MF&9+^H89$ZTH&Y;"76GT%*4GO,+2K(TV+[9A[F18<+,"KIO^+^+Z]&^60X+\ +MZ8UA[1)XE]7E>;"@G;M@"7_[NB"I`0_6U-IP>U+3PSU:T,-KW-Z5-E^[I*.\8B+TQ="D@7,.V +M)&,`_O1GB(*<.H+Y%II(URN477+#2^RJ*4B*/1S]S.OZ#P.]U/%+"3GS:Q=5 +M?&]APC33#.ZX^%PRQ/KVS76R]^(`1;"$YQ5(U%12]TRJMF;12I?C\<"BQC@H +M)L(SVS7<1'F7$I[.*-D#PQ:CC7^V'!U?KM6=BL'1$AW?79M3-?&'+`SPWW-^ +MASVYZ%T:XC=8A3S]8$FF$K*VA)?G],LS2*4P?6X>ALUO&PW+G:?8,@QT3&^^*:K^:.XO:$3VU67=.-, +MX5_+#'DT`'9-VO4+Y9/:'WD6HCZI0(E`(;T +M%'QUXJ=^YRSQ)H$/H(UZ!`]^!E0-UIJ/VG!@3THVRX7O6I&X>#,YXP!)Y!F4 +MW,,9,TB&N98*2K[!A!0-V6=_-W2TEB#2'/K9E&+#U:T>2,-D-)Y+/\C]?'&7 +MSDD^JU('TXA56S,/K0T'CU5O=,!-3!3EJ>U-#7%JZ39,+%L(*GHT1*"=6X"N +M^:>.0NUK,!MI*+OYG+`"A_80UA?>WGM0_U!#YGU7_,7+N%_#*/]92W5$IOC, +MR-S=F*2M5=-?/S<,<[`W2B#F$`B!!42"%J![)%&^E\D,2+)RGNP]D` +M47Z]`U`]]0N\J&QGQU0-S\PE=N@L65E>VV+$3Q2'D_NJ*R^2Q.$!=I"H>9_3 +MZX?4XY#_SA/*)S323P!O-IP7_\0=-9FBR6M0498Q5LL_CV#2%P +MTQ/*M0QJO?5Z\ZM#$;0UBXEX)$W<@H,WLD*;@@)]S7%IC6'FGVZ=%%@(E4'L +M#1%:*0JT9,T`SE.E2#5UMF:_C7G-!]G#25$"$ +M*!HC2JM$GJJ(Y&+,H"1SRF/8)./_HB*_XD$,+1B^!OCM@HVM6E/VL+7=652J +M=5CVY&):J]`:@Y]WQMX*O4+JA#&%((H[Z_BY"R%]!'I:D2'QAB-`F5X>;.8H +M[BT-)B4#Q\(_T@(!SXL$.IXS*-]!WN=!N-_@AZ!_N3:ZS6^9M/W>UQ'ICKR' +M4>K6/[P))9@[DX:4'0&=Z?2]+37PJA5!3J1*\P(VCP/M9W@2*XBZ5_1`$\U" +MFT#U0IBW14O-Y3'W:=&2!W(N""[Z([^H/,PX<3Q/\:\VBPX%?;"3CD$.W2Y@ +M:P8S._-9-ZX>L?$6'^:KBAG=RFP(< +M>4X#_X[^B:WE:K9,?8A1\Q\Q)8MH6Z-_+]1( +M>"^0\@'#!-6[*/:QA.N#?)V_4`4@'FXPN9*,UUL+(:CWMF"M?K>DM3_FK^R, +M1)&M,KDBZ9#$NM[9:V';0`6F^78RZPK0IC`3O32C0%Q)^.;LQ"[-_T>(>&T97P!Z39(T-T^W% +M2(E$.*.50G*EA*JE14$9(V;`%U[&I_Q]]U1)+4M/%#6O2G(-9DSS(.;64$D^*AN&'$,E6]';E6!\`->ZN>@8#8?T':( +M4YS9L-8:+#OQGF1EP#I5PO0N9;\F?0ZH[G@J)W2(;UQ +MC&$\.!YZ4+^'+#;C"0!?9596LPQJLJW6IVN@GR&";Q89(VPY$*K,8MO#.I:;H"2^EQ;'SKE,QDR<9=U^Y.W^:XF%@=&DO=F_\!IB^ +M+1[&6"(1>WX!^8D2.8D6+YU'MEVQ\58ZQO,TJ6`/_FL`V*S.^%S_'`!4QX^N +MN&YSDZKL(A*%^Q=JG%*PL*.H`8[FUOE!/"KBZN@^N<2_I`&7IN$YP@9W+A\D +MLWGOWH!`B?/HZAR_7/?R+#"]YLB"VT&""V/$-8%O1;?^#!B?C:4#;L0Y%%]" +MT_/2I&DA9U+R5_B6]U0>X[?E+\U +M<$EO<9'FK8`V+5Q6OM_.F"T#'RGZ8$:*K<]PO;-]85[X4(8*M*/'22IP/WG@ +MPSU3[2@$%[,CO])M$DE5S6:;U:$>R9G[F#-"'12\%80-*VXIWZB$0?WC^)Q6 +MJ9K^T7UED+:(XB"BD(?[1"B7?U,5XDZ%R(-@K@`TK%D=N0'?/O7$FA7K2WB7 +M(([PX]NFTI`2X\,SP#BO,2VYKYZF4U.[EWZ1QXV(3WGVGNF].3#"-`S23WX+ +MRU@`MJ:)\PGQ\MT\9(D^);^^\OF9UJ0TRFMD67UDBEKVT+]FV;*=<\7WD>+1`F0DXB;_WWS]V)'B7X,!D`KIVZ>_`1MCX$89E]L; +M#.PV"Q7<[A*Q0W-;8EPY:AEPB8I@-1TU?P7@]&C,H&OUNU;_ +MI7QP)0O7Q+_&@UDI8]@3?%DDMW$FS;,CG& +MUV`TZ>--7M&8*DC*R,#T6R$7F+N5O&W3A1!E'XL0FIV(/_MNDQHL_DG4#$($ +M6C39MX[+K@L5&#[D#G=FD!'W!70'1W3"CB\8.+BU+3L_>Z-8IC%&`-%V2SWP +M^14R9SIL%^BM:*'3)6W%V)\TB6?E4QY],&2QRJ,\=RN;!P/HKI7!&V-I7"0Q +M"(;*6'M]P%F=_O0U@4F\O/IU,NM5LBB+-+O8"]-H4E\Y2?)Z'CW1*>B-:" +M,+UJO3O1T9=].(&1SU8VT;GE!*U(Y0*PH4%%"7X/T]&#%V9]B=B+JUO9\#MK +MIW!M']+NGG8O"SW\.B3C*Y,(%X/]0D'.K79&1C#"4/X,Q5N%0CT#O,*0:LIQ +M>+%@ZF`<@K7*2TP>O/&D0_35?.GIF$NHWW`&)/%;G"I[<`0&9!P`"`$%%`V(`4$L!`C\# +M/P`!`&,`C+`.10````!&(@``K7(```0`+P`````````@@*2!QK8``$Y%5U,* +M`"````````$`&```/%Q3`[C/`8D\5N<*GMP!.E56YPJ>W`$!F0<``@!!10-B +M`%!+`0(_`S\``0!C`(RP#D4`````1@D``*(:```&`"\`````````(("D@3G9 +M``!214%$344*`"````````$`&```/%Q3`[C/`3I55N<*GMP!1FM6YPJ>W`$! +MF0<``@!!10-B`%!+`0(_`S\``0!C`*>+#D4`````WQ```)M_```(`"\````` +M````(("D@:[B``!C;VYF:6 +KW`%R<%;G"I[<`0&9!P`"`$%%`V(`4$L%!@`````$``0`C@$``+[S```````` +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes256_large_xz.zip.uu b/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes256_large_xz.zip.uu new file mode 100644 index 0000000000..5af7b50ab5 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes256_large_xz.zip.uu @@ -0,0 +1,1898 @@ +begin 644 test_read_format_zip_winzip_aes256_large_xz.zip +M4$L#!#,``0!C`/BN(T4`````X`(!`&LZ%@`(``L`36%K969I;&4!F0<``@!! +M10-?``71[/`@3-8%7,YT3>IM,M6WW6<\@T.),X%L%.B="`.!_RP5.2,7!<'R +MTE6&8'L\!1DZ%LQCGO4&L-0`/'?XY5@GSJ^G%[D>`3[-+324TN&9,@<4=WM[ +MGPH?CSG1Y$4OE96FC0IRRFC:U^V2-!S73Q)/`!I`"#HIAGOTM/QD4,D."-9X +MK2M9#*'@:Y>Q\%=,H<\HL,*G-ES[*H<+,5?ENKV.97SU\7W>/0\!=3Q*G@H= +M><1D*F;KF&>OOR0@`98[I@(^>14W&Y!0KWVX2Y]R&#NJ3>D)('$+P3P7"\98]ZT5]P3=$PLSD%6/R@W-Q']9+.#449)*8D,[KAX!.4A3A6C +M3`5T9UC&R49C`2_^(T:>!<+Z6@6X&TOI,\"[Z>?^+%+OB]K"6.N9];3BG9EK +M'M4IADMG0>>^4V&7[?(6HF@(`_OD_$P$R*W_0&1R1ABXF24X`8+1$\W=`"=5: +M"/!P@#0.B["?:T3SQ>I6E,83B[F*OB%Q:&]/<]7,M2.3V[8FTET7*W_C4OLJ +MV1)B1#452FQH#^2#:N;"F4B19:TF]H1CI?+3%3/FP>X_8%'J?+`SW8&]&[8] +MS!U[&%_+NF'9B?1("P&T@9UO3L^%_=2;,<#N\)=8IT\?.G +MP@$7\DG7#N&#J27X!X6M%5W=W]OM_F*AX7@;=>.W_+0S]]00L$L4P"YX.V6T +M/[9]#6]C?Q$8WF9B3^7_0!'ELI8+V=^>C8[4-\X(`9-+E]6]:?R+J08^ML%' +MH`#U=`WAZ?&B(+@RB/W:!K2&QM7Y'*C!L-H].XC&*TKZOX>C&/H2W +M\]/1^UTKAZ_7CC/,="K#!)6KYM6X!9D6`H*7(3YI+XEV.84>(&_4O5"-)PF_ +M9H+%6(_%<&6DJ+V)#D5]XQ7.>8P7WW!PA;O@U2`^`T@<9P:@*H?9(/>`JN3Z +MCSA8)*]:G_2JI_GPHY'\)6%#![^$:W+)KC!MN.[QVFW^DN+.>N\.;>E+>/UI +M/>4P`-J._(0,#T6*TPT9W4QTS9F*H47[08BQTWL,:URM#%E[3X82RYQ)ZOY% +M/.$1X2V#.`7VVDLL78F5.B^$UP8M/,M?3A#)RQ.(P'$UMJ040Z?5UVR:HPK> +M<"2>:Y.WVWJ:F"R,8J(75W9L'TK:#&!RGP-<-/?'E6(?:+#\ZFQKPT'SUFK( +M[Z>]&R"@55+@PY.+4@`-]N1;PL.$`&4R36"K]."2V(0-N#;"T/>=/WOGKE46 +M>_ZRF;7B\2>P]=[&C0TK?+"I"/V/<+3X>R__;U+\C!..0<&H/9?VYZZ;&OA[A6C!YM;.7N3L +MN=+4(JTNDDDRR.&MTI!UO[XQQIL+V62K/[]-M[!A8RF]WE[DZQ5QEWEECS,V +M57')I\I"8(BVSER=9>_HLTT?/]*I+CMYYS/E]I>(=]^=M\HQPPUSMQ$GBRF? +MOV/4`LXR41L4"P;YAQCAUTCRTK?1'"P-F3N[LHSPLI@G[Z^?5:HX^B;S0_U" +M[]=*M"DYAFAOEK*:K6%ZVG#6&(B;$5/B#A/6FXO493J;6QP#D`HT(4[ +M9Z1XR)G`E8RL'V<[32+ED)5/10SX#YV-#4E,Y-X_&)DD>:2;^QIJ&I1%W4X+9F:R.=DK\.$`9H&G0FVKEX4$X$GAH_5ZG?6!T+T.P/;-ZLAJ._NTX+9_0I0J)+[',-4L6I=6`AA?ANJ4 +MQ<%!HNX^#Z_G1IG,S$$P1UU +MJ4PF=8_+N8H>K,_4(5/W>!0VSLA1[!(7J735+]0+?X[?),-N9^GBH2=PLTD' +MME!#C]K!7NQ=0N>EV?@J?+THZ*1?4-;VQ3L*"B7+(,`&&&8/*1#D\+@(T[A1 +M*)T!%?KV!(S9TIS)_$V>**"/KL3AMOY'DKO!V;37D>D7'T]OB8Y6/?QLRUN) +MSFS(T\(\[28!@>)(XZ@X@2SUN$%!] +M[T*-S@-Z7X+G'(L]_Q[-N,D!ZKXR6:\-(1$&1U.?9#Y%-]T3&8;W4&S@CB'B +M9V+<0ZS(FV1#%W'MN`L1V%)G7_O8%>V+^_!5AJP6410_4LP +M*.N>\(>H==^57IU;(SJC].Z"Q,R^/6S[*V"&%SQ][.!XK +ME+AHJD+1\=\>O?XW4M/SDT7:IM$O1X0EN.6UH[\TM[W"SYZ:B+A&&3/AH-82 +M2M[L%KC3,%1DU>F^`Y4K'DYP`[\FF-*1U;%5&$6M42IBBI1=;@"U49'#^[;D +M$=3&*M76<34Q"IV,W(6D;:J0(^7W(I8??8-KU1+JT!X7"(9.\J2_9[\![_H; +M9MQP`:BQ#Z,)8^NV('^"N1+*I.TY*(+^OD#*8[Z,EQ4M%,T"E8WH=(*A3U;@ +M&<,P8*>JC?MMXAM%:J]R,`(J.[&^=#D^`N&]'Q^3N6@6E@M9'A,M+W%%HP5* +MIBY0+_P;8'%@KW`A4W-@U^+VLHDSI\WB6-LIBE:\#XTW4JUW@WZ'A@03(580 +MM)DE*4/Z>`2+`GKJ+QE9@UMCM@;;?EE[`1_/BJBY8^.L/M1JIX30"&T5^V\8 +M#*@]+A^JOPWWEM)E57F])NJ&?YYSI??(!@(DKU/AM7.A=I&,(I4)?V`)]C<: +MUI)B#9GCWUJXX@Z%R]C%G_=]``(R=,3(P(0UT_IGJ$7(-,1$5`#9UD).S41- +M$`;ID?L\_4$QAB[Y +M=>*#@]+:N=@.PJMK;AMIZ7"4W"7K!H<`UEZ0K_\=EU5D<,EE] +M*%+=A$R\W[@M#E$[THO]\Y-]LE[@K`[?V_*^\?2)"PMT^6D*@0X2$BW%7D#D +MN*>B@D@'%'9?F;W#I$X15+""EV`E&0.&M`<8IAU?)?O;OSCR629,,(,H7Q&; +MAR>^I+,M,L(T&J:78_S8F<"/24$VV>-(7B+@V4'ER'S!LA`C15D7Y2_+?6[X +M3"M1`.>Y\RO8N]JF/G\*"QB^C"NG^\<)SOK&NA'T5IOH>,X7%RB[(XE?@G:; +MQ'T0.=0!W'JV,,3`^E>X"`G>%,&8$)C1.K?%$>F$^SJ@I!.B>M/MFD^,H(R +M_-%!0*F=.#!G`T_K\KS7A>S%^ +MOI+]@-I+T^H7354:&[0:#[AL5P`Z+L8LX1`(*&Y'Y,50/&M^*3&@5!1@/&C` +M!?AW6CS0];[VSQSN%3N#C]J:6OMQD]9\,D+(;Z1=CA"ZV!/534\N/ZU);.:; +MLO^;^L/PP2T*']M*`6BY36`F]"FB=5NDM(Q"YORXH^1#L91%`J&'4)@2,N2T_+LO^937/UQ0N)UJ&+>! +MAXA&,V)9]2H>CW4]HXM;CQ6,)$(34;P'X6_YXZT>C,RQJZ#Y-0JZAZ3LFOE+ +MWO"S#%EHK;^??D:.V7L0G$5AU6KGY!L+B+&A=2R!^WPRSD?"C8:JHZMG=@P@ +M69F;DLC%*D:EF.KO`0MV=K*+>H_^2?X8@EKQ9@:M_FG\#?5W.+6/_87X'R9+KI%CS +ML5RCH!1=P]5N0IP481<":FWD1A]?^?O36-R$Y-AMOC1 +MK2'JP\XYE/.P'U-?I3"QG4W3D"S7/90`5=*T%HB]_\B\1_J>4U*#C%L429S"%0F+S^5G/SI?_3V1M#16'A>*#E!!^,?.]6'[_M<6UI+5 +M7_=%,.T/.O%VGN."3T(>+_L,QP4BT.3_G +MAM4@4M%;2:J&;@TGZ@:_,$'T8V(2SXN'T>FB?KZ%D3W>667 +M0;JQ-U,&K:`M`Q6Q,+:>L4H`>#U^.!5#O1C,)$_;J^<\3X^+(*7Q/S9+]=I@ +M<4$H./@!0?2(=X./#F="6V&QS4$.'+J/B8*W/\*BS9$1'=B8:L.Q[FB7PBU= +M@<1#.3:&6KO,*9M[D-19NAC)8I:2"*2/FV4?'G$D4*S;3--A!/+X45R[I^'\ +MK(0CV!DB*?Q@'O=PY%I2@NK`FZ"`Q*ZYAC'5C=Y"T0C`>;/;`B`M_0P2]YH,:M^V' +M\B37`9*=A:H!?,T0*P\P*OU5H#>8&M>TV7T_MQ-`C_]`<^'1.\4=CO +MN"!6]:^>MK4),DW#`6MR-I7C>YGT)[V$QM#ZEHW8UO,\0H$,:*?0=DP#O(ED +M_;K+FQ*"2PYWA-!X)/1RHQME*]/7MX]B04=W8(O&?Z#5[#\PJ%X\Z^!_REI$ +M!="A"4_#1AX+%UVP\J$+M"R\5TX9F0;I#;KV6AJJG?('WH(XDJ4-V2ICSK`M +MS8MA,MB>A/TNM"8[^C>IS2#H11/\#E8`V3HA`LPR:N@K`%1;5K&5)^DO$3F[ +M>*$!UH9Y,"`G%WL?^#C2&Z][/!JP8XETB&S0R@)^83,2^ARF#NC2KX*G*X)Z +M-_`-XG"G,V'G\'#4RE?7F'VYHT:9V!AH1.X?@?+(Y)5SDX/9=]TR<+\?^#S% +M,G1("3\[6/-_Q%I2S?O@[8">3%F`"=4D+%/!Y./S"MYL/CR2PJ.$D.`PZ"5T +M9=%6C.Q<;>5[\,X-@RTU_B?[?7AVUW9S+H"(4'_(ON@WW`S^W*?%X]3,Z$5A +MH+G0YU>T""+R2,)'C)>1E3(=!U2O5&6^EL!3$RD(*V[-FOEN98#ND4LT7B/C +M%I2`N(#7FHXIU!B[N4"`[SN?-GI!&JW+"=[6,FVS1"L%UPD1LP;P=LTL&#X +MD4=#DFQC"%8DJT_2WC;,RTMMB[T?LF.%T8;CJV)],K'`\R7H^U`I]5(.%='? +M-*7FT%/K(F`CY`I3G=Y,\S79&$]-GE.OY*QN!XCR">ZJO]!NDB-@[`B(.;1E +MV\)>73U+P92F;42/Z6MN#?C*BH)N7HC5RQ_@9:"I]PL"64"DZMG%-M;MODG-F(TE;X3?VT-LIP0$\[[LY +M0=^;7DGO5LO8+[(E@HW9WA2"=='VEQ1*:S*Z/5<<+50IFXSZ-%+U@)`*ZO]1 +M='!O^*$TIAL]OXP'/I$ZB19;=GSI!:`.CB7GN&JT[N`/!J=^>&][)JNNV,AB +M8)[-X$W+,.JCG*LX`JTYI3X9416 +M\;0MGB5G/E.K&=J9"KL3C4D'RZX)XVI/'-RP]QWNK0]CM*#YJ&BV?0/?&#-\ +M/_LX75]"S7JE[7+\?`#4KJI6T`V4^*2X>1.*@R;(Z>`CRCFGJ6;%-ER.0VXE +M87`;=HTB!XLE74(@OL'4R9$%GJWMTZ9>[:8M9!!_(>D@L^&`:T%-.HYE7^&Q +M,*(/!)O7#5LS&ODJ&J>,!RX_H`S8!\U[FQLA"*&"[:\+($027=!.YF:EZPGM +M0X(H'N-*(@9Q(#3Q;DR3LL9-I#=,I.\'?L6ZJOXXE7K!@1!V1W(:A.9\'+[" +M<4^5/DTJ"LG,]EXR,L:Y0XKYLZT:K6T0//**:Y]4&2J]$A&PVJ6[70X:P\0? +M5)CK0:)*E$^2=P"%.58613HO>!LO5'!LW81FA4+0<06!#G;1`W"YJ`1@M82MB_N^:AXN3!6*K6W18I)T.=J_TXJC4V_/O:GN(;)18E7!U;Z\PXC +MK492*:&-O>3OIN1(=8-)Z=]I$>A%-9+ +M=D`$&N8M5J2#]N!VU8;0\W2&5GF9IJG#X8X>&!U40"RG*VPUQ[+8>XB?#O(\ +MC4-]?>VO1IJ"W1*[S`)UL[SX6G3>A%&^KU\AWZF[.L2\N07)\"OJ.6"X&Y9& +M`FA/S3F?3\051;F4%V;\4\888[42F)72,!3-J\R-^R`],+B)6$KIP;B9BVW( +MW\,L8RPL5B79[>;K-P,KQR5APIH>22""/*O&^"\W`GIWK%TUYKA+O5T5BC/K +M^4L33&4Z(&HZ!KE1Q^$1O1LYZ3_Q;\HL=@UC@NQ/.JFS$5*P]V0IMV&.5+Q= +MU)EO]7?:)=B/G+KS=DA"=ZFE(2BB+5U8V3$O6 +M:$PQ>'CR&3:>`Y*9RN7ID[F"B5>3-OORV(=AGPP^IZ>:U+118%*'Q*L5V\:? +M8DR)]9R+'S7ZACPZTBR.5LD;JG3.PN[:)^V]=:M'-^A5)^9X?OC(N;EZ;\Z` +MVH0.!E'5X;*VZWNOWMOQI;H[6ADL+9E#^AL19HIOO<1C%939#)V93RRA"36UX!<] +M:/1*$ID50`<*`"Q%O^O?,PM7Y"'_Z6@:6\?>%]#>'*<>X@-XX5"GK4INN$N! +M/P0![S"[\A`A4&61P3)Q?&4'B'R`6+ASZBW'>B&8R?(U__`.-K1` +M/?RY(YX-6;/#0>A_JE7?Q",L\ZT![]\&G2YL?<,Y5H>_;5H%FW>ITND#NU!S +MNJ:<.)_[(_'9Q7$W=PWP+I=@T\:IT(PL` +M$#[HYLQQ-'?#F^]SL.'4Z$OF0G[4V$L`S.]2T\!"7^]UA7G4\!#QNL`I-BF/ +M%.:+((.(D0Q8J"(<;Y_4!0KTR.CI:LA<,P#WM:= +M$J*EBS=M@%JP>].]&+6F-(K_6,4N2@"M)O4@ZB@/:G#0CR[N3ZW5VT6`6P/FL[;ET!*O,%,N&\C%S63DF`8H= +MM3<%KVRTI;84)NHBY?NP::WQDRR)NJLY2Z@7Y;R.VS-91++)R=E=;N_;ZE^[ +MXJ>$;!NJD\98`I97B1T:X$F:4M<88)1XU5"C=G2LF8$(M)^$.1KOJ$BHF7[2 +MZS3NM&7C6GO)7K3G*4.0ILWN:.2DN>2K.1Y'C[R,A4CNC7`)8P5/.V+QTJ1T@E!"EGY?OB +MR8*>6DFU&I`FP+^LBZ+>OOG<8[((Y5B?0?V6OYKND.X8VWL8Z]6+I]M9]X(9 +M$DN.!ZU[KHWG("B7A[8KC8AZXH4]413^D(.1_VM]?\I>3WK4K)9ZH]4I!&Z* +MDV-&;>A>HMN!QC%SK:/^]:`/15D;PT3"_JL=BB$F6ARQF#Z!"0T72!>BUV'B +MZ]V&;%>]HCL+IK5UKIGJAKG%;]7V#Y`#FF$1]4C9A)?XY[Y#@XGB9?Q_<4"Q +MO,ZBT0ZV_\J^3O:_.RZZO8G*_@P3KP.@NP]_'B90TT389UWWSF?3FYHHBH/. +M"@,^24Y`A@@SM\KW)WDLYM-MADY]U45,6$T='*D^OR)6\]'&&+5I`@XF1X/J +M>^LNEF002[DQ/_3:D.+.HY]<27XKIYBEEKY)B361+,<:T1CB5=>)WK^7VW5/+[D=:3E,DB,=!. +M#_5H)[H*NYW=SS*L04/>:#>?TXLJO2BFCJL-;Z:-S]L=Y![O80WG0-*AZ7JX2,X!1_\U02OA6?B)K62GS:[1/^3=*. +M\3RZN&L..!&R:=$J[FMOHV2,V'!ATGBJ^1$R1:P7TQC.L\?$!67Z7X8:J`[J +M([&KG^.S(9,@-7P&O0I7Y^7N;!,NC=_R;)J$CD7IOF-PEP^-IQT`((M"-R;\JXPN(<@_6&._#^Y2J2%'G#ZA%:B<5 +M8\BE?0$W',1>Y5:C6/Z[TQDXPU^CI0-B0S#(\:Q:UJ[`VHAAU(:ITH&K"/XW +M^BB/VX[$,G\X;N\^0U!/.ZTTF`)#A^>G'D9GT-2/-T_LK=A.7[P\.=B06QAM +M`(QF)P1[P&B\GK1"!NR?F."G\;G@K(A!SCT<>%9=A`#!JFS.M[0+CP(`F2)'(4O,&/A8A\9F +MW2!R^%:#<1$Q$F,CO+&@+"ZV+0\J,5H6?#[J^`$R93!]H.!>$OT.0N&L`&V4 +M/A[AHBT0_KA9O"_9D_4R697JG(AG?/)* +MCSG,Q(';RE7EZHZ1JA>A?7O77G2F6)1SS^GR86FS9#"C,`\;&_T!$!54Z6SW +M,.$,:ZMNA(U=V%D)QN@@]7D[1I*2B@O2%M[7P(2HZYZ#IR/IF:EP:0`[N +M#V*9AZ2@Q<<67*AV&$(56L*Y=-5EN\PX'^E^W<*EH^->3?$.G[!+2-$(P>>] +M*@0<&:7P@UH*2W;Y:53[XNTI!X%R.S;0C\\1%`S327RA=`O"4BD*S'G\HJ/& +MD=*?Y__ROQ;9>4C:P$C_N^';N>S\6RUJO<0+BO5)$G9"@28EME.,#960N<'7E +M0&V`1RY_#K%KR9E*J;K('82/>)6_W/=QA@.Z5TW^BB_>*5FN4?RC9(Q^4 +MA?FT(OF&=WK8VCBUJ<6==B'3^0](O3=^_=&WA>IFEVMW4,!LM#N.&1;R3AOO +MP'5VAC".)".,7=MS3_/:DV1/V%_LX5^'U[8VDS#7`;&A%%+W!>2Z>7^OU>IX +MXY@DB7E.@CXSTI:_6.FQB2VF_QM'"EWEO"7Q4?R'+2!]5)KO@SNW7.]HM!%M +M$]84XVJ_ABK5<:(1;-8:I3N#=J<44V$K4%$/-6(?Q.<^LM].:QWQ31QW;)>* +M6#'"`/=9>J'1"D7":)SX<-J",G#J5`JA_7$[X6YFO`/=4'+LG?8QE&Z*;+J6 +MN(R^W<_+X3![(869;A^#!;AC:'4!6R!^!=1WE:T$>KST@I*[TC(L4_OR%59B +MR-*;H,YCKGEV6A)F:VZUWY0XF4WK$$>!YV+-'Q']JU2^,8YZXYM]5%G.F`ZR +MU\93N0!PQ@)&.K^@:YNLC>"H'D\2R$]0M:[R/E\N,Q6L&$PP'>HV]"34=;<& +M^XI$LJD-'S3"`<'@14-A9_5.BPUJ]7%N+$M(`C-?IN:H5)TN&7 +MNE#Z&.A4+0%;4*RM%>?/+SI<$KSHGP[LE5<2"YZ5KM6)\K8&HA5%X\LF"8^J +MO*5:FX]Y_AK(8G/-4$AS#@*CV+!4:1%`[Q:&56O,EP@ +M(RK34=!&X-;\+22BXT,R3:P@W-Y+GR,WJV)H_\8O/4`HOE&3F'8='M!3#5\D +M_AW[0Y5#0[-J;XX2O?3P[AI>/.K!UN('B$&4]>H[3TCI +MKXB+QW']):"($A2J^3?D-,&>V(JG."SB@%@04]X^I-)*[^3=: +M'`(\T;`H\3-J`8RK-]?2&&Q08BIW!6R,6>78),_P\\RCR,ZA?8A\D#+N +M[!##\44-J$1)UOR=U&O+A_)%`SJCR2+?R2S9#[ZAJFS=]H#RKCW#,%T#IF#D +MVGSWAQ@.[>5C;7ZTK;'K&W.&$8YM98OI;A@I\BDVVH1$!R(BIN7B4_."O%TP +M54@\9]NY]EZ'S\]>*K'QPU\7_;""/4X)K,J2+P-GL7Q)]44E!\KVZU"8E9#" +M;U?TA]U_:T^J4UL'B"T&LU+&*H +M5>M!?)R4A+$)X*Z5]'/^=/L/K4>\+M.,#ZLSP05I2%VHI3\KYX1"F)E)EY,X+ZD15# +M&*A#Y53A\7)WGF_X5@H3NPQ1A3Z(5(R5H9$#`/,/4H4=Q6DU3(>TB@D/^RGP +M:?P9$WBDGM],KR=\5QD,Q3@33X&<[GW2\V#AM"5V]YH&\39&L581Q.F=''1K +M).DV%$R'QAIWV9NC2S<_#'2IK&Q(7*,HI#9.B_**(AV9MJ_LJO_H[=%J3-5I +MBR<9R0C/MM17'DX]2L[CCG+:YA^0;FLD?;$CHZUGJHE*HK)/WR\!-)III$66[W5Z:*- +ME-]F.MIR)W[X63SOB68@59T#HC_J-+B+A2OWZ&HVQF!$3+I(]_BT*Q'*'5\7 +MV&;:H/*YG!"Z+F=:SO1"4X,4CN9@OQ3*4<5JI+7K+%^-.WGQ'Z:!5T@H:J^!"K.D*0FAUEO0"0T;62C)`=)6 +M&R/D50N3"C_%T'ZM3=W0B]RCF3MJ`NQKZ'*;RWF&6%]$VYP6 +M$$GHR%+65(HF4X+VET(-V&/]#8MLIDL,NSJ)(V`TBT0B# +M&H[0*IJ9G[)\+'.E".`-_4-8R?!KUZCU1X-=AORXM%F^C>.'VANC:W!:N-X] +MSB$--_[)Y_B_@U_.P:FQSP,'G,@^F^"E$XF;^Z1L/NE9)QQ>2 +M)WAO7]DLAHV=PL:T#]"_82YH`@D*J$T`E]KJG9Y&(C[J;!>@&A659Q8O9ICW67K([35:;1E:QXB\Q?-)1CH\LW. +M6K/7.IPXX@IQ#*`9/3IR:056;7%]`4IN+?DO$!/9&8:)='BQ].VOAX(: +MP#^O+Q.NX!^D.:E9#S^+'%"!R3379K92WR^BB*7`RN8\W%%)+[," +M]!EL^W[A,,?RBP^6#F5@[K1KB_]1QE]4UU%UG2W]5YK7RPPK[+?Y>E@09VT( +M\+YXJE5`*PMAX9@E6&NKPD4I_PJP"IV]GO.<-5&8MS!^KG2V/;HTV[+D:S,` +MX#NJ+(9]`!-UHIL`LNN9L;;9"^<6IU[V7E=5'9"BB"A]4%2:'>SULUCV0-+/?%0UNH:^K]!%A6$EYEK*7"!_X5E?*@C +M4'\[WM'1YR,BXT0/"$TVJCP'\6>SOJE\\$.)^T/2J^:UPCDVB2:DO=C*84`/W>)>9Q="2QD(^)`. +M-?3K"&L[?F5#D(9+Y5EP59XM="!:OGP`0^;/E#S**>K0#XZPR+@D5Q`P4(@0[\'+@%:SFH!V57BHZ5&BYD_D4999L[!UZ +M?N[+7O*FM&X4R]B(=%1!F%90]%*I_XBQOCDV]1UJ@=@GV-3Z/,XCH/.8\`R5 +M#X(4B%)FRTA'.W52DZ%$5UH/<83.E2'5.M>D`C3&HH31C7MS>1+7*%R^:>87 +M';1"E?"]F0"P9T*QY?W!"/_8UM#*>'+$".W>/$TXVJ8G3?$4KC#K$$577&0R +M-ZXKL(\A&4ZJ?X5KUW%<80O@A,1AHXH;;@J/8C/1W*Z,%1&K8@1X@+)Y.;F) +MACM]]-I8A'?H9'EHJ:J$TM?."'&QN[J5K7GU5R`R[2YT._(QKTL6ZR`R]:7\ +M350>F'%_4H`KO!9X]R/>OF>#J!D<[%<\*2Q^C!5T9.M?LGR*T_Z"J_T[IQ>Q5".9HG:O;K#3CYN>PH?%%5Z6,G$'+OASH10'.C=D(C1`/;PKQG=KJPZ,2Q +M\G*29Z:D_SPJK@'^%[%KDXI?^8ER8CLA(UM*^N5(8+P\,/`DI'&J:U7V8"![ +MD]B#*L[8EM2Y[(/<%19-R"Q=H)+5EUSJWVUFC$P1-!+HKA`<^,S_1M*BTZRIR(`#/9F+X;O;%V6V0D(PP^:N(K).8JD\J%DW^`#+I>0[\V!:N:NE2= +M5ORW!K[R^O?(CK:[2RI-QDRS5X:=!/C328%(&<*(W"<0(,54.22?O6MI7JT0 +M&ZK_CSC2,IN5AYHVO&J7'YL`AH6%R),;1\0P"?UN(ONXCQI(B:-T\T*0V"D, +M;BAGM;2J7]%U5$3;-:M?6^"-#J#9L&(Q=XH.=]TQV +M9C\2Q:/#3GP^PYD`)5?E&$N`\HE6%/`P`SF'D,)#N]"RLV-4('<[G],>.QB( +M20]D0:(E`9H=6&HH@DOTU#9WC&+5P=8D5)7D77`'3>O&<((UL3E+V+6BPNOWCVHC&#'G*>VSC-[U)*.;X57T[9H_"0]UGI>*>X +M6)#_DVU\VL.?2E!6^_K/,?WK:#"[ES/2!4W382?'JMR-^C_JD4>Q0M\$7=DS +M%A[ALQR`8XV.AP&@SBQW=M1=2U\+%Z1D>9.`2ZWV8C((",#?I4`4I0V!.=Q8 +M\P<(&5TED5K9!%SJ*VRT^9VB<_"\,8<@91CN^8-AFLY +M"%2CX.S8"O0K'^P+,\F[@6;L07WTJN/;9@I?X6$JDHKHXL(YZNJP(<#P?F[Z +MCX:@A;4_VC[W7V%3"?@'&YUC<`=X?Y.W3]FZPV:;-"=3\M^RAT2V(N=M@5Y8 +M?%021ADA3"FVKSU*BM5FSO/,/,B,1.0Q2FH+)FM.Y]#,FN3Y+5E4O-'XA,V +MF,AT/A'HDZ)VY>FH):@DA[E`GD6WBUN)!KKI6S*?`NEI]]OO%RD$QWM2[BU5 +MBH(DZ'%%-ADSG`6E^^(T39U>KOT3W'.;A%L(%GYJ0E.#9O30[#-L0HJR<.&\ +ME?/H!DU0B^J!]\]YO\O6,FK_R^1N#;T%J^8U*W5;6=*T^[3XBAO/92<@8CB0 +MEN+<+(DM#HW_.`,EH5'ZK&(;@O"6^`O&^%$?E0>4/&A]NAOP#B-P>CW(0-@L +M!R4:+W:0+F4?"`LK.)[+3`0OLSDY""TS[5<<3%?\E,9NHR>Y.Z9(]L'$Q]%I +M'R,Q,QKH=ZREJZZ\=NSU[;5S^U'`TP/='F(:.#MZ#8@[#[8FF(H&7$N1V.AI +MK`@@NX^\R3/>/_`+Q.KGIEYL3M&X$#P`_S]`OBQJPQ^Y'#$X5KL=^N([IS7F +M.X%SS8;@QID[RA9313$LJ!Z18OSLKD]/+#%.*1N+?*(S2""9P'_P'UK" +M-)TTG3Q.U_AW)-0.<0GS[CN)7O5)]&1I\-6@C7#6+)I4Z,`=4HX6!(N'YL`U*=EH7 +M/0U(2?V;:-;!"3VV`N6+Q?T1RXNKMNK!#)X_E33UZ&=^AWKNIH9K8=WK/A]R +MY=HCK"U('21=CP]RW7O+.VP,K77*7O30:08GEHCQF;D6_(66+OG%K:IB[,;Z +M%$G=M"@:K[OWPO]5M-TR`=WF1F:19B?,I&E4^MY+?CZ0"R*I?UC48IWRG!^= +M"?/0?U":XM8/J#G[8Q8,<\7.`^-AV_T],*TW0P5&O&C.K=V>(=W`$Z\97!6: +M\?2R@#!":'2!7IF\H$#5:OON!U2OUD4BK2W(JG+IP42\][.0E55+:MP2N$;< +M9=:]]>705DW">4*NS>S3I+W5"53BYLCV=-**1AQVW:J%T%=@]DJ9Q<[[N+\X +M[*&;5=%E[$5R),]\E&MC^[C$*QY$' +MX/9&=)5*47_?UM3.[40QRJ;'KY)O=_&C5=PF)5]P1<7[=,J^D.7](8$Q*\#` +M4D%@3<[E]UA;PV.9&3X4T4HE!N*3"_9CKM/NHX +M*D(:R\>B%%=?U5WWYIBF?4WQ`VV>ZDT"H2#7H',]V.13;4>A[\5T%Q`M-R]^:R[]"%^BI +MI_]A_3%EPG!V@6R-1R40J5%057&N=>(4QR-WB@$TX86JG2 +MF#B9Y71=J:PP-HD,K)VGW<)Z=>,),8*KC&R/UE*@E*T0H0'@\ND]N=AZJ!K:%.OXA%<`&034 +MFI1ISC'"903=SDNO&%@:4C@"2=HN2#=9>R>\:YW7Y4AS)KS!8O>N_:IGJ%9O +M$21-P<_!4#\`R9\:_%J,Y.J\KL#ZN,642;&46+>7V60$J8F>C*5"%=@^@L@W +M=#>A\^%\ +M"LV\;8QOJ"D)2.;?TC@PL-4$&3):*B[3EC;8N]"&2VH+"+"H[5H=J7W[/+T7 +MGH,#XMDNFUG)S_M12R^40_!"LOYLH-FH(W`I['*E3"JCFE@?DU^+RS@ZNO<0$Z.4(8%*0``D<51\W&,1V#K +M6%0I2F1!4'Z#@`8*[%%$V!1"\Y(A=BO<5CT;F'!IS>>\[C$!FPGP@`%3O6K9 +M!P%K9PX(QUEYS))5AL3*6$B;Q$#4[\%2GL']WN=*T[5QK]28G.K4[?K2@0UF +MA*^LH1N122!I$?+51S4CQ#VIB9&/W5@C&M5#L\T28+(51E^<70KPC<:Q2% +M))F2K\?XM*RO*DLX5&5*!9NEM]GBRT2G^\]LTZE +M%".P2^*P%LI189L(!:JA%FO1#TU9\CPTD5&HQ12'3P9;_<>`M3=>4G_(ZU?M>L_0T3>SD"HDQZ&);4"FX +MB"$ZC,+J%(^X,JT82\W>,.SQ#BH[W,6C%`<18C@3 +M0T\HD@T*<7"TOTU/F\Q,0P!6WW62R&TDM,8Q'FRYQ<50"JY_43VSHRON.0#-Q@&5H +MUYP.E$##%.!XK[:>8X1:OK#MHG-W(I_OL+]%,M\()"Y;JH:GZ]^).W6S=B_P +M3J#=1NEM41#<=7K.06:"9FE/1?#'%@S,2%U:\'@N+>9T3126<=P-6S+T.]Q/ +MX73UI3X:+`8>M:`%;`OSD\;-PQO!(X@I&[E5Y@],!.58_OOR01%.J11+R>WF>IX?^TQ7/ZXS&`PL`EA_RGV_1 +MQ8_W_U9*J"H^&K_.$.Q`DNZJ@!/BB0JZ21B]V(A0R^ZL$!M,X4QW%D.YP33; +M0*$OS]6`=;GAWL$O]BQAK2Y["2A=F)!_%^_-[U6.!\?Z$%C'T-,NJ%/`!X:V_8&CR(3>K +MLK%#EC3822.D&**+^0Q\:O1VSX9IJC:0/&:(7`*7WK98*%_\?MPXY*M$S(W" +MH33G^V.++IYYR)"7'K)A.L,*XZ$WR5#`Z-%;9^,6*IC,Y0Y:TTN32DT*[S[B +M@^YTZ)O7&CJN]:,,*&7A6?.NB5A\"$P8P;I$'=U??!#4!DQSO(8H9 +MV>A5RP)/0[3V`+$)?RV7)QMX!W">$+@V11L:G`9-^M4N8&VQD*T*D6GI3O)4 +M6Z4BF'2R0,(V5K[H4=0:-B5,XN)S- +M[&K#3Y^IFMR0/:_A%4-UBJX:X`/?[,$$8]6RH_=IH]"7:A;W$`521J>8DTE% +MXL$#SV"M!H"/GA!UY$>2IV@^=]C;5G%/O<=$RIZ2+@=LAD$83KT?/5MB_2[A0M[V +M4G!I!0DGXIK%H9G.!&PRWH7G_\7ZTO[10I*E3%;9BGNI[`@F)V#2J'\7(@=% +MVU:TO^O3"KQ@G1XQUCZB[?TOD3.#-7OLXYN@G$]+WXNS8%XXG0E-W8A:<`Z/ +M?`$@>J`UN5HBF:84,/=6*?!XOJA3A;)Z&?^GT:.'"X"JB7OJ?\O-= +M_9/N>I'ZS1\EA47>'[1_D?.O9JBW?VER56%Q#+F5_^Z9=JR^GDSJ*O*>%)P& +M"JS8DY:)[;1M,809'KN):K[Z)MZ\]B.N&]4([&:ZE($)>;(\$*PI_Y1X:`M+ +MY*-I-"$!P2290O$NC'"`\J;\W:Q=*'R\JW($"'C:S%0D#-;H@HCN"@;Q`0+\ +MFUXS>/$Z&=T[]E2Y*)3@F4C*)SM&G2@1/1_Q@QGX-">"*,:#9D<:#D0_ESF% +MGUD:O4Z274J]-QXT4GUDK]G*RZEIC0\,%CG"I"`(,VQ("I:Y>8E1E6\/@78< +M^SG)\;(#"=DMR\?)\I1O@EO&QQV^OS:]/(!J3[%LGNV5UW'I8+7\`0AW0SF(1J[6U7L(3CS0O6MP1M[P+ZI7!;49H)WDSO>93AA6'"GOT`$>N%*7BMV:>JZP +MPX04M"']*'9>8R2Z!^`X3%-799+H&2$\N9&[=AR23;#3M]'@:Q!K;"7L!IA/ +MKH(-/5-;G-\BW,B^%6KT0+&>^I>'2<@D68Z"\G&^2?D;Z&[+?`W_7H=Z,%<)Q!*^,E1DRNT^VS&++K)0)%3#;UDUSK.P1"$7G!_(VMQWN2IY25-NR%)&)990(5W2:((E,&,O>= +MMV1/)N"0&>A/E*KE%:X'F\G0+V?+[".R9\X>:$A.??*_.=/L;@Q'BR8HDQ)^ +MVI8G_0-(X==4FM30<1*;N0X(<$J9+P"-5NPC?(+5Z!81A_"-O#7!,!#=A,$/ +M+A)QX/_3%2Y@DK*>K0Y118:)UAXQ[7!;9_635-SJP.IA4[7S,8@:O$8BMZ1( +MSR7J(AQ$$YWR;.F1WY+P+2FRKW5.0%KJO"IDE%PH@WIG7PM%MU^PW#$CB=R*OXRGD@I:['*IRE60`.1./XHS;HG!JR)$;N4I"S7 +MB0?"+_5JD[#[#`U.?_G67T+^VN!W2MLX)97'!8C&GC'FC.7V:$B/FD[C/DN# +M^C&&_'84$L27]9*=>OL:<`0%UI1P0B1^*M:^#W@X-#J;@Z1&RL=9U68)F/^3[ +M_>P63%?>$-\B!,D%P>B6#4CA2$;S$SB@\YU^.[==DH/.12?K$&PNR6N#R+JB +MH48DEF)875TA%^/WG#$,[X``4HB1S1*U2.F7GEWJHQ!$(#_D5& +M/1*EU0D@[%;J']1%S:*'D<\NG*&2W8AE_YN(ZIZ`)-7&M>]1.3LG/E$60*74(RW# +M:;F()V-JE>OZT&^_*'G$MUHS]$.OC-(^#I@6#3$5X!4H#D*3V1=*H_5SV)D; +M'1B[SPB,@`RXMP<=-'B8"@)Z1I>R;!OD_T=R +MH?R7D4K"TVM_D;GQ:T?:,KY!A-BB26DPGXS3B&4,E4XV?-H`PN9/0X:D-2O9 +MK5Z(^E7#F4Y"G10'*64D!^:?51?$H?9Y5[T_\Y3GRN,\! +M9V-GXHG:`\9^XVFG#1FRB/U*B[:#'B&G_A8H?.U>T1H.<3$P,#`XI:*8(WTS +M'.MX@ZZ?\)K"&P8]!3^\0I>-ZQ>"R!0)C*GAUKYH]]R$D@:RC[O6&",/WX"< +M`UEZ*M`6C-29(E2P6HX+"D%I+L(-:_6HK#?WFW&,L2HNY6OR?L9^6NXS]'=* +M5.EL(_"4<6S:IE7T7!S^?#<@CG?Z8#58G9,*4I6&4I$M/<2.1LZ%4`S.,]A+ +M8P[R*7UCL55HL!J1'"_N!J:YZ37@>24HYN2@RT8:^6P34+:QGOFD'&4-ZX-> +M$"%0"+^!90R&Z]I^7$X+"BUE(2O'")U[9Z@9UE +M93%`NBW;H:N'O'T:4`QJNZ^^*96%,N]-47-@S>C)'0AW^[`NDF+*,1M`MTVJ0K3QN5:\ +MI*5"!C>%4:4Y$*,^*-KZ?N>,*A%8^B7SVZ%+PM^X;8>B\K>T"C!+YP@XS>E+ +MJ=B8*N8)`GEN&@G#IOZDHV1,AMZU\)L"?:2^Z]7SQ)Z/ABJ@]?957@=\]$Q/ +M;_#W4_Q3G^;G.#$?=\X:]JILWE03$FY)70*@)NBJ^A[*?,?1HN62Q`8%WP;^ +ME;O@O=I,2W^XG@1&1P;R:C4@]5`2!VTLR3;/%I]B^Q1?H`J-?J("EAZ\0:A_ +MF)BJR^[I_]W;?NXW*,(D&0W"#M_3_I\G[!)@8?!G!3W,PCO+76GMQD2^Q,IG +M;15<%=]T>M=Y69V_YI04&LB1,L*V[4GW3PQQ#DSZ3%C@4W"4F&U$:5+QH'1# +M[OC-KO!Z-@GH2S#&2V;$,R0VKT*0-U8-*7I0&Q]+MRS:/)L=V@0O/#-8>#"1 +MH986O*F)8>PJ=%$U+F,LOX=QCP##!>6;_ZPVOSDEAS<R54`E!N[ +MBML(#)IPU\^B`:7M2EI(K`(#"BKH"0O>`JSC"B6EJ-CV^G]6:U:Q<6"U-LJX9Y:@LYT#JL4 +MR^MQ.^B,0[-?AW+V$-R8[<1CZU:-:)>.-2/U[;J`JW_/9`;;+=(\';:.0+"JIK#L1Z^`1(B$K_FW\(41]=EC"/Y]1A>R(_Z+"_R`Y62$XB(,SQ62!L8QVW_-3BK[NP&! +M/N4]1SGL>`RHNR48@ +M842U)0KOZ/PM*^8JIF7DY@&H(X&1<6`5@EO[`L9=;-1?>4B,)I'`S)OMT5TT +MT@1W]V1Y&T#+D(JG4#=/!FR+FOZUI(BA2TLEZY:`!.]"'V>-431YU>.)^H]$ +MR6YP5KD716@U]:?S]/JBU\QNN@Y/>L`7(CULKW&H;MC*5TO`G0Z'J_Z5[!6D +MK&&>7#66OX-Z'R::L>OYX)S4SW;@H]!DT?3!?L:189N/>6O!R`H@M[OH8E=+ +MT(0O,;)U]6]K][C!]#TGK50P)4[M:3DBE".N4VEG(R6J$H"N2;*'+*!?^<,> +M]8Z/X;B*:21I(&NR_W[H?37EZZPQDY'W(^$&C`/335X'=`%BH-=H??Y.,HTU +MS!UVI=^O2[',E32UMT-#L0OSA]F3FC'=F:3Q@_&D_EQ.3D%XS?[3\U!+.^;9 +M"@5H'EM%25>#8NOQ)-QTNH*_U=J>#A48C413HFD0?E5::W?3W;L5_\PVU%=` +M69=[Y_/1:3PW*2^+0+]\T?&;YWDOW`,L8R7^D+"PU,O3T\\NG/W`CJ?M4P&C +M_H!9=[KHL">0;`W)D^RJ:H+BVA+:^I^"P92;5KOZ+VP9=VU`KD04',4KE\Q@ +ML)\DAPY*BA(B$@_/2Z+"]_JK(FH7`[PKZ&;!YSA*VB#>V2H?;[!=Y?.:.4^/>IUDF5OBGXO&!VS)M1F?J$N@A&?;USHE0< +M?K$3)O/@B#=/CC"7,9?D&0$U[%J8<'P<1@2NAS?FHBU];X<3R2#"L^CVM[^, +M]Q'.E(BJ'4_:FV?=&WGJB!DB)A'23#P]0/I=?E +MH4SN-<;)6F3!<0K;;_90I/4>`'4C]&F^>E)56$!9QJ]MA#,8.EB=*+Y\ZGJ$E7$]SCI8O[M>=M@1N[$?@/:??]"Z,QH99/8>)&@(OUTJ/I"'YMQ$4?=X,0D(ZN:=SX8U2*T(TMC?E&\`,L-!)>MZU)U=0B)WK4>SQU'KMS0/R7-%WY30'GQ8LG1D((WF1I@ +MJ[>1\6`="$62QO]Q'Y74(N`=5"C-5)K.9O8$$YD%[0U[S:.?_I4+-?;AQW)! +MS`:?W1GQ"8CD"XLC8T+R!!P6OWHR*@H/U,CCE^WQC/H2`@2"XH-ZRD%'.4OR +M9/LT$>R:KS-(/A<'Q2_-M(3)TY*3R(_ZVJ84HO'@6RHA^,DS+ +M(N[)6D8@\733V(>6+RKV8P3E0XI=&C76*]X?Z0&&PIJTD6<)DGRJKN_5(L +MM9U1FRLBCXK"X-6+W/V[E[MG,Q=I5QL`(PW;K*IV<&\PS:41855*-TO\4X(_ +MYN'H#G=%Q/1J8%-7'>&/4C10>'WAK552-;%"L*GM$8K60'83A'3<4+^'YPP[%L"N4'#F,# +MI;/WQ@7_GUP0:+E@+LKW!'7RG[DV(^B*;B',3`KDYU)8QW(F%+J!T-\&\LT3 +M0/HK:W9G0(;NI2GOX=9))GU^$1!`XYV) +M7<-RTXPR?L7GUR=)'2=9VRG#RAP``T(4EX5##N]+#N+:Z&S- +MF5>^&.C0F+ISY*&[]6ZHJ=J9\%JY`CHKPO1AEPMD30/+B,B/A-95WYMYJ*5S +MVZ(>C;_J9`I*B.V"ZQ_T` +M:$/Q^A2FH6C5=X^7:LY@YA@5%J:0`XC9GL^"KG5KSVX7NJW>J=NMT%5,MDNP +MV$KD"A).VEI^BTWQEV<@CK3MC+G&S_YS\AO2Q:FMT`^+GQZ773R:OV,@>8G= +M&+6Z:4=5UU#!#US"=L2(L;7:=HD>S72%R)8;\F,&G^(]+&*QJ-VVM2:];]/L +M+#>N%U%O\@H2U<4C"0-VUKMD9^ZC_A.B]O((K0[?]I,GS"'&TS[K^DI[5[ML +M&5]N&`'[R5?5D9B#J^EOP>QT##YJPVH8M5XM0KZ[@/AO>;;W2&GWS=UUQ7S! +M[@I"O2T,_O16^(-FJ96J)N['DKX"E?=M#UK9/>^QBH%XQVV7(0CDCM3I,@Y* +M`-Y4K^4R4_0#++==NQN"C0P:E.:G'0N:QS9&*Z2ZD2RQ2F0KU;X8R+>^5D=4 +M.,)(*+.4#,_MV:%ZBI%`5S"5KH:Q3_0C>0AVR9K0_8BY#9YZT$>KW2G7O84( +MWD/0#DU(I;+D7;*6YD?:X[!;D=#B!!6;I3_1@$R"*6#!/UY(_V?/#%'J]ZL\ +MO0MJ,]!_9C.L+05V`DNF^9<$(#)@U:ZV'+T:WX`WWWEDE9LUCO^ZGE[<:#H5",.Q3:0.M5] +M,!M`@M$6>4T_MI7C5UV'=*+4#XLVN1?7BIN3+P7F$)8O2A$BLV0FEAOC^,_K +MBUV,W,MDE^_(0%(YOK><#6>MQTV&0U`G&0W&HTL\VRVTG9+YI- +M$/S.IVL_;TM?2.(%/@XS@L61MNW\VN#4-I%F[95^^/O:JT$0D?LFO=;L$8Z, +MMV1*P18\G)6^>`N7OSPP`LIH*M1M(,_%T@%FEU.SC!*HL,BB."[=P,<8JRFA..]2IW*IU8Y>/=L8[3@^1BPB:.?I5, +MI,O^5Z^M?FB:"G@71HB+";SZ7J>&'@D]#Z^Z#).R770=!K):X^#_%>,B%+>F +MTD^H2FEY!@W;'=YF\K5-_UXW&:'U(P$18SZ1[L=*X/ND$T/TR!U[ZI#E%&__ +M63EV35W$7'3/&=Z>#U\>`YV^Q:@0GGUK&&4CL9"D":>E`0=CPSC?Q4U"V=^3 +MF8B_`4'=A&),7C1D(`=**H"_]?T>VSG/N&#EW_Z8$4>\@J9QTY.\A,O[G63;E +MWV2^^20!K3OCB)I+36_F*:+G@\KE*)(%%GX7>?+ZR%%`6UYH)2/ASE2EQ@$G +M7/YBGT\=(;=&NI_*CT[$.ZY!9/T31B;OAG$3+K^/RG1"7*0`F\U5:S-GO5UQ +M'@.XKWNP3.`V=`A+[CAA$`^T.%&5W+1A3\5Y%S/=D(&@@E+,F*5#!>H32F +M!.!&A.T#6?EOZ3$;H`5T$P-R9+A(CY8%0A0XR*^[Z#+D[=]YK:0N8J4+S3GG +M@?('I!B7]IA\B0KIW`G7*RNV7?.J:S/P8012SKNNRP5LMLX4=CNAP#W)9FT5 +M#=7(/FV4T5F\WC(W/H)%_R6*!*!S[JX]@BHB.-C"@R@\-FC:B3:\PEEK,T[X:XB,J$8@^38@)Z8\].98.;_JTV8N]YE8380$,ET+ +MTH?`^WN;F(S:C)X+':'4EEP!44(C6ABD#_#.R`!?(*Q/X2JK%H6)UQ1 +M$"4L#C>59E33F##0_%(46\]41U-:^VEN:/,Z"1SALDBL,N"3)BU'ZW)0'=)8 +M'?)KEG*SCI]_JRR'Y;,K4"6J*+Q4MB7-.;$\OU1%4>5P7BYZ?,NBJP???^<" +MN+CY6S%VD)IPK?3E9:I^3DITA%/J7>[Y#N18(+C(0*>'^V,Y($&C)HU6+EW( +M2(5)*U5]!)S_=76UA.1;#;8GF!--G_"A+)3F=0(/#';:[35)>%-'!?R,<_X( +M'M+-YR)0A3Q[[@D\KMX*Y/3_"VX.FUH"NV3672]('* +MU5\EI_?#'ED_7*8BM()JA";5C+<]U*8XXG/8D3WS#/QOD#UEY6/IHZ(I^$B- +MT[;X')T&+L6JU"`/I7X6V%[#4;09'P99-%_H31]]<;:WY^A1\?UDM?U? +MJ%WD)V8CB_;S([9=QHI`#!XN:R=L%)<]5)FL[/_W,P^(OW%;Y^J$;,D/J5*< +M]2%S$90<\M1?12-V"2C:KXW0E^_K#2M6W&D2P#%L33\&'&.Z,/AJCEM:DE2C +MWP)5>Q:$[70-J9R$K6*GFXZZ/$:>A\IQQ3430"OJLJSJJ,W +M>KJC>K#3$8OL\<@K=>YFP]'T#`6MU3OK_T1L;CQHQMCU^[[%UR=ZAV(!@Z.O +M$7*WAR0/CNB%@_(*ICU7Z#&IP)R^N(&#@O`@AEEO^Z:JF<)P:'Q;_.7YGOV* +M$S'@O!2/[)!MN44_7>C>G_:P^1C6)+^A#W.%-BTCV((A0!M6E;6!9Y80@D4`DF4'#+_P8Z93SQJ%)GQVG.KOCQ +MQ">T!RDO>,5O%_)`JN\Y@ +M/+CR",&`,@-'J;H&'^S%D-WDCE'L1R&X(A&CC9O)IV'@7`E7?Z,OY!"W$ZIT +MO\1@X]3,-[F`ZJYB!Z:$'F!C.1Z1^&3^!?`ABU>#W3BS5H9[-@87SNX:!<)0 +M-BEW,_?0@^O>L!ZWY1;BT#Y&:1MW*B]M@MM[V%6SW-D3DN+21N[>8'*QVC5S +M&UZ1M$_H1=Y#Z^K/@Y[%I46@'QD(*?C6(0=4,ZHX=Z=;ZI+V+0-:X$98CGMA +M#(E_:`_C&,2IT$;;`,SS>W$-+F>N-L?<`UXT3F,MM2-$VMLR +M+Q-U)2GP?QK(&N6!\^-@9"P!`77D,RAFMNF5E:/2_>M$`R`S +M=T]V`#GM-S0;'N*!>'PL/SRJ3<@R[>'/3?WT^_2Z@Q!+4,I79BW86W1L)+*X +M+_>?CE<1,2ZB_!\[BJ^*SX&$)`"\Y +MEFMA*G"L\7C3KZS*+-CY^?7N@'Y4J`&J64LNLL#X-`GIG3P6M-'0()*A\F$S +MCI]VC"=I+7`)_$4VD@6"4:LP%&X5K+=.5,S4#3*\_Z`YGWGQ:60=!]I)("TZ +M-A6+P&]'/"Y6]W4.65*Q:^)33]A99L3:`)%`_>`,$@%5.0M.)$]CDKBHUC7P +MATI-8L3HSASBT6.7KC5#:?O237->>HG-\7[:RP`Z^I=.Y:#1?[C;4NXF'"(SI +MH1J]3G3HU^#NQ:3)V`"KEH3,B=66OM7JV89X(4CHU8F8E8!9L(2?]YR7CBK\ +MH'"?8>\3Q$;9P3ZIH?\]>?J*MTQ$IR6.%I,<^F=>9=<,3V/BYA-7#]=-_$=< +MFA#>6Q%3(+I4/A]$H[>@M2@^C'S3VE:'7'T/B/A^H'&*;HMMNB2"[J;_;YZU +MX`C>GI%6->-*+;VV*\X#7@S#,6I)"AL/)%&V[C:6-E`YE*M'(I?E-Q^N7NTU +MF,MLM!UZ=0B%).6!2L2-AS?CN[;Z57*^+`)LG/5`$CX.;ZQZW8/(]NK/@M=2 +MO;P]+*NOMR)19MF>(F6\D'&]$D^4K0GRKTY=`=''*2B?@/G-"=>2F.M^J"HB +MTD,&B,29$$'QXY-UL-36I=K*5-=!MGIS_IMS1HT?@Y^3VK=MCKH@/MN;$\*I +MOCI'4]GW>5Y\XXQ*)"@#"=2CK5RS:UF"\B2A7MR?Z$\J]^Z8XMYW]%L6C6#*/2A#$L%O@5N+H?UL(IK=%<@NLK +MF0]QGY)3O@YEBS?!0VW\@YKH2_SX9`1_<7X$%C!,#Z!@O'\^8M5\/YWR!U"* +M(5:9--EIF:.A0C6(HWW7$R.G8R:>PNX2#)]RFPX_L,V2;XT"CT_`I7&7U@`B +MDYVL_VJ'%*7/)HWUV!E3E9.8=+KX246.M)YHJ\_Y>+J5;(FK"9Z[KJ@>X6!_ +M^M%PQJZ7_C+?7;:`.>62SV3IU_DN_AR`)5"O))KQNH:\8DI\5P0[=&3`@Z=&\(WZ!<=!-O+?`[H?W#XPIY%UF>J^\DRW_J#N=K=SH +M)9PWL4YL7(\F3H)]U_R$,C``@EV+E[V2W^_@V6`+GS"31G1OMBT*$*YUD5&B +MG6/%%\*%W*2X8E\`_0HHBU1WYWIL*OL$JZ8\9S>_108*?(IL`%SEKIEXO&LH +M>#_TOM!JET[V`4(1QAG8$GU]Y=%+:3)D)\L]+$@UJ4XB&KC9UT]0[95P3SUN +M![:\VZ?[,P8VZ_@989D3\4GKI:%-@H"2U73YEU.'ZV_X3\/=EW<"64,LR,*2 +M]\U!8_04,$;0^95!,,1H'W),\:2>`3 +MST_LFO"BD!76&9,%QBCN/L2@>'>:,*D<"Y2G-.[W6FYX)V^H@8*O<;*\SY'Y--27 +MC=!G\FNKS@<\XDF8O,Q1YK/\33CG34A4C_@\K2J;K1GR(7SM3/>F6(6C94C^ +MZO*:@P$BU3LQQ;"(E1W)IW0":]9FH;+LK^/UV00!_Q0N=F-HF4B/TF6AL:P? +M*=1K14_%+/M_P]K-96V[KR%[ +MG:`@>WAJS!X8\.Q36V-8>IP[].@WY%CQN$J5'ZNM^U0(8K/#X`'%XTI2T%Q! +M\L:M>"@E]5.AU=N'`Z\>_?VFI+IC&R4C&8;>U/YIG9,WW?2.Z87\*+:RXWU5 +M92ELML68Y:K_W%)QW=``'8.5.&LF%^,=?3B^5WPO[=NY&K(4]8#6!'F,P=*!X4LG/&43X'XF2-6 +M#'P=Y;MQ&*(\[&>O'BVVQR<63'*:&,4ER[,[_VSO"%O]L2_.#SANJYQC'&?2 +MV!.J`@Z[$D0-GK-IN="YTOH[_MT(8/1V-;QQ/1>.!V'"Z`MI^Z*%:8 +M4D3EV<48UR@$3C$*0J.W-O4X&T(7#/U9QZ`XTJ?_(UO`N%U??Z)<->R)"4^. +M;_A<[V1P=-V%243*H222U5%GB;B,=&]FSR=D=S0*+9\4"FH1*;=+^?8^C(O,@K+5-68`^/Z/(#!4@_!HK<8TA$NRK[7AH +MEX_HFH$_Y"L;34V$/RNS*D43GQ#(B3=](ZH@9)]*\?.(P99* +MEJ"\V!/9]Q5N<[<5!IS"HS*Z3!5*I]!!OKT$EP37%F%HOY%7%R`F"(!:'0T7 +MX+I$&G$V_R<7D=6"$_(]?O5"+_$NI&$F0<0KQ&]EE+9:0",(P.4S@=EN!=C1 +M#>.:Y3VHX?#=!$B,4XDVB;S2^VL+`\J5,CT6N70+#KV_?<@2/O,=L_Z]LIOD +M@DY@`DE!E44.B>\BC%=#F_=3HQV[H +ME0F;J'`L;1CQ<(!#LN!3=Q#<\5/$KN?S?V<%S7Y3>69.BB9CTOI"!_K=6-RU75T +M>D++T#B5X`MMB?CK!,C]4M]^8HRS6(R4]N@$TR(DH+B7;T&S1.1A$$[GMK() +M<8<#LHDIXF@?U'[12].]?OV25$]C4ZJR>+"AYL*4J4=\8`.J`4IS9J'NYU[& +M"7MDX`47HGW8[IY=NAIN[FCI;$)D'/2:_944#BOK/`DW,D(3RH2H*Y$JS]/6 +MX)&;C?OQ2%L:PZ8X[<6TC)JE`?YP@#4N1'/>N^-U&ER\`%,G_&8SB\A;L0WS +MJ6SK)B8.H*/FHLCY&('S8$G8`,/Z6:SE;-#*Y<82[C,BSO3V8('&82L2'1 +M^/K&%, +M*/HBD@H@J.T:G(?MK$)(#VS+,;*-H^1Y@"P4H2KW\X9-(?2]C:W:S/,_K6G@`0O1<4%GXZ+`U==`Z)V1K<$P5PG-:XHFMKK\'PL_6P +M-$@Y6E12#;0F*+4'JG,UO>^H>:\BMJ>ZB']L>_0D%:!N)@..9-;`0DW1:E8< +M'VYE?PLO;)G`FD1Z.@SGZ,N5(&VJ?:PYO$G?G.*<*A4EH=>-G7"JN1B)^;-M +MLO6:7?7E`;D`4Q\'7ISADP(!3HTOP]9)%AWNNT+9V(&RC]*1)%^DZ?HR2GJX +M@V;[-\/@M<3U]L3*<985&8!3.G)TDT4H<[QG^&D%N[(]Q)V;4(S'`5;I]Z$"5-N(UIIY5Z?`II?>0#; +M>A%D)[\&);8@YME:9]$4CBU3UJV;E%E,:O1:G^'9RAUD'PG:-VB23YQ/I3RY +MA[4*[/'9J$XZ+)[M\DR,1UP$UJ:.SE2V59+=R.7+K30$Z9G%&3Y$I,JE6B/[ +MMR!H_;__,G:6#:WOA'ZK[2E?4D#8;GK)GSWF^LH;D2MJP4>9;B*O,RUX"Z0F,QMJ_]?G#G=`-4W/#@";$H;E]^4+GED +MY^3&WX/!:'DQ!-@0%0/!0BW +M4]2[`7O\B3=M8&S7#T?"(%YUS'>S_TT19F%ODF>!C3X$[DUEE[]H=W!.9U.& +MK6+82;6^GE<`*VLPE:YT@.[L5(FG7$>/;]5_^V05E'7E@&UX$T;;0OD&+ +M&%#_-4ZBV'$0?6XUK]X-Y:BFA1D9H5(WU$^F)5!5)2K^R(B]X#/-]C>BEFT7 +MI6?AG=*U:L2LJJ?6]*8&`:I+2XQ@8\9`Y6PQ#K,FN@5]H93WZ&@5/I'Q5AO!@3 +M+4(VKQWN]1.W43#7UM?81->&_27"6R*^5=:%N576X1FZ;CLFE)S8B?EL/:<2 +MNT"[3,)+OWI1!94]V#@=CJ4KV8`8O4DPZ1I&`.WY_!GIB>(Q\<\77!E^V2CR +M9XY!^ZP6^6Y@'[RW:I-[H#A:]57G/VWRO_6GV-'7(@/*<-P4_QX)H +M?<>2X?F^>.NA +M(&AV"V';$B&LSL1CZQ5.6=I%;$]:YE%2 +M&4EG[2['27.4/UN@;@HT$A8,=A-0ESB.PSF],!E[`#,?K`SOA$;C7,V;B`!A +M;("?%H.X<4:F7O'C@AI04-IOQ:AEM6Q:I(52[YO)[[FD\*M&"1D$JN?YP\.Z +M-.G%97Z!64@W)6=7Q7F>(`EPY"&H`W.C`L1;T"!A16:TIW/1H/$Q$2=!`4^R +M\^JOV9E3AIV7Q3?N(;)LW0;S^"=MB;)*,^$")` +M+T*)=!5?O4T05D9Y25\'FP+0ED7H04A>9U^(R`T>@0N`7JR?9_8./_2ES]QY +M3898*WNF,_.X80UA34$?+`F@3FWY%FI?+X$KB_)JYU7D:$(W\9[[Z%"6!^PS +M@J):C`)0RS*^'R;8YI3$[2*;\AA<'($Q!14NMI+4L`)IVAWS&6_**007K3KI +MP,[F:%IXS]VD"^"8+>.S +MM@U/JQ8A/3SG$]+%1915;MPBL,[$";"`44..(.9_]@*L16HG=%$#2[/^XTGM +M?$1X1UE`[;!3I#Y.@:0]S(4MN`%>?.L?3$@"K>'2!?G9&`N(-,EE@[BY.P#" +M9\:^%O3L2!0*P*777C'X]JB8$N7DM!N*.'UYX+V!2?&8Y!82Q2'@-WW@6 +M%Y?TSY)M@+!J+[(0D5W(VW@\/1WY0=X*&,252`I\'7RT3IUS)@LAHBY<0'.S +M.*H,@IBBLYAKHI1^.9_D&2NHXYCT?(VC]LBY[CMZO73[R5FG^+`S_%2ZGUS` +M8`YE=39QGNL`B)46?W7W#Z@+H\!)TFK%^480HKM[?RP2 +M^A(S84Q'MJ-91N@9C$S]^/F'9A;[-O?:MQDI^!JNR-5KO7G/7(YPIA>)X+C/ +MO*"%M*]Y^0ZEK]_,MW79&(G1!B<^P=F@.&X(2)UIGL%QK[AVG7A>&=R'!Q\< +MOV(\6O7$5OF6MH;NZV+GBFJE8*VG-8YC6P:+Z"UEO]^I>*?[)]6D4N-50D41 +MG&U)Y-LSV=^5I@KS@/KUWA,Z)(<$YII%E:J[K(T5/]+JU;VE"&"[5ILVL +MM2D&SPN_/>4BAV+\GKK7D_X?6D13GJ=GU.R:851@AM7EG%HC=*&Y2.M,;LW7 +MJ)G"*I,F)A+18FGAGH:T\2B4N:^4ZZ%:ZY-:>VGM"AS-]Y1[%`?!?,Y8#6P) +MB(6Q>NYM$8(XE>@$<-$N_)%!8IAT5X-T%*$7R(\"[U[,(/IB"ULE!"K;"(OO +M2M\C]\1"YG1Y'A(=%98&2@#6GZ_=^%,9"2*NV',Y,Z:%MT>6ATK59*:4Y'=W +M@WTIEDW!\^QL7U<,L4A*]R!'H^P3`:F_,)NVZL3^)XJQ@NU=CU4;IGYG4@*@ +M@^FP'@*2%I(IQRNQZMP!PX]P\>$)GS"/ +M+K8EZ+U__S&("-.:01$-Z<1-VY +M'R@?T1"*B.+FHMZ..5WJ8O82^Q@;JM!''^QV*[[269T`82H#ZK@_]B4O*#3Q +MG&\<3>BZ>>A<66/)/E\2EB\VCQ4'K[C2(QC\S/OD<".=4;!#P&+0+667_JN= +MJ(>_VH\DTE^WW69;76WYM\&7L_K6>U8XLA1R>SDMJ";>X^R7(G\PY +MVL^YD@SAPYHC`O`XE;M48ZD&H9&D&/;Y)]&^0M)36HJ\->IDZ!28"3/U\)1. +M?RI]?`N6#HI77(0/@MU#L(&[14[\,6:NQ](8=2E4(1M$JU3Y(EM1ARUITH3S +ME4>">`[O`X@!+'8HCH=&#Y)9H:.*5D1HS]1A-.V89C-VEW()3S:%B)AS\]L_ +M-Z`< +MH9J>>R7/$T0M*V1(@F.3!U47(J0^OA8AEGQ`[8&F8T<6AX7T,K_V7H0LPQGW +MXFLW?O[$O4+H*BUKCA\)NQMN_52A$LI&IU$^_=\.KJW$F^KKEH!UWEY@MQ-= +M)C62>ZOC?M=U$O,C>VBZ4$9@AS`1!B4,:Z?[?GR5D20R,ABI8P@^3SSI07\* +M`]S_$:6`$2*H:=H#02JTBM9XQVSMK*%F0N-TR/ESZ$J.(=C]O=EJ[B`:>?]- +M0V#QI`;HC%3NYT(V3'M3>1YJ*%1R/==`?"`QGR"@/=NK(W[L03CYIT7-B-#= +MT@Z'V^5.<<+8RV%'OG\B'=VF=!;"%"57SF`BCW!)XBS2S)N%C2K3H`+@+Z&) +MT(1=06ZR9`0!L8HRBPMRBT>T3^V-0KW<#B5\GRLCK3A;Y(/\+HLQ7UPZNQ/$ +M5$A0ZTBA1P+#DH%[4YVQ4WAZ:9H-B:GVF6D`:H[2SIAKV3"T]1**[C'MT;/5 +MSFO)5*:(PN71=B1POC.8.MW[H9*"@(9G;F`,FM+1O>RPI"F_YPW+RX:5*FI: +MR^2]3#XO+V0\E"^.0*8XA8*59V++U<9\_6"O8VH@SF(7SH`6`>#RS+N","I/ +M[1_I4R_"++'_+N9TAWT6N@8,O(<4X.Y$G=0F';/8Y%,'9X_Y\5H2QG?^1(%K +MB%E:GC4R_XK.NL5V2[L:DJ)<;R$*4]1.+YGE68?,6[E(P7G +MSS.G_(Q+CJ(93QPA%0[S#\9OT81R-;-\:Z604-X;DW^@%J"U#)MU=J!XD>4C4Y<@<$H:.(P?V0\6>,?*/> +M"(#[+:=0S),2G\FKD6FXQMAC9+2^]-+RY4B)R)K+O-3(^.\"\RGN"E#[7;JD +M`5VPW0`Q7K@:CY3M+:57T:)X\QE#?53+3822BF,]2 +MSY4Y*9$R`<_"H:!RG?'Q"A("';WI]@2<`[PI[W@P=A*Q?]U^-#^MGA(;LZHK +MJB^TL>[K>KW?Q.+,K'`S=J_WESW$2`>YH8>CE,N:Z\20AF;M?Z19B+\#\_C! +MFR2G;+B+?1B3@AR'9\-FOC-GR"AB!NF(Z5:1*E\>RBO=+7*!_SJ`B4NMLB3Q +M"@Q83,590#6MFE87Z\+2ZW<]YWQD`TA\SK@P;B`LH1:=#*4J#M^_]PD_JZ2* +MM.V4XQ9:4D=F%^%V]_:%%=LAZU#"GCI=0DYVY`D4R_=)&#-F'1[R`N(#A\-G +M'4B$#(F+J+1.24FAEYJ(68HR":SCW`-ZFS$,/U=SO_,6%_OX(U$6AD%,D2`! +ME/L5%X:<)GI83WVU@9.^-DK%^Q^7?&;X8`W.""+S0T>2BM:OA/,->P.8B"4O +M=F3(Q2?"==-H(EUP[[XI_"ZCS\$[ZJ-IC0`\5>8]&_B`>B7Y)<<^E!J +M2,!OD(*/OC56HY@XY@BR0H)L^_M-8T'@.A7992/WX$OA"VY&(CG$W2&4&/I, +MSB.]D5A2S'0J`YHU&U/2U3C$C17=OWZP6WI&4]^MDFO6#W),FC"M0^+! +MIB%$FK8H*KS8KA_Z!X2-B'!G=!H5YI$;P]&G,0Z?_I$4L<J6P$A^/NV#E?%K;#L:&U7[D:%YX +MDA>4(I\2Y@Q-MP9@G@@5KUWU[&*$U$#(F=(+WV`SS^@?PC65.G)).*#RJ#Y. +M85M]_T0EXM20S@2!^6`N8<+6'3%_2$PMT'Q#Z5\=?#@U?\;&W:N.,&7A^>#+ +M'P?YC*_H*9H!K2EY)$(@06-=%F0H7`5?OQY*_HV(I&5OYHLZH`$,D!*6>!@=:D3#67,";"Q@N89?4MIO +MLF,R?'['0TPP^VK#O:9]@H1&K1$E/)#0EHXZH[YG&6JZ+)0MEFDY#C@1>7TA4D,,+_C +M!1+<\S;@$FHJ`\CQ2*XT2A<&@F9M1O]Z/1GG?HL`VSY/(H[9(+]E3@;IF9U_ +M1$$8[K[*F0="Q'_ED/+[%S6]BX$"Z4:#V`T)+0WNI^#S6`0BA6B0OC,%+ERQ +MOL;T0?\-N=[%Q%TYH+E"#!_@T'L%O8X4=Y5$F&$I9Y4/[M:]7^_G13J;'\&/ +MF<=BY.?MPP>76_O!!"ZW2%2FX.SY`V,AZQ*#6VG-+FG`?)@L<[$$"\V!+O6) +M-Y(,K%8Z$)!\-R,JI+[K3SN$\B7[0*JF.'FL.)T!-O9L:6P2.4L4.PVO:"^4 +M]YA>/]0?^3Z;"?$'-2,L%3:9?;D17YG!!TT?Q]1->RXS6M5'."QG?9NNO@V! +MXX;S3OV`R?I2ANP$FU@,-%&9BX2RJ-*`@O3' +ML+R/E:N=NV7S*-WY2GN6H4QKH9YD8"^5/^XH3X7>I/YO%CL\0A7KR8RI)6BL +MPP.5*AK;2ED4\M*_M."0`(0-C(3%E#NA/)XNR9R!F%*MGA.,FM[EU&>RS3)! +MJC?/SK&[6V94WMTA0QJ$_X"_/_T:YG>)QF3[\+":CWQ^[XO+FU.#,V[M=]_G[Z".PX@> +MGU80(ATRO5Q+$":A^B5OPD3])I%@^[VV(+^3-(!-S$'.<,%S,J`=Y\>J"`%. +MP]G@/G=[K,6>I(5$,;0$`T-CB=217G:*7W:TQB_&=O&X1HFO8-LS=7^P%MZR +MR@Y^,*,-4B#E9:(-U +M(RH8#R`SZ@.8 +MM1M`-I2Y]&8Z\72$)'KP+PMNJ@:,96L/"K*6*,#,ZX%_N'X"68+610O"&.XJ +MR;Y.,^?E/T$!;]%V;O;#B-\3XM9&^B]<#)EBN$.?-SQN+8M1X)_]DUI(=6G) +M9(8V[JV9:1(%S0]*;G(*UJ&ZL_EE9BC&8V5A@`,W0@!C&7+W'7A)!<6Q:)K6 +M9[=(D5F&SZZDSPSECTYR1@<3L2;;?'.Y]T=4V@\J@?C.444D.?4'`W,N=;D& +M@\FU'E<2JD3$GZCWG_CN-"46;IJ[_!-PPN(J9M(548'!A4"XP)FY>U'&+3+A +M`.PU_D/0O:_.43U(_2E7;"3DXR7_IM4KH[SF]/&5XT,-"8^GY'!%Z<]FR/I) +M.KV\DM6K.YQ8EPN'1:LTBI=!?VR82T;+3_!.C\,E6#T!7.=1P4D^J_8XJK5/ +M*MO3"-EF=$J-Y2S/P/!$VC'X'LMJZJ^69$^L$-C^>\(\E+!AO%T2>4)/-"9. +M@1ZN,503-NC884N]W)/;M&O4/FCGN90\OAT+SP/PT-8$7=.7T`JGK7+/CEQ. +M<;ECKUL#J>3,BS=M&[FFIPY-(NE&7J^^J1*,P0K)NO,;D@.LCI652,^!2KY6 +M^9\_N%]`ORK.<8\,%`\8#AGBJ_40)N6??1B@B!JTQP@$P +M'RG[6I5NO=FL+%'#KZWL3;\XU1!5VKRG>`B?BS&-$9Z[='%K2.)7ZNVY10$[ +MQ#-MMN(TV$E6 +M/K]M?.[K^]7LA;?YY5:Y:7\LEX$1T*UJMGAS_L8O8%2,S$).N+$K1%W*^4U, +MC";NS.,T9Y#\O1"3I&2+!_*/;H"VL\0#Z&:>,:SJ;@"1[I9`?CUA5'.1F?,` +M@)]SC`>2.WYI7OAXX=9%LK!87J^7_?-%.Y$8.J=_FF_?7')YA?6!7(;X."SX +M"8)&8;8>_?/P#V"-">[@H^@WZ0JQR^R&#%(B'_*E7-#X%W^X2&"_X-S#:\$L?\&9.> +M];Q&](,[H&EM062631V6@9K5>Y)>C$_+BUR$?W]J(23S3K1NE+C1F15<@LHW +M*LVAW)HC*;"_Y=D[.N5X@3@**HF.;/7B-2T3T^3%G>47I/[^@LWP&'G++<[; +M#!Q;F-E'4M]VBU-ERY/$=>`*C!#1$HNP4312$?*C&]@+5-A%K5\DL<6E!NB+ +M:]3B5_SE.\G,)%-LJI[?(>MA;Y!Q)<`VB[A1P$(?"3 +M7BD[0@@=94=3Z?-$3;K`)OH5-;;R!:.%6,M([,??\^-ZIS.O_2!:@Q(&XG&? +M0QRQ?I7TAG$\##%+0]0_1W*I[PRY"0YL:0OO<PO[L^!& +M1`:^OXXH`;3%A0&T^($1:9VF]-%&P"*<\'C:$-)T$>@WOF^U`GS"G>PA>-P+ +M7[.[L7,2,QCIY1#-AC5II.1&E9\97LO19%^V5N$1FN:P5`4)/9RN++0(QO[' +M<;Y-%/B$PK=Y(L*O-)#%`2^GE9":#!B^-C%X'Y'QKP)BAX;Q1\5K`(N;+/5? +MUJ9Z*)H;5=QYND6PI,^=1_P`K>3R*(BZ%:A)L`$O@"2)$I;K9119E#1#YV>; +M:E6X\;&5'9H&`Y1/1&WLFH#)1_S-6#DQ.97WKBKSCQ/E" +MN3H*K:#7D?F#8-FLMU/F_.\9'E=7>T^`HIF(*]&GD8/*0/.?'\5*U=9]=0P@ +MYB:;%^K07XNKM8YI)%`FB! +M&CZCX6`T%^C@VNRW7M*OW+_8=3Z1RA>"TU$W4V +MI1^;UU3-;8\<_9/]ZOKZ-X'%K/)51^QE<`%`*)WG$*)4-PH^&$H7FA-##L4C +M4&3E7[;;2X/S?#)H110N&!&^[=PWWS$D=\5HE0=3%H!=7VTI6LUH'1C6V"V* +M_LNJO!W`TC0WL;G;"Z-Y=HLT]C$9;`9G\S&,U)XL"3UTEUGUGXD8VEQXVKN!+PADX)TL\D6@8'O`ZQY)]=*2 +MM9/PRQ':?&&!(F?-X,=VS#;'0_\C]#4(27;9K;_L-^K]'22<&AZ,T-8,8)*C +MR&D+`\F(K^Z(RI8U.<.B--C?HIYF/O2[,+5*./*#-Y/6G%-PPLB6F9[\289WX'N]LU),RJ% +M2]'W,`?1I4Y]P%>M_+S80S57U!GC4__XA$=8G=6VND4)!#3)X5RW\2S>E8"> +M,]\9Z>#N"@"?8WHZ/,@)0>C6-,1)Y`GMK.AAM7"A0AO]5R0\@1L+(.RE!2PR +M\:7*F2JZZ=7AEH2J1JGBL`R@(K"J`<6*,1'P\W.?N:W/#YU,3LP>JP+>@'2% +MA?OBC#1:"C(0$2OY+FO+E,V3H.OB%/78'I\DC+*T#P*Q=,[1#;96AK$%$+FQ +MB$`!\SXQH&NS$"08G0B+O;#8QO,P3=2(CL?M2NV46X9O+ZO4:H,%A+U),H52 +M%HV-Y_\C]F?Y1%_H`M<%=OO*#M4ZU(V?XB^:)#BP7X+@:4+U!]A2K^JG0%"L +M,X3%&"[@Y5.>6\S!PR=70)S@@[_$/[_D7L4_?D7,>;9]7VK1104MY+GN)A"1 +MZ(FKRXC3#/NXLW+I`*3S)3ATZNI?`-5UMC.Y>J?H94IURW)?A"+2H;87<-&= +M^Q),K40`4,T!1U!G')$F'+4N1&W)=)$G,\/']W7<.1E]+4E(S',\`K/FLAD_ +M#VZDK=5R.L:9QV'F<&RGP,SOY4MG3M?/K19>8ZT9!,$S=M.0,;!;5#U.=JPO +MY':$67WT;0MC2%WM.-_JI42O+VRB+)3Q*08,KO1:DVD'.X.;]956]$@5#B[B +M:V0!.53?Y3T6B<>!0"GB@0K0:'$M_X!:AV +M:)@--VSEK@G89C.)*YMH_VS2;/1H:DSID$1(Y[=A[[ +MCJ?3\H/,4>+4!37F1$+<.46K)E]Q.VX7AVP!J]M>VARO3XO3*.9-&`^1B1B@6ZA-7%D +M8DAR6PA8^D@?@$2YATJCSC!N>@>8P^X(@]K77.)6#AXKHP,<^,>_'0?#+U3J +M&L8R1I7D+_;2EFH8FR:W8\J!$S/@D#S;WAVX:G.!R2A;='TZF%6E.ONWAR'? +M4TTE"W?C?C)2V:?VNVE$(ZNB.^Z(0H_BK78'"J@'V=7J,@&Z,I@=M-,"FSB[ +M50F26JK?;::/J+@C?<-THL.\JT7#Z/QZ`,9]#2I,M(O5.N^Z(X6R4*FCM5W@ +M#X!JLYKG1L(:*\U$4&\"1@&``H'KYBZ;"+^@QN8&KL-$G!LQ_ESATI +M1(H*-I5#^*%;;22<461)GBDXU@?TU+&@JQAS0#>1&O=F54]Z:U]6(,_#>HN1 +MMB_=3_)C9"@8'1EXQ>80Z;$3-X6B,S`5=T18-=$DMFD/K&5`($#F0@%]GV6O +MTK+CQY.FA9BO8U*)R"U11'%#5XDAG[_U\?KD&8'_^^?M[IW0H/ZB*Z'+ZMC; +M-%:G/^_T`]IN=G2LI41-.7=DBIM7F9[/VBO\-PO;*'?'EUZE,*.Q$4,3%>32 +MW4`,*,LRJNX&1JS0]&AY.HR(2NABY;O"R_(X;`,.L8^,6[S6MTN#&]Y^T.UU +M]N:)JP-SNL#;'CP5@+$:9=DZ?*RB&/>%`YQ^.8>K6R+Q3VB*NQ)'1L%*29'E +M'X>9,S:":=7_9Q\;:4?I=Z;Y5\R[$Y+KSH7?=U2D6*ZL,&-OM'K[CE=.N8!: +MD\V,&G`'(.\(^\[Y;#?UM$26<7`W."4%ON,3_$5&2G[C-FSZ+)$'T-E;Y#X+ +M+)I@3T&K*).H(G+[B,5MJO8,BF-GNJ/)%UY5.K_1?70#L7X9FTNAW+WA[0+.;WZYRGV)9,C6OJFCBB4;=[+UH*3,@WP +MV@G%KO-.;\^,\NOE9-,0*S9C(Q8;[T!,#,>=#S+*8Q/7JT#>Z"=T\Q`1UH?3 +M_Y&=^6DH&@:Z,DW+O1IZI>P8;+_*1>_F9ETNCMZ?\7LDA1Z2D'6/G+%B.VN: +MZ;,8@++04\HFM)](\G`Y_1T+.M!%WX<+]?GCK,TH*.-+I3U!3"2K=E52/,$I +MJJ*^VR>S%;5]32?IJ-(=+A'SO5)>>_1WT;!S@E@-4HF(&IJ,?[V";,,VKH.= +M1)C+9TQH)MK3,/1C2@6K?\45&<<_C);BR\V^I08]'-=K4*_4^*^*\@/Z:HA: +MJ8+2W#RK_$3ESE#8G@_!+JR'&U]QFO.DO;('.MRV'MI'NYK6OU9+'7T"!T5);!_&,G9M^N(YJR(6A)7C +M7X@U#X3>,A0S.FH6K$^TQ-AL(A/DZ2S%=UN3=2[FY=J\5`1N7>:;2^`/1OX> +ML/U_&$]N^&/T\I@S,H7!=SM0PTREV!:_=X193B +MM2!)JI[O#KME'X]UUDH+L$8O'`(?>-W-7*U5N../%SJM/G9-3E1/Y>C:/?%6 +MN\Y?")FG!0LGJ3B*R:;3OBV476">#%TES>/J!Q(BB*>XXB15@)$U/7+9(GCF +MV6+P5CU:9CVNR]8.)792E>8:5M0_5AZI/:@.7ZG198(^S*\ORV*A`PK#1'&Q +M`]8\ZQ59+F+,G@;+=:)T4&2M2G<,N#B40%'"7E>7$U2[>Q5>Q'QQE]"BX1@4 +M^)08E&-3G?MOW$(*&WA%2HUB0I@8CO%/<2P'L*"*P@67HRTP=G;52G\6$F36 +M)?>(QVQ7,&7!^,%`FUS0&&`X*K7Y1LSFMA!`M"QJ^6RPXRJ]29@.2A8,QT3' +MG%:7W+MGD?++@+6DM!,KNR'HYL@F5BZSP;F[=H$IZ:E`1%VL`SDM"7AF&IDA +MC>/O%;>-H#-NW7[OYLD]6Q=]L^XF3N12:^IL`=E0AU=O3QYQ\L@UF^5V@91& +MD_^`,5,SFCO(ZH`&2_K.(2[)[P(G=4`(CP_P@AEN('V74PCG(7;.S= +MPZ+BW^0?O5*Z58#`U4Z`N>VI6.'H>9,E\-R*I3RGKOD5+!:"9PFZMKJ\LX[Z +M[5X;CQSR[QBMT@O#1!(LR3N)=A9F\YH,7G/CH8Z]1P78IM2W;Q_16I[)V]Q0 +MY%BRY$8(.'\!O(.B$#F04',@XF7UI?^A!*>B\WN4$M!I(.@[^'K3RL;1OHPV +M8N]GOD$&.!DNF`2&L#9,Z"U2:].V3FXGW-#/X)-/L7]&"T("@N"$WOJX!%`Q +M"'_BE5["?_D,^HF$PA)&8GFA7S+4YVUDVVJG*V'F8BR)8L%*A:]?1^DV7FU$ +MRN#!E\\UV^R$.S&EPW-_`O(:J-DEV4B#?*M%I>1FW-X=0IFL\2MVR_$U<:H6 +MY-T%NL9?S1\)/P[6@6!24`A)R;T#C!;2G+[`8K)#6!3FB\6<;^_$\DZN.#$@ +MJIP1KMN2UAF_P];T'XZ6)0KZ_/A,J.7JUM?H0_SLWBWOX<*#V3#FJ[8KB$G1 +ML3:+/L6Z"&_>LF/:=[UQI:Y7C`R+/MWQ^I)/&.)JVQV+`T^`Z1./I%5SR/2, +M:Y.<5`-N'BI4>,G>+0`\P<J4(]=(M"CR).8O4^47B2Y7%[;25B%N +M:(X.91\=)0AL^%\0^L9NI[X]ECU;;'TB)IAG?_MP&[L5TR`\%R2@L+:F7:(A +MF[$T*\F;)^"&'H5??<'RE&^H6=EV]<<;]BRYK*KV9XN^TEZLP0GI5'+,<\^CM&^36`&;0891C2"QP>'QB +M985L:4GAAZ,-"G$5(%7>@O<80`60IK@L\',5H=W/3+J9XNV>$%C0=X)^VMW2 +M*YFT:/BXP$];"SPX;56/7TA,NV)6Y?3&LZ[0%ZI`X4N!/JX#(^SQ!J)1SW]4 +M6+3A#(U822(DG;S@E%!5TRT6;V]>1?4W7X*4*HS*!%"&G4T6IK%XAI$OC$'/N:5LW88J=U@)XA^#5US!+I1C@-T..;-3; +MP:UNGK`N5J6F9NZ5NH7,13_)T\7:/1ZD#@$;,;1CO5+M"V7G^F"^(G[^'>@( +MCL'8M+:#<^,3M6*2;288SAZ6U*)\+/BNF_NV-OFE]\ +M(6RWKD+Y>SV+9*G'4'_JCK>WE8N(Y_$T+"OGC^V8T#+KSMZ +M`JY1M]8P:\"63[BE"\5*7&M,--2T"8B`-WO:!LO:HUJ+S(:LU3PW]_L403:) +M;%U^&0)I;3,5VN`.,^\8Y*C&3-FKC8![&'1D6;.:JR,)HQH?>?5>X8[;!T@? +M'XK@H,%0+(2E4XLXFX%$A)R",:6CHF<7I2"V6EPIFNK]YXW(X?-G#7^O*(M5 +M,Z>=WQ=,1_GRYGKQ%K<5YF]1A98Z<>)#\N.6"XG@I)Z:Z@.7;W@D:H)12"TV +M1(]*XKD;CE)''R3;N'8)_#.X4$GHI7>8T/JX:'[6XTT:(=6<9(7F(Y=SU<,X +M6DNB>X^(/6@*MQ_%D,3OVS1K^=)/IHC">0+SO31$`@C*RZ,:MZFI!EE_LT,B +MR8-!9+N+,.V]AB#;J$((R@LS>PQ$.D^0PDQ/AO1_!`HK] +MFMF.=FXM2G;RL33?2PN>8,TNLD4HHC;WAK+,/W_V]GM +M%XDE(?`J.MP@^^P"EV7?4G86X`4!XDDTY5.C5:$6VG7^Y^3@U$F[YO6`?21G +M*C=23(YZJJAV> +M#:6+/I0R!3L(I>:X"C59GHMW@G]X28"BKN',A%UU)*+7=85I7NK1S,LP**6$HA_IO)IVGLM9-0[V8+=(/#N?K]3P2:S +ML"<*TG/\?Q$O%U;*O#X]; +M9BE?KPDS\A7EH;0G2PKT9@.PE;*OL%DFO2\\J$P&-=*_RZ$P6SE5)#`1P2=CU`^<60IL%8VY;!FZO=\PP.*9 +MN'6-5:'!9AMET'G/VK^*R+'A&!:UDY)/BU(Z>Y+EZFSN."<\`!H;[;(:<>%] +M6-3S?04-&PF*74L_W1`!T10OT78N5*,F'=S[+H/*O;$/F^6.Q+;MQ."*(S3' +MUM/1P*/=&QER20S(P=:08UADG*N0.=KT]F5OOZ'0D^GQ5AHRWL6V`\_P7&1M +M!<*IZ\;37Q15*R4O81Q0'R;5D3#F33]*J+=_XO9S*AR8W2WK-DI)QBD0*7C/6FNUE1E\9?8(% +M*Q7&-^R[^N0#1+="Y?>FF2T#K6R3JS*RWK)3K>;X46Z9>'@+SOBY-8OA0\8, +MN"87O;`[W72Y"155W&06).>0Y1^KO)(]RRI.GVIWWK9(_?_X;X&'LKXOI^7C]&V\O(D.3W3&*,>9 +M;**-@=:0_A:(I?\L$-IY]GJ-%3=\CSQ-K4N[=,[72Y:O*E-[CA?T?LF4F4UJ +MT3L29Y15'2Z,TYQ3+4'%V*%IK=8LG%QF/[V,6.#X$0%X?UK?,Q^ZEX&&;M*. +M[`=D\8Q,:B!QECJ\A?MVD40^5D<4J.X9R\F%%1"F4_"4:P=LS^J"#<^%!+]6 +MTC^IHNE';KO+<@B85]YOJZN=5?$Q54>D/0O.5Z\6H_YZ*3C0NIY5Z$+I,)NJ263+K3TA,;%?5V&W1<43BZU2X.:U86 +MK!1^N35'0X&>:(+X5Y*=D7O/PE>45PCG.JA&@QM6HVM%P$2P#6VT*3)51+6> +M3']`K#2HO5<4!2X&"Q]'$XD#Z[GNU+M[-\ +MHKL%S5+3=%\R9O=K+8,G[/1D%$]FJ%E0AC[I&^21C._.VCX_6YV=%HPK12YA +M!3+&K"9JLOM4:D#/VNS"^Q`-3HKXBLU82>V2C8QQ$1L[1!LP74]TQR[0=]]T +M.?=L!]?)%^[\"H(7.Y2_SKW$LFB[_B"U;Q=:MQLI#@4H]I0(=3FC*OYYB7T\/3U,\Z+3;PL/1VDIT%#K:FBEX\ +MY[.7@ZZA*OR.@R"H:A&?U0P/CR!2\,'B@A%6GO&P8![)9:\SDD,&Y7V3LF%.*^1DX`=0N77G1/9[4?:DY3$H) +ML!&>8J+.'74WP/?J'"PX0**.JY>#JE:ZY.M[\@ILF'+?UM(9<0/R=)FD;%HF +M31'UP8P"_>N_:M/H:VAI4:'16::PWJUZG5M6^=XII*)+*S_?C6*!-46UO<6M$T7,3'B70$?QY=8DHQVOOQGQ@$1^%#, +M$%/,]7A1XG,&PB@O6HYN=PYD_QG%):81E&XEHU.JG"B.$^-*MZ73+:6$?=^I +M3#:Q/7"8KMK)0'0&_MF:V8(!!\PL?SZ./V"Y<_P_`0'Q1MTU_89,U&?D0Z?S +MK1Q1S\'.U]):W>X)=#NN!!S*XB9"[1I:1['.C4Z'5$KZDAQ6`UI]A&`-JGH, +MD('!X!`S!/N:^6UUUL7M-BW\9^*#^`_&8)K=<*!\X&?'>M$A"EC.#C.XN@#I +M#I&'0K7D(^XTSEU[GMN,W7$2?>:9&;"=L:LE"QV>"W +M5%W>W*5-';W,/"3KD69L`0;9W#J78R\AO)BHD*F"7>@`JX*W;%8 +MT)'.:,&^XRRA9=?C:^R:!L,S&O6T4_G[]CD[)(:6"-J;6Q>$F>X-C1@\;8UD +M&X06K%YH/M#*Y0QUT=(VE'5/U'-.<4+T3PW +MGH2G.27FNY\('/T]2GY^NZ*U_YA[24'P*>A[*\*+;]I<&H6&`/>>JX-4D1J* +MZ`TBH^V':<`XHJ=/Z"6WR*GR[1["0)1I4!7T>">^MEX`$8(,?-Z-)>L9Y+[` +MU0OXJ\5X%$@2Q"_UETZV:O[R/V<-3FV=M"++6@9L=ORGVPN+Z^6!KY/$W16] +MW+7]V>)F">\J#S2WHJ$+-Q?OT8&YUGXWH7=K*$.P8H4$U5P176V +M7N%G1,,`C5W"+DM/]5].UJ]@9B$:?XXP%BRY6[-O.9TDVWD9*U4&XR]1"XU_ +MY-V$B)ZHSXQ@B,)8[TE!PB_2'1-UP4DS1Y+1<*.#9WS*29C@VD1)_1W@W)9V +M?U1@3`8:(X7H1.4Z(`-AB],]NGCU1D*/]Z[22NC!B1/TSTL`,>+1UC;"IYI7 +MB*E'F&5J3NF"7W(/:;]!FI/2(:.:1EV/4RN&U$2=?DA50M[T/;%L>F9-Y792 +M9(;*!RG5>FPI=L,#Y^]M+]-X8;SB?$@`P[#%9R8UMC['? +M3'F.(I3"A&]=BC*P$)1*O.PHV/:<1"JW0![D4@G'&O!`X%T +MON[T#U67N533XD<`5&A"P`@8"ZV*$MR4?0WG[HN8;.-7RM49,Z>>CHX7,5*& +MMZU@?^79<*7\C*9(OF,6FN3<[<,:JRQZM;-"_X5S#3:1I.^M5`[V.3_9+-E! +MR$7PHHJZL'&IV?#8SEL%4U,OF=,8M*^H/K^*#WA"#/7CI'TD"CDUQ%M,/7)OGW$5-.M>", +M"BFYK)]J"]41-9M1W:M`I-\VF'D#`IER>$4+K,"13Q]P-PHZ,!N)!UR377!,;8BSJ"^3#O8QWR! +M%L`KI4Y(T6->^%X[',TW#^DD$]#<0.&U^/'./]4'P@ +MJ,ZWZ<`++.T..YZ=>5>G[)G*1IE`.'Q`5J3E4UI:2AHV(1G`3QW>@G: +M<;"/F<.?SY&,;#C,`C#$Y."6B"Q7<7"T@)NR[;)&4,KS=YS_D<=SRJ2<\J\> +M0$&YPKV]RI9.<'^&WDQFX5(!.1."F%"?P84(*ZRUP1JKB=_Y0$R"D3`X@M)S +MV-UC73G>CBN.VE46+;6_WXTY`KN,&GC2JDC$WD79L^5F'D(93QUQ4)UOCNEX +M@^YM[#\D5C5MV,>NHUT,`7*+LM,]<%4W+]3N[[6 +MVD4;M`-;"6>V?9!K7".,W0"<1L&W3F![':!PR)H93--K$@P(T/"[KWO^^7TYMO'Q;#6E`#;^G(OAYX+ +M(<;*MKL($S@< +M9.JUA\>%34?4WD#=&$?3VH>1%`3IB5@**L3F+I>/-^T4+YMDS;BUP^GMW&'X +MB<^!,5D&(,!"".H#%]-!)7\SQ(N4G<78.-F2_^['46HOWM+[[$`\"*A*X.P, +M_^+N.+%LV.LW?R%0/,>HQTB>][:X/+&LC?NLCL3V?2!KVQJ9`0!)I)#OC&EE +M/2SO8XR_9`7M6:)I.?=LLS]LQ#2V$>F#[R.0Q:Z79((Y*JKV9?P6=0/^QRL4 +MJ*'QOC:W?CZS.ZAVN=*Y3_U"BA%<0M!ZU`M9I4LLQ_TB@`V#BEDV5Y4"Y[G3 +M5U4!&R=+(9:$=IH;@-M-D1.@!>7.VBN:XA4RU\RL94*RKNM6>R=A0%4$2$,? +M(TEN>$R7''@"[JXOZ7LMVW5V-N8E$7XZ^V7BV#!=-4#6Z@S=@%]I1'LF';?' +M#$^>@R.O5G!\J>OP9@6IH\G+7U&6(A$/]%)T@T1V+QL^=ZJ0;`G>-;"Y>T]Y +ME06A,#^3(D3Z;$G__E\I*6)XORMZ2]_2:2&YW3?-@P_UKWZ_+;HJ"CS_("MX +M#+F6!A-RL'P:>'J:EGRX>XV%E*=:?OA(;63"6Z2]6IJ[/6HKFU'4CI'.Y`S3 +M&,"1+W6G[ARXK$ZEY&`!O((:H`SNLW?@T.63YR?,EWOY9)H#*C^]Y4I],$F' +MI9&;6[V\,@K,(?R7?*,]IAZ/4]QQ'RL*>D`#%4@G!51+JGZ"OU9SY]="K+MD +MY,4%==L>L)?3`$AK.YET@R&7&M'-O?:!-C'N$+M4#'P'^R%HZYP^B1;"UO`U;V(EZ1ZZO-^ +MI-H=52DX,*U33EAW0(X3T9=37;S=%]M-F3L,BVHERNX/2^V@[*:.4D&` +M"NR#]GE@%4SJ>G/LD3.C*$2UD)]?M<9$R,,::&WZ21?>P0QMI%V.YV>%R]*D +M3E#Q#79ZAA!IZA)'10GC&UZ)OL<,44[?++'&R3H_^>!3;[E"4I^4C%!\KP7* +MB!4"Q;ZZ5#9'0MOOWLWYK$AXG9:Y-3Y99<36RW&J37;;-Q".FI/::#+1RUO2 +MC8W;!TO"KY\8R&WAR?*!6R24_:!OU5;C9.]M'/DUTJ2DTB-BY$*(:,T)_7%+ +MR5`31^%-6#&T"[-Y*<2-;'I-T3Z285T+$Q'^XZO+_%E+`SK[4`T@#'A(L6Q9 +M!9L4P_#^E!K[9[44#+(BHP]T5$^F69,^F"WJT7 +MGR(/JEEC#.41B[P'R#7=>;:9J7$4?DHXBPMHS4;`-O\,@LOQCE +M^@<);\-3E^1(JT])C'#!\GL8:K3R):D4%O^`AF:X%ONE^T%R.TLH1#0I%6>! +M[.S<-^!]P_292-[#[J$\%TVZ(+OX27^ZC`B4E$*#U5^E'./0OYI]`/F>]-F$ +MX>4!8\']FZ+,--6X&S +MVM)7/;II\9ANT?*#S@;"4((^:[+(_8@_SX-J)Z:TAF`*.-*EG3:!4B2-Y0', +MF(R$PLFMF@JEZWQU?NLLQ)O$TR?MH="_9)'-XAEJ47O-%@0Q +M>HI(T>__2E']_7ZC+FS)SHNG-A0G41R)K)0N,:%L2$8P_8F"603C#_V_FQU' +M/7DRC/1J\"2^7VC\:>93=`/5$T2#`AW(AT`^MY.E3@M02HS/B%0W&_JQ]E5Q1SP^03;.GH!%NR"/026]8U]ZS9Z9 +M:/\;K7V6!Z+ +MUU(`Y;;7.=;YY;=M6"AE0R6OE#_G#!_7>^K[C(T59SGV_NH'I9M\8Q12#VA? +M82"/V&B!1H#!LZ78AU!N(HN&E[F"C4VQ#BQ#M82N%P6SL'F_0_(^9'4,2P^T +MZ3[H6#?H6@').+D.ZG8Y8KT::O:1._$">Z\\O?__Y]V:@=:[8L1FEY%3`EG2 +M)R\QO232?WWCKL!,PW1XKTI'$FNA478/I'.>.H(&/ZG[F4#5S_DDX?3DTAF+ +M'UFE)**"=VR*@:"_OTK^*K@0$VLR+U8]&?DBL9?V"#)&&V[PH>'J)QB +MZN$Y!$HMD(XY"B7J)-]-OJZH*/T-U#[5>@'/H_]A6C`12@H30>\]@X5`;G^D +MVK$!0YU,>)L[][2J"1.], +M&]';__Y_RG1"2=_EQH"(9)+3SPTE,)QVE:XC7THRT6=M4QH$7Z-H!H#&T[*O +M1.[6Z"7`)V-)"I97>E+&W7"&)@UQG8-KJH/1X0->(1J[?B"H\(<:Z:LF=^)= +MT+^W#4I9PO.[#1L2T/ZTUQ".QQ_2*F%GO-__%QX1,7-[.GS/+K/*&=H3'P63 +M2#I>-2J#18:-7GQM.=]Y+108B2"R7M[K$3\IH;]@V#>O83[%EQY1UC$QDE2M +MB3'>5'*&'$+KE;G954JM(._(M41GP$:KB)*'Z`#REP)PNOZ5%^>IP[*8+=SV +M0$T:@WN%,GI:/D_?[)N!ALK%YJ';]&Q9**5G]7Y2`2(RVC6.F#CQTA/ +M*5&_@8/[@$=V;VS_/OM-MY-U<@QX(D/X0=[+&HCX(6!&'+E42+2NV:;I96*4 +M[Q^]P.'*%#3"4XW=PS8*'<=:EHF$[DT4]!ZE]Y^?[8N`!OD;)??T^L6D6R+) +M+,Y+$]*[ACY["+=25[ZNP@_>:G"J>XHTVI5^[RZV6(Z:2&^6%:^!0,8X5S+1 +MR5]?&J?HIYV=L0[RBC0WGJ"54??80PA],/N<]B%&QW,8W(,E/]4/*%/0:D:B +MHN\[\T<`L[,LEO&(7$)B<"C6F4J=IY\T1'/:ZAY%H^+TBU_!O>J];T'#>@1: +M9Y\3,Y:\U49JC#I3UI2#AT"4G@>H4>CHMD#67M./YJ9R_E/(*,F]F$D)%-3= +M_R/$(,6_1X7Y=VU^J*,YBK8I=%;UA^"!!U_$>]I$T6B;_N(-POQ_0\O<9O6V +M#YEQ)A8\/?MNT*12WYX@]B^_Y-;/$Y[`3DOC3?(L][F$N^H"=\9.C*,$9.LO +MM;."#<%KMIC`<#Q2)(_HXM",;](W\GU@G.]@O[[Y)G'6;6`PZ_'S<2,T",3A +M&)+?PT@9".F\V_AAMMBH.0]8D,5I[YM2JL/(0K.C1&E;WQKMO]((3,8P,3A9 +M\!U[&03L;B#M_D(\&LQ0W\))X.,(I"=\XPB,,+O>``WB1:$)(9>N1:G(9IV)[FI +MZH@[H3Y)B%FF;X4]DO#<@POVL)PFGMVD6-.&&Y*2X!+>/(^TZ:XZKW8R?R1= +MVS2KPO?!\G"/+$3,D^P3P>:S),G,9Y0'\6(H,0.;LQGV+)PV4$M.@M>C7!;0 +M8T@P[]LXW/"R:)':)SZL%2RI:,J5=OSST=CTQ2'3*K_J#JBY)^CSN__WW^(+ +M++"]\?O[NY[P[*4MW+]$XOYS[.\):#Q4V(KY7B1L(M`#`:Z7)*,49QE`K!@Q +MLQO7ZC"W_=2RVP8\>^ZL>R&^LH#_S[X?O%L=/=0YO&:;!>>J*?4IHA2X)S93 +M_G!6E&Y6)3MIJ@B89)3H/U`=7U&L_0!R%&7EIJRK]2B_-4*^+_F +MS-X+(?OHGV7X\N>H5!8`W7-L])+2_>%>PB>Y,RA`CR($I>1^E![`$FUCP/:^B&G-59 +M^5!HK?Y6E9IE5T*A$QQ>=F'1F(2EO.LG7KU="C(P]&)"_?L_E==G2Y1F;:S# +M>ZB$Z_W;X$KIZ@7U/_F!N`8G[Y3=T.T3!>[I51((P')5R&%=1F5O4CR"Y,+Z +MI+%T@'-ZY<\[I$[:$W1$1)+@><.\:`R+VLEV.6D*!.+X-!X57YFX=Y._[I'- +MKC_,>5"F+27&;-]G+_&K]F +MQD1BE(-8C29'6PJJ(E98PP_&Q.E&.R$(,+ZR<._K0M2^;'ZP7Z0Q)"!K=A#[ +M9*O!9\34$8QW +MWNZE+)$C?Z3@L=E@"1Y=O$NC`NPF?CWB$`MR(X5R09'T*9OGQ +M1F27K`TK@GH?"#$`/I'Z$#'E/[%]P9@]<%ZOYW<`"W[^H#N%=W>:2-@K$?:9 +M9FOI+WQ"%=$C)2$.H+_,#FP77M7RU-?,U;^NQT;.FM:Q';C;X9N5\L-#9@5>S3\L\,==V]5$1,\MEW?H.K/^T +M/]'0"$BIP]S"8MA5T48?]XU,UYZV`_]1\PV$+FX-:BI&$A +M8:`@KN\JW@BTGI:"D]00+$)X^+=1C+&7!6BNQA1:AY#&9KQDG=%*1IH3J*'! +MX"+>LW`M';WEITQT/Z;"U9+S)9DB0PZR8R#$D>DVN['GN\__C)0?S%&PV=(( +MU2CB4W8QY((TLC;42HXS\0?16.D;X,1%0E6Y',SY8/8V7W'%PV*O(S\W\P*E +M0@1$@;2@(TIS+$)*OJ2B&.6>'BR`_JX,^+^*_=]X%-=$6[=21ZW?"]N$Y4$'091D(H[#L'&X<7A-M8 +M->;VWV;X5)0'AH8$N7HE^5S4[?#1[V]1]D`OHN&LNR[&P5S]<9_SK]*"2$%# +M>7HKBC79N/?-\^-7Z;:KBNMS<+2303MF)"6OJZ]5UKI!"P=?QZ'F6;K36;3E +M9U+OO9AT2*2\;R8.Q*%(#EA-56LP_"%NU$$2V_^TJ[KL5;!Q/STOJSC`>FWW +M9XE^I,)(=8!82.GC3JFD8`NSZ)\@,V&0@M.X.\RX_G-RZ8_!(27#(D657U69*3.5"XKPBBO`G[][TU;AR@1);O=$SQNV], +MQFH@*M.V4GX9FIKA/30II(D+3Z5J@`$3+$@\^V\2EBI6I*;( +MZU:[#;>O,1:Y[8*$Y7ZQV2*;N[#U=U%**4ZOVV$/.O")__".N4VLUVTO&+?; +M7L=\@OMK;9XTU%.E-<%GY7)R!9?_FXMMJ<[9+I.I=D(70;>QBH)93`G6>9:/ +M'A5_7Z-OHP]!1/28#"=+Q=4;+I<&V2S"\>.)GY_H"%4_?#-%`#_H]Q/XY\CR +M;[+:5;A`"UL,M`Q%`+#PW8W$JL6+"-&U9:>7!NG[_@?^9!M-!?C3!*']V5/V +MIE[GQ;KT#<3F*KY>Z$GDGX7&(:AX6%V_$[AQ?!OZ.K9WC$H";DA1.?U3N.8_ +M.)V[@`H$X8S%N0/)7"-HCFD7!*?5OLF`.2Q203]U"["JS8U5`_YU,0H9^@=M +M`DLKRS%+WV4Z[PP[ +MWR[L+RD`+,1"W*BR"H<)2Y&P]4/4B$JN! +M!(]Y&JTDI@+L:$*<42[C$F?JD&E,["Y'V+`3']_<[?/Y^YV\V:I.5MW&TZ$I +M?^1&PF3\F2$*VC6I>LOPI!":S@ND'7*``IA@B3N(H$')MP91N?#)`,2.YI11 +MBK71.V70W@O>O/:GPB0P0?@Y]?L3IBA:=0M83P)C8:)WG="YB52(KZC;6%!<@!"LZ`9R8*%#7-]4#">P/#JK^YHI"%F)5V8[,438_JO\ +MR[8AV!Z!=3X4$'(Z#ED>YH72@RWDD:N[[^ +M,[B:&\=@X;(36OF>R1MU52.$%14ZBJ/A5W@4CY\(->"N@)A6N;3X@;6_]P4" +M)Y0Z4:`MI./N]^=?A#[Z#YCX=I>ML'`PLG"P;H\MI!55W]E"21C0'A/E'L5% +MTSX?U]WN/R*#F>3L>L_D.+*;(`Y.3+D#Q1[ZX&4MXO#]Z`F3W,\G;#"GT)QP +MB.!H,8SWH"!YH/'5KX4J=. +MKKAM[*IM"B/8VF>N'J??%?-W!Z?FL7<(Z>F04HO/+;_5QZZA)+H6?-'^Q1=J +MZY,T?G$?RI#Y]B^V-9S,&KROS-"W29-E1=F-JXVL"\'O([S1)>J@9G"X_!61,$IR0S8C9GR8WIWN27H=[2I5_Y*:=B\P`J8 +MAT>)[!2C73L(TIBN%I[)D#&_'IUUVSAB_\56()JC3,WL@M@T58OA8+WG!(_4[ +MDAO(!77+`^W!::$+:`3PFT-QD^H+W[UD%G-%'2(=P57#K+F#G1@6>^Q6).*M +MH4(07-U),=^"484/#-?JM@:3!9N"O>_0#NFVF/%^L!J5$#]Y$`,J,W\<21^9 +M)BOLTT!]K)+'_]2=2X?"\8M9C:$-)L!?0F8_<-EYZ:6?L6S,0T*6?L8@W9I^ +MY7+:``+HE6A,?P*'5&/K6L$/)$MH*=817-,O'5B42R/V4Y!X:>'"_R95MQ#, +M]H`%J:OMJ205G83Y.Y1%2]P2&=_0!+5@,$F982EJX%W3HW!@3JU7!^@QH_E, +MV%I3AD]#`AFST@3@)ZPX-%*3C4$=P4VC8$$STV^`;](:W^3EKG"L7[)XVV1: +MRWB"#0[2:A\^8F0V^I3587%Q@N@-MUX\A6%W`:4B)D=K:\&:W<-$5S+KQIC! +M'.N,2 +MECA[Z]HI%0AW;5CZ2NAZGN,&;S"^C#IW\FH9)&!]<`K^.7I\UM[2$MCV=^)Z +M&4O/\5?T"22`FBR@2NJRN68>CTS2MD:B_F)Y8?(37T52<7G:RV$61]_:R#[O6[OD4`UYCR*7FR6$VR?15TGX]TP?1,U+Y*O5`6 +M,":D62B>O.KV=].YAPCA5-'"JBBF.ZWN;HHVY/?/?Z836&Z)]H19+IRNO'O% +M$8IK,C<`OF.N7,D".?(Y%6U_-F0F^NC_/1\)?QNG%OG])@ZZ"M`.*=\MC>D% +M?:T+(VS`-`EP%!J<3D9IOQ8K<)'1X\3:-/S#Z)`H0HI0ABE8!>PX8 +MH`!Y87-$[*3^3=R%AKB,X99PH^7*QZ,,N/?9NVBTNCMC/::8R.G9Q%V#88R^\/FN1(DN[?F,C]P-OG76YYXX;`4'+\H +M_8WZ2<<8HS#WL*IM(LB(R:.#B.B*PWAW%M;N'.7J[[_-:.#B5!%`\]523[V6 +M0%9F6KT&@*FY@%\Y%AMU7S03KTOX\E.80YZD.1HU6(V`OW/8( +ML3W]K%_D[US/:>I?Y?ZUY&"UUU&=`N!SLQ8C\&*HESXO;AR9>OS+%=VBG96@ +M/!&'T+0NS$.RVX"-HY,I=E'-H>%&#*X_WGW_+K?$>X1/:.YK1B^9<4@(\T;$ +M0TM)K57%%Z5]KN*;<3E<,9F7P3D16TH/Q-*Q9(:Q@1@/$-8KS+! +M^*5M%L8*_(M3*<':?6UCZYY-5\3(1G5P,-5C'A?]"B3HX,_\^GCKE2$6%-Z. +MC$YJ?X'^EU/6&G;%"4C2M"`.LKTGO]/!&>*(([@VOS\NK>2QUNTZBSFNS<,- +M&9YQ#+J=<&'(_N[1'+6*.8`;SK!2L[&"_?.Q1D=>N(6U$Z1Q\1LC:-7=JL"K +MXKAR*\W[9H.AR-`_;1Y.A50QB@&%.S,]SE7NS0@AQXWJ;]PJK?@\;55*%J% +M9-3+HC/\7IX4'[((V=5*[?$),6*V+UR9E^DJ',*05:)98C-[1%KQQB%I34TR +M**\A)-*K$7_7-W58S4&34&W@TS=?C:[N*S@\F)9[XZK7(6MD_8"6ZYAK#<`< +MWVRW('O=>7RNJ.U0D"%>`^_.DP-5"_=7E&V_-RS[:C5676G0/@B"<_T3L25O +M73=RX-F\V$.%7+_YG +M?)DB+-+++J$L.7UN72Q9`!$T@IGX.N#IJV8$P?/"<-!5V6FG;FN-.OWAY9>4 +M`WX1D-D=*VB`DC@\*-U<;_D7 +M:S?73QXNW(A/VC$8WL`-Z5%-437!2;[AIG#>(`MBY+DD^)&D8Q6)*]>L9W;D +MC/N^8U&9TV45MIDUB@PS6+&X1T<6X?Q`(AX/"L:Q3BEKOPO*4;YVFHF5;Z,W\$ +M4;2).2>@8J$*E.:0'[UA!BDZ2*[.&X@J)/\D_H-X;+(LN97"S/,M?B'[PK,; +M[7]=RUU)3W_Z8J*0GO1"(@3^ZP\XIQ='UZ_?G8U9RQ:<'YFFTO7RD$J^JN<8 +M//&(UIKSN#NX5_^U;B#0*PU.?N[-V7T(T>N_O'0RARY06)1=-MV]!QSV/_LE +M@J,#"Y8BF/(YPD13ESA$7<1QCA/1M?ZYBZE[$'WG4Q-VC8]1LL0O(,^65HMZ +M@5R94.@6">H`(@SW,W)1NJFD/C!K]9._3!Z$$%FF.D:=!FVBJSUMHJX9X34^ +M(:/H85FIU-X8230SIF/\QJ=MI-:ZXY]%`!.Y_`"]B##A9^KY)82+@W:Q1UG+ +M[-@2C8\)R:K,\38\Y+4<(=(%RDS%+EHB8_@OJ<($JIP_06W]9[ +MX/K9'C*G!M/&[;Z10+&V[9R:HH`J5VI\^8N';P/(QI4%>]>\@GC@AY82?1>L +M($-MC@Y'OKV45/VSDD^E-><,I5AI1M;IF[W_I0BZOPS'MI?ME\#Q1RXZKS^U +M@"Z-9(^2V'=]BEPF=H#HS\\C62F8I6#M3`B6/'X]4,HZ6`*C[;4B_/#%YQ3NTE432R2&#)OXBP7"FWNY[9^N`W,)\1 +M]$S5FTKL5QAT[]A&OR]P],B^(^.[_2POL04T,P"_]'<5-ZX].DWG?V$3[BA\\7=G5R?X8_ +MVT<8#_$.18[C1J:U."O"'7GT"4HV-DLKSX1%[1=]"XND*%AO==KU+[/ +M_][Q#,P;*^2>W4%04?"8FQWIMXKG[5!_H(K=1`D0!]C9K/-++(QHQV.H&-@0 +M0!R.'`A85^Y_UT<-+5S-$F2Y8P9@N)/)A9_-E8AV;;+1!71]8'U;;<9A51GL +MH*.@T5ZE:6OH,U@P711JD?89%:L<0V:*0.4?GO`P5T&,BW8#')^%Z)(*%VCI5':S[L66W$#N^M:PXNR!>!4 +ME[C/CJH[9!XXP\)4EL(6*_`40&0.JQ]LNDV((V;"AQ'9UE'!9PBS>=?8F#0$ +MJA3-Y5DK)=IK'O9;,^+PR(V+\=['ETC?#'\67J+10NBTXWS[*/5#;9K>5]"# +M/>[TVLEC'22`/F7NPC#>9[U1X]/1GFO0`E9V%!(N!83<.:\6TIY/1NJH5H$+ +MPP=M)P*G/MW3W%WH`O%-&!OWD#Q)TO$:@^/A#*W";5F$?N+,L53LO-]>+U1"0<2;5H>T+7!;1D?@021VR&'UE8EI.TQ7"B4A?T_KE;K.S[74=J1L3J1C<*W19I0?1&TP;^-^)M, +M=;#Q0(7=^OA>4=6;Z_'?-ZHN#U!?Y,CP;OF*!BLDQN=<5.\&0E/>R1]WWI]V +MFF8QOHJQ.,0A23O"Q=*O6^*T=*3]:K%'B_I6JD*Y2]L2.8U]6JPU^N6;!XJX +M@[*51R;NLW4[B2S90D0Q.WX0KAE7%HVQK4;YNRYQ%5Y02ZSY%9!X?!6+I)+8 +M-@+AV"8F-ME#2YQ`]I]F;,(G?6@WJ]03BI<1JT'--JRZ03%MM31')MP.+[N- +MO`@3'3LW;/7BI0&)3)?Y/M]N&+^5=Z*(F+:_>]-7T&7FO:4QS'L+??R8HX;V +MSMF>&VGYO)+SOKMXB5H-,R41;/?,1U5$]%T7;>$RF<@FT.PG]0;Z^8FG5*^; +M`H58=OQSI>Z1>Y"C9H'EZ_]_&8;5QG6.RU,N"3>EZG96'K+1WV1X-7P<^[^^9Z;:U=:NBK1K<)$:]=(1'T538;"&A;L3_OKY>602`0YIYA@:; +M:YJPI$S1<>]$+F+YZ'_REY3"RY%WO/<,2N7E,6*"FUR,0'Z\PDVB8E6!9Q+F +MG^!1M8$T-*>,AY:#($R=A"SM01"-&(U:R&Q"&6*1Y8WJB(D2^C +M*.>S)3H"6/[VRZ//N,342S8.-,BNO))_"8Y-D`W,J!YQ$"8"1#:;P/OUT!*! +MX9:3PC9/C2O>U?: +M$3LHP3O[^FH(]J/!7%MUN%RN.R]"LT:K$C]$PR!#D..#FOQ@(@%P"DKK2].@ +MRU0IX?T[*J+B'B%DV$F_MZ-5\#/H.$F+C+D3J)@C:9_[PP>BP@DWQ:0RFC&? +M?RP>?5%\4=&`"C0W3[!5:%KQECP%@N=US";*4WIJ\BK$=2H:9[JUW71J_IWDQ^A;21'U"57<_/, +M5]/E@%`7Q`U$=$FT;-Z,OG/*T=YJ)R^Q2<;FMB`4V<"#EC6$(G%Y<&7R`PL, +M3$SEW[?D<[)`AKP>IP3=<$NRO3=4AJE`P@"#R/BAZNW--"_HCUA`>0`DE@(R +MX3=\A/FWD9A`#*T^C+JS:=[*G&]:`&7[)_!+Z'&:Q\;^H[]^M0OW":R$9CXV +M&DP+@?M\#X>R^X[5&0\H2&-KSSROYA295NT1D3E)I_WR6]+87Y^R?"SH3W?7 +MG0P8\N6'NS-YQCGKVSEG:L,BM)#%#@&R[5`-JT8O"TE=NF)=JS*J5/9()4_`L?_28MRWGMSFT\N).&F=6/+I=(UGLF%"L`M +M[99N!0S3=/,B"R`HXR,@0-P;^/O@"*!J2L5;V3>I81RRNQ$/@'W+ER!>DQJV/O[./MOW77J9;,4NR+ +MK2.J+&P7SZO](C[!Q7<=IW&VO6?I55_(ZJ(^%CB6T?1@`>SAWJL;\/S;S\87 +MTN7:CFW/)U21?,:E(E:6U%KH#/E;"\-#U!#;WA9:'W*QA'C75][ED*"/;4!O6EOOZXKW;*0]` +MT5+YJ$9<2`ZN'XYPUN5(`_@$7W2/48DN('1R83-S$@]3QSY),OS1;!@,,&O' +MT7=L!7/Q2I0TJI6KT,.3T'1,!/"V^]JYZ6/$NR8PG +M(^*AKQIBSQ`UQ\^%$5$?!(Q2:OP7C&[BB09#0%Q(C>&R)3&J9N'>!A0%JP!\ +MUBV<&Z\A82@L?LJ2]!I@O*N$3T`PS,:[JY@XXJS"408>C6O[;T;C&W"E+A0U +M,@@L.D,`YA\G$Y<3=U0HVJV!L\MF(6V^?&ZRUF5G?Q(B6P9!;[;7:,:`&%*3 +MAR9>%;!FD@C>Z"J&.C>7,?3JO7F,45-I)A5M<'HG!2D8BJ?Y"F'@$J^$WH*G +M;M,/%@64;9H2+B:G"Z%UP)1S#8&0P57``%SWPU&@>>[_S,3")H>C,$X1;B#' +M!DG97&K?B6&028)T[8>Y;SB:=@Z6HU-^AU'#LRNB^2M&U'\A+N:37YFCL0[)@(T[BSN)XH[T.3 +MB]//$/JBB2/E]&4G_TB6D&3)Y[UIG5G)<@OI5(?S"Q'5.N>8V6(6L%UM.CVQ +MW`E(_G2+M*B:Y*)_A*[,)WJN+'<%.[+T_/Q71+"J6E(9&Y(?]#*B>N.1!EY1 +MMR$QZM+OO,/B3?9"I>R;X&YK"$',HOG6P$+CLGQ\Z-:!B^V;,NV;JTPNW'$5 +M'(XC'6`0*59@XP8N*_OREOCI])0:B9:'9(#)?PC/2!U +MK&:%849=*--5/@:#N*NY,K7JDG4HF>Z@D^%I:6!8O_:U>+2!A$ZU@_R#"\5! +M'+RM`_W[+X].6YGVEJ%DW'C>SKS#7N&A.+'VMF@Y*GA69A,ZO(&7O;EA9_3I +MS9+)AA%&'(#?0\8$7#1Y@I9&A_L6XVK=PJ'/Y&$MA;V;2JP!,PB:$9/"<0*E\9=C +MU!=>YM(;[*XBEQ]<%+4\A+M/>DO[G@^?NP)D7R[I\NOH8,M=19Z5-5+@PG[W +M\P9VN@[#-`P&=!QV/3LZ`RJ=,!2`/OZQLA&^0=_K?H>2CUA+0U'_/\_AA3TN6& +M;_M<,88UQX#0*E=#90CW/G.!E*)M[=/8?=`UVMQ2@TT0Q&](X +M[^?5U/9BF5..P+'C22DM,13-'G>P.53>&69RB#S^^V(ZP+V<,I>SV(-YPHF` +M/;OS[F=JROFU07+NL`#%/+R0!73?:E6M8TF':7J&ANYS[ERV\#%V?'(.#?K0 +MREY&]79N#DJ&NK]MOK^&.8IX/Y5V;]<#5@OP+35GQA2@@N?*M?5_+73-DKY?RD]]*AQVI[_ +MKM-I`\O]%X-2I.-THG^_8\G*3H"@*>(41+(N4.YWK;#44@'O:=BS\)I39?5' +M;4")HF40K?R#$8E5%])Y[]2IB67O]SHP,.)P0(79^%IJ!4MO,C<)E%OM`.-L/2GXX=)MUJG-L#3,FY(/GZ57O" +MB(@6[X`A!8;]9#M+8TZR.4F%XG`!O^@;UE@D'7S@'Q,!E35=30)2LTE-H:GS +MK^N`ML%D:N)!'!F_ +ME28*.*.EC?X=C'X82B,UXQ+H]0WPA07. +MF!>`15;B1G6WF_<)"_-KW^L0<[(2:Z%'Y:R[S>%.:M2 +MKD15U^\BUMH'WQPY:BVXB_=X=H@"VB`_PH]O/3[OSBPDQE0&1L_3P@H?Q1P' +M0UQL/L,72;QC(O%,RI:[>XM]35-^DBK:-]"N([=&8^1L)OL:"XUC/,T\D&%" +M"MXD6-=7UI9!,0TT24NF!REOK=$1BO4@[".V7N&-.:U\F48L8JP:;66QX\S* +MVF+T7T)]>LK5:/\A,@CL&O5):3T`!Z8[Y-QF$ +ME`TOTG=YG"DOXV=\KV(*R)Z3H@G7M9[[JO?_4=C-X)@G*!SZ.NU\M>"-F"CF +MZ@O!?PE>FXD+L5;8O*887A^=91RF)#T=_+VQ$:!TUT+`I>F\BN.FPVEC&PD^ +M`J?RJ38U#,K$(UW)F4(W)T3!&[/,PW!+TPI-!JJ-F0(XEP"+D3$H#F"G.=V)-WFJDQQ<4XW$]H#%;4,0^?6./O5359876`+IL?P"]X!K.A5+_K`;:^LG7.ZFKM=[5/FR7S\ +M[,JA^XD^R8U#7%@Z'F`2E1;K6*MA'FX,J]`$P=I6/R4.RGPU91!DL)3L%R.UI8/,2XE@`#>H:P4E""< +M./D#"4X5N)5(\'=?!^2^-T[9G+'Y*H<4@FFR&?-\,7,%;JDFB:M)0>4!1(IK +MK)$_GH3K4NS)'UG_K6B13L<*`>"E7)'C/=4<2P<`41`>L.BZ3P*`*LO#--L' +M4YJ()M?-T8UM``T91IL^ZSX`3""D']4KM>*R);46?J),GAT<3<)8!1GWUORD +M5S>XQ(;]`^5;53,'`5`2.9L`G%X25)?N?'`(85!KX/)&QJ[EL"5`]5$;!,IM +MKP!'7[ZWR!R/U%F/@PP2UI@PS,0#5SIBBP^6.B_;^:0=JR7..5C\BY5/!57< +MGQ^%B[`JH%-#H3%+F[2A`&D6-(**GJKSVS#8R3JT`3B?G51/V*7BSU97NLC# +MV`2.;`OO3P99?WJT[$H6$QWML^"JJCZ[J84C9+Z)'X^]S3/26EXV#=PA2BJY +M6:F_1)CSZ>EI$)2QEKB%U]D^S=Y)`0*:X(,O1="[)([SE[T&(&:>B/90YYP) +MWWJE[QE&D!!BAWA-7%\'IG??*.9G%:V,Y/`0E!>Y;ZB1SYP>[;WP2=9A&46$ +MQFKR-"?!W'#V;O$!C++7LC-&"1J"ER. +M`$1P5H0GZ?_X*'@<"?(%SOACC'5:L>*"'4P<:J/-TX=A=\814L=[9AG:_2%S +M9=,UMCMU3B1@P_7AF;;_%['/_H7?OD(RA/'O9LE#-B0GF7\A+!C67AGP&ZZH +MKD37=&AB5B>X":10$_/CX5?D1'#DQ7**S3%FI!L/79$3L+DO>ZSP*3UKN(W- +M\A,L\50V.^JX>@)X%)UKL6GF,5MN:H/7RBNWNO#7O4OY7!%.K;)^'"W$2Y_* +MF$AY>Q;T5U@5^#"Q8Z.R>ZEGC?CHHQ:#QJ-=HJG +M!TPVU<.RWJYH-!0OUO[XY\Z3+X-$F<2/\^ +MEN=N%[<_&B@%O@-C@U*&0W_B'W86C%`9YA0-;U#X.JD/9'8.QX[<*V#*#(&,=N_Z`CR[/][DCO)XG,O2[FP;/FE!_!KNW8R9"?)%@:*? +M_&`FA@.(D_2&(U`LU@S7U6P;N[>D)-/9#N!3>.<)U$>&E^DUK<19%^@ +MU[ND"A)"Q'`:7]%3_3Q2*B'5'_TT2NT"-@DTTT+WVIV0`Z)U'L5`+G=B/7G1 +MA8!!N3N'63QY#4^+3EN4+F[<;!-=0CWK"_W:H3\BH.866OOE]G`H?92.^8UA +MHE:^K326`-E"N.R$MF2(N3.*:Z*<%J!7?U+^0R2RW'9*8V%VUD^Y/DHR56Y5 +M%%X44;G+1-8[?J,A*`>(%2U1=5N:K`-*C@5-GI!+X1:@,VO)I@>R!`!'SN0* +MZ$A7\^.Z(&X:X'[552:@T?9$1\C3T%Q\^"U(U?QNJ;EPA;U;X6]A;3QLV4?D +M#MATUC^R"01.MP9YO^D;Q#(54=O0.4+@TG:Y^,YWT\U?79S +M785J\'G:F%Y.&$7`-/_.DR_[D8T.[Q5[H&R*"M/>=MSWH^C6<\1"VC6*\L&B +M*8X"MOG``8B`D[UJC.=JTF;"EV'@G>1`CG!5E`. +M,O.,CU#(\`3_3SLP^'4@9U1?PVPV6&F\U=#[1![U`4^)SA&Y(I(+41:V64\U +MD*=BY[Z?UWI(5=!E$V0NP,0R2/LX!RAHBW]E`4_I@'PH7V!70(%<2E$#)T9S +M[VC$=N#)6K=#?2"I0J>O;'P$A#YTD:-+UH;O-'RLTZGD2!CJ$486$S=/T>%_ +MXK1F;ZAFVN>*SZ"9DO1J4/1%GUS/TAXEN?XLC9-'0CET63Q[]=]&^$,8)U8D +MT829M!"E98QP&7*S!``3>]&3!9-E&QZ6+$;#EQ8=9LI5"[OO.:)5AU";_3DA +MJ.8G,-5Z+.A-`9=8.P0;>URZF`#H?]YCXDB!9K#$;7]J3N,T%GP2H/>JW)": +ML.9@'#`6,^J3)WT>4\;:^RI>308H=!Q425PIVZVT4/U[\/PZ=GFM1AOO@3&F +M"K$;V&F1S\*^TD!B=V@#6_4\]]JJ/W8;/ZA+`##_&=_;NG!A;0JW5/".`GQ1 +M'ZJ49=28Y`WZDM.*GZQKRC^B9'4.Y`HB;%9%1=%2UUO/MP?0HU&4T(2O`LMBD7`2Z>J]CF> +MJSV=>PA^@J/N#JSEF6]O!G0M$Q=7%%>!52>%@<=EG@%8;KZW(BGJNFO#A>D@KKFOXJV0R+T$2MF?6T@'FE, +M=VK-,])8<@,`_`:Y;^@]*%TMMN:^D\-K(M+24J>\Q^H/-]2&$H(:EDQ%FETI +M"I??%AUZZ'-V6P+N@=0[S2BZ#[^&0:>/BDVT*L6Q;GU;F>S>OY8X3`WW9RD& +M"^T'PJVYOUD\-.#)G;C.EW9/#4]&\)XA)%!0RZNL(RAIPB]/?3U0>/P)I[13 +M&>AL:+)1KU)`5DT0O2YU?8$M4%P^:S;]]B+>1!!CX^NO,CPV,M;;GUO1Z@,R +M(F`X"6/.%#X@+L?P](_V$^]LG.X](AQ;#G +M)HT=AJ9%M/04IQ4T?="*OK=3BC0&1.&!;VSDYO;S=3>0$,-)-M?U>->Y[N&- +M)RY9(F76>!P+Q+K-"0_%H#_Z;G:A_+U%?.KP0HA_G6O'N(T47^9? +M)&_:*1U)3(D&!VF*N@6WD/UL(\RS2]NO0\DE6\DJ!16-5141"`IN7A;E0?." +M;R9N7JD/1 +M(BG-D31*^/#UG?B&R_ZAVS[3NF!PH1929H<2]"K[)3L7JB\I7!$BJ[W%WWC$F!3OR&[Z:\'V\G9$OQHJTBJ0@Y8.L4%0QW(!X3TC9I +M8T%5JRQK4(R17!PL_W7-DMU3$WS!5OW>J+72=%0EM:,*&F"J7!^2+F[G"!;; +M_"5\NZ"80*R^A6V:#GES1F<7B0(9K\-#7REML0U,&?QM$%\.OK6%QD4=3,!2 +M/L.\&Q\?+SQK`]++6S"RMW>%,!@(,`7ZBZAVDD?Q-5FC:[F7DIH!JB5W[C,R +MG4F'QUF>;@"?&OR836%`@4%$MGH-2O6D?:XK/#8_X+M6I!Z9>=V3;$](2T]! +M.FJ04M3W&W$R%-M`US*8:!:[0.[.I2RB0TT*JY@L3\BR1EGJD!<8H4M%?TPS +MPM?\O#=`]HQ(PT?@Y2_%%@>P9DU1\A3@4S!SCW(QSK93+XO7R82EF4>^)WP- +M\&HJ(!)"BR/J=S-*SE(:NS,#6=ZG\YKZX5]_3C%3^=_N0$`5"V&(QE?Q8!%J +M;_`_'J?>T?VMGW4`O(%&/D,?[?GF[;XK8([EKQ$.)_L*&X0"[[^B6Z&FP!0\@F` +M5[N-XJ-)*_Q+,3JJNS]7ZEKR@XF!':VK>2$LC&JS9*M8L= +M,A;\=Q!]73>33B&L)#JLP\Y&#S]3(![^\J6TY:%P1\44;9;;0@XF-27%G0KQ +MB!S2?WLB$!,#%%&/&`["Q,!<561&U0GSJ?``\9%OYRG-(6R'2V/O>6\F/'4P +MF)EL+[Y5*@9!`JHMWJ5^J6^X3#S/Y2?,_57MM54J!\Q+::6W5X-^-,5Q$K_# +M3U]9;`TRN\AA1G0@J$ZR:JCV)/&5/)TGMP +MP./NMC%>;X]63BQ!OT*6-`-Q!2`=C`UV3GP?%X]E+'H(#7<#0CL-T&6+R67' +M=/M2+^*1=HO#MH!XNNX,^[)HTU,,?X+/9`>A%N"S +MK=@)$-*IGHF'\+6GRX>]4=/#@UFRE>[^399=&1ZN6RSH)8<[TLMD3#4CG"])[9AW#B*QO*B7$L5 +MQ_0SU5A`PO8Z@X$$]^&_/"B<&1(+YF82?.A<9CM#0J2T2_Y!C`>E@4?&2GI<0R'47;_V\XW +M1NE4'+J]W-%*;J`4-PU[55VE!/T'W'SP&1ZL>I]B?RB)L/[(7LS_$\LKP:J: +MR%+`3[YGMDY['0Z%N$"?F_1I6B8EAT[ADC%C/@(WO`[\P'ZIP<(^'D+K_WXF +M@&AY_D(FLW1+\=Q/Y1IK!8S&-F&12<#RO;B\&KR/=3L3'.<>9H6U%@< +MQ,]]HXSHM(.>#<9$,-QNX1(-F1!PB<>#?6SEH9\5RU:F[<2U@^JA.$?*08XH +MKJB$[D.+.?;*`HXSCJ1>[,^"0BQH+_R8#`LQW?<=``8G(/D?E;'?Y]T)`_>U +MMK6B!O;'H'EI]#"GZ$9W4"R*>.W66F;,?I"YC!5BH5%[PG]'3P%]]B:$:=1> +MEK@T4QPH*V*"'QR0C).[6QR#(&4._+FU1G!;0^1CNLDKPS!^H-'5HE9>*'GMLQ3 +MI38QD7-#%2*LE6G3 +M?91@#K=_HKN,,9QK^M]#"];(-C"^DW2>L@Z4M3D(#%:)IS>4`^;`I'5<5%,/ +MO6IPT/NSX^A.C$1!_L0=TI)^QJ<_G#X7)5,.7+^E+UAYF*X2M!+#>PU=`T$> +M`I$'8\(2CU6TD:Y[S$`OE!4X9SX6]<;:]RACEGG+=GK*$QOX*E@3]6#"E<,+ +M_RQE5:W^\>T6::\8\L/%'4"M:K?).Z=+[K:1;O2:_4VAFG7?=489G:'80)V^ +M#/.70"2GFZ$Y'=]"8OT_[/%[]_*PY5U-8Z*.CP?IPN(ZV@#84MFBB7QS.QR1 +M:U^%P]$%E*8?O*I$JSTITOYBX<)X,\6%MQ-3T(U%1YY8L#D$#(IU`&WTLQ6] +M4P?Z?P_?^:.O][O+0N6]ZOL_W-^"/MMFZT%>W)MJ#56/#\S`2Q5^AIZW:^L1 +M-1YW_:_M+L)$G7!FC87KZ\DQA0_0"^U.P5,8UDAOTCF +M`;0_^Y,YTW*?:\%9C$$D.W"$H56K$S42O7*;KX]+YZ8FX#UWC?8O(C^#Q90# +M,UGP.[A8FM"#UFF_031B.0A0/KX+LM2O#U7ZKW[()@=&ZF<[,VAQN;@KOWW" +M5E420UF=GC.77!9I:9&"CIWAKQA2E-ON#*$./0(1I>S(FH7'/`!6LAE51J>IG=@5O[36U8^4K`4)SRF(E^H +MAZW=$7RMKBY[9M$A@/8@&%XWQMMZJB/HP,!#\*N`T]SF#%_L&+URREJUP) +M*OUW7<17[3N[?_T^'VK8K/(FO@4NWJ&(?,8JNR.$BQPGI1(%0S;Z_6^O#D:; +MD_]H(/JDE%"S/D(?905DZ1O#\UHWUBH;V8MFLPPI6&)G"0E!>GBYBX;)FLYR +M5$G0()5&>&6BE&B51!3C'$IH$ +MQO)I]EK[QNBH><^A\:@5/=80\/-L+X@O3)GCR< +M&"E\5U*=?Y8$%BGAGIH-=6@^^-#38^N:$=D,9@-5B_FN5--4EL3"DT$X+LI%&PU; +M-@0E43R)MBOC,8/W9L>)K(\(:\]VI2\A>$@#3\\=:CP^YL])?BSH;OJUJXZ` +M@0:6J5)&E-K`43S8F4D(.!G*,<3'3PB!M+L9/[?9Q>^HB*K$>,).A@NB_/@]M%A+1YE8`Q!T4PO3Y'DLZW]ERU +ME-=K&TS@0(D7S0"FDIZ=NTF(Q_5H:F>?D!T>O0:@C$#2E)_S8I3< +M.ZHC-ZBE%(=?/(#>SZQGS`%@]?&M3T53>S9`4E6VV#5#!J6,GW'"6KL^5G&' +M_8WZ5E2*(:RLXZ#EA)>W%E539W55E!MSJO4SC8#8('VM-@7H\Q-:_]DM2M3& +M>6D:GS`]_(3*.M8!@D>""8:-Y?#%*-+OAK6MJ-O7'DC[4.WY0CH.?T8ICL>= +M;$$Y%46,X=KH*JI/G*2:\%4`N#=N5;^8E6'.%(2*?[!DD^#S%6Y80%H7?&.A8F^C/ZS.ULI^J;`. +M#._J0&)--&L`.',<70%YH9R0S1Z(Q\%YZODCEY\>)[>Y[C6,*UUD2!X0=BJ; +M?18#*"ML'SBA2VIH,%R9.]1LR^@$;.I_#(1YI*_+@+'`1GF'VG#5^;$;S$RMP=6#O4"_3V'XFI +MUA'Y-'!6ZDB4!C3.NJ'\'X#NS@U5T,)T[NAY`%.WNN92Z`W@8ER?XN44LTB< +M8;WF%J'&*4C[)AWLAZJK=`[[RHH5-CV,P\NW)@V5;J$0(S\4R^1#FVOI4OP1 +M-T^I>T%59#"N+A%C@/B,K%+K)M3<^S6R%?$VC5N0VA60Z9-I`K:`SJ2I7K#$ +M1K_:GJV/;0`&QOE$-5YA'$.O*$W6^DPIM2D`)D?[?S=LVZ31)4.`_J/9_/'M--WBW8``M'0+]6#`^<"C$7B?0*E+G#VT +M@*_ZS2QDMZHN/D\G)WVS]AV5IN?,"-DS[0(X@Z"(-[_+V-Q/S51]"]\.4GL<3ZZ#];F2D)N?5PN#`R432<$7'D +MY0"S[PP34\LLB,&P%=]UA&GHZ1&C85#+-0;A%$!.LV\.L3A79E)T_HX#$+A5H?!2B0 +M_)+;*JY4(1>JZ1N2?#ZI@2(KWJ[/`$N7!)Q:PE^RF3LR-X<@7@%D-BZ$0U+$XDI1JB2"&L_@WNR1FMTL)X_E6 +M!;B\XOX/0875F"MTBX^9\:5YIL[S:&/+]**TV#-O8R\`J2,&;G"RL8P,@>VR +M7*)Y!O]UI%ZZ)WT.0!(HO62_P=-.V1[A&$$V*7R';UTY!Y&"WIR`5L2R^`JL +MVO(-.=\Q#,Y5BG)L[DTB.U,!G-&V=CPW]. +M+R&&Z(YZ=EE?I_'\^H2^6Q8CKKZ?-*[OF8ZF]+-'Q4DPM`,O6KXW:RY1QXI\ +M85E;,J"*5QWO&V!>AYC662&K,<1HEE+];=_$*?F>\!4#MM9+F%[(P#5\\*N( +M[]#7>:XDY.*),1S4/?D2YO%L'K2.YCX(#U'<"0Z%Y(]B:X*K##[P2=2'I1NT +M[JKJ;&2N4$)<`&'-C@ZF<0E;GMB\-"L7)@,#C41`01:D,H""OYWNA\)>B)OA +MB:J^M4.PQ?]3&QPQS+X_!`VJZZ4@PT:\C^Q>H@K1EX[^V_JR$%E_%#[0[K>[ +M@SGH=(+Y*\9OVT_X4LX5+K)(@#^SB0]^\-)M(!:;N,@C1RP@^<'`H2,Y"F@69:%VD/)Z\DVK7*E;_J+%@W.0 +M>AT1I_%:@&37G=$+X$CTW$E>/'LSO8P/1*/$_6%_"V7X]IH\X5B+0FT_E76Y +M>UN?)KB'V5]!C!CS<`2T&Y?'5[3CMJD,2,11_L1(3<>B1U<.M5>02O+H!-F,?@^YR[@XU`2#[S83?)#1`@F6^(6\*<"_Z +MRI8RK_II;26M[S(8+>2+WB"58#3W,Z_F#_TR3E=#[%!7W]986316QSGC^8O5 +MGK&@%S!MI19*^]CAD[DY%[7:6 +M[L/I3!WU(;C+8+"J]B;1C!_D=+J*&K6HP3;I"3^Q&!`H0`@V$VVKRM%>.`E[ +M=GYN?2D=V*N14OTVZ#.9+IX2&[/*ZPV]^;S`T5'@%^%:,L>]-7:BV@3*"G:; +MZ%05&]GR]-D!XXGARB[A'+S`Y?;CXP'!94:VL:J=]E6O1F?I&0KC8(=ZS9FY +MJK'JS%EWUNHN>9&.K_-4;2'&D/8@R@Q^Z:+FR7TWUC5(76RSKX)<.W(9J/)1 +MEYMO=FG^9,R<,+X"'\J?"FK=BJX34<@ +M[P0CSJ_1RG\W"3>_G!J1G0ZU.$I+.:W]*KZS_\KGRXD4E^=)?XO3ZF2YEP/Q +M/81_[M[,2%4GA&_[UCII2F%D1ZRV$Z3XK"/.5ER.%F(]ZF$S'@JOG`"($K'@ +MC%?P&;*E9#L@;Y6+WMSU3[?+-NAM@/E`F"-<13BN2)(B1S65X9J!J:\)]"CB +M8?8T%+R=C_?+M^)W!B2V,7]CL8/W.EA6C?NQ4I0IO +MDL?GISC;/W:`=D`A-(I;N4[#\RU\=1QN*Z-`J-&5XHP>KZWPC&*FOB5.1DY>0T(&Q_ +M#S5#?.<#ABIIQ0@%J?"IG&+=H>Y,O2W(QN1%.L.#,MXIAJRO$^Y8KZRD +MNJM+MN@?_64["K<>Q\MXLDJW:[V,I8@I098WB;9=:'@!C]*#NL8%PS;\N0NU +MAEETR$6HD847[1?9[PTJ6&7PP5GZYN;383 +MY5;9^:G(/V>/`+QBU'L\OM^47<20)'.)9TK)@M)@N#90@ZH^!]RW81W!SSK*IH%Z`><4F@PZW8&K2&=U5#NMT-L`[#'8L?*,E_Y,`KNP',T1Q +MTEA\'U-*%;+(1ZAU`QA/7=ZWOQU7%AH/#DMD^"U(X:_73G;'&UH;5F'ZCX0= +MH_#AK/&:6&,?8\HI41^J!=:_(W?[&C&LU3<]I.;<%'@0;P;D4I)QD!62\Y&^ +MA%!MP10()X*:RD=H:S%;1TVQIYNTR]NHYQ*B+FQS;C2=$T_G$?<;'ZX4818N +MRE/B/:[^\P#.,7/-,F=O+Y#ZU?ZM#9W6X43YFRKA^03#N,XJB +M8B<'KX952U8MU5CF>B.](?W>P!Y/_6:&D<6ZWO$/#B(B(F'7#\/X(:JGQ$IV +MNOM&;NG!-]J.ZP$7]2\0$99)QX;Y)PNMN1\SE(.C_0!IF&H/+LDGJ=K,22SN'O^++@0N@1^YGHI%6\[>:KRW4#5P6/[[8 +M&F*(K/(/P0B_'[-_H@3+`J2/$`^/@UP#L)\AN%]G[2WW%K"DQ[*+XAGS!,C6#"4'+M)H6%876\"E!)VW:J!#U`8EMP.T[\I=@V#;+^HXQH6:1 +M\N/C"O_41HZL"!3DBJ1R(^)EKL247A%6('YG[L?W[+'I)5$YC9UY;N=#V5@P +MWY`X67RJ,<=NDP%@`\)T]Y-&E(RKNR:9E*'3?Y$0D +MH0./)\<61DA+L68B`S28_,=GB0X@*W[,X$Z-(.T7#,37`$X[[$E`0`U^*`JD +MGT<4TOI3(55.N/?DQ]%O891@<2*T]@(K(%?T"9GKL'S'1#H8`S-KIU-7C.?A +M.^M;_PNO^_SF%Z54^.G(M__W4[P],ZZ@6]8XN'J$P/-B?V6N)L:84"K"UO]= +M%VMH$L\-]E^4E/08SJ@%Y/(EE]!#OX4F`5O]PRIC0T]D,0']PK1M_<'LY=E*-2D4D[&1]%P0?($=&.!$+PS[8B`YDP_*:FG\;6\.- +M:W`X2L-+G8V0[74]F?EL;R6]X.QC/2Y,81<&M<&TH^_7@K:02^D8.[RB_2;! +MC)V.3S"M"PJ#R\(])5XISX&/?Y.PL06C#&LIF[JR.&L1.CX0T#\NJ-*8&"=' +MI-) +M7^YG)NG+@H?ZE8_28D3#/!I%2`9 +M$_&.H;8DB7]S$YX\U<,D2+$M6QV:U]LKBP-(*(*(\Z)6 +M"YV599&QUC-H!.235FXB.CP[/`[]"P&'N\B[9W5<\=]TIE^L&PHK!&L`502L +M6K3=+H?,2BXA"BSX4`"3##E&GS'D/\7\S\\SN9P=VMAEC]Z<@C7I+33H\:"/ +MK4LH.9R?$Q8IS86\)@9Q2.YWS)F;F.E6ZD(*SPW%CEXQ)A>_-\?+.>]GD-S` +M)`C>`O@7'1*"10H\_9O>[A+S2,O#MM;#I.:9I1G<9O_(_#A7L9?--181X^_$ +M4N=K+#4*$88-Y_7/CDYT0ZYS2<A2:[K +MFN%UPGPMM6)[#C[/^J+T%*&HAAG^MQ6Y4.!4EC!*FAS?OB6JW,=FXRHH/99; +MVQX#T))6I/+5SQV1DI)QRC:R#\BW,HQ$7%0$<V.L=>1^#4)" +MZ>@#F;E^9M`S=)Y=4L3>I7F7RY7P5LKP^2X$^2\TWK"7N21/OR(YQY,>;;5[ +MX4ZDC\&+DB_]*Q]1!SOWL!`WN&DB^%7% +MYBCDB#@P;>GP9R9@3E:;LCCJZ'7S@7;23]+\.LOM\8Z")Y/(@O(Z$47&99Y) +M"74CIO1STHS'O=9*#*(W.D\XTZ,<#MYLHQ_>;*+(B*2+7T-,O[ZPM"F2R$#@ +MIM;K[F6VR^YA#\^/FF:WO"G:WIKJJA'08>^U[$KE#5]QBZ32=9_C30FF+*!L +MV:0))%7N8#%I`P^=DYL)PD0=*MC!EW6=QD?9^BX%5TT)S3S:8H+;XW]5Q^H^ +MY_-!WVU2FJRAMS.C*LD8`]RWH8#M'EMH0&_\A\BJ?!EG!A9=PY]">3>:T#,QT5`3N`)[K.B9G3 +MYUZ%%\P-RX\#GI=`D.0A]$K*-A&LM`\LH1(2.8`K^T3&-K?4SADUD>&)S**-S;_LED>R(=KJA8U(4?"ZLY!C4D1 +M8&IZHWR;,OHT?NY>N,P/58JB0`18"O&ZY@$U(72$_M7.WMSP:+VR<4(L6!\?/T1G'%GDRSFF8:T12DSJMFU001[_",XW5BPK-29>#_1('-R\`1BG? +MF!.7C$==SJUY`*[1S#I\W'1N];HBRJPR5;EJI32E1,[)A!6^)+1^Z%.(2:MR +M"\6X8SKVV)!RI=6Y6:Z1$P[/_[HA^>GI@]%<"1`U%$LI[[#S+H%P+U"+X0GJ +M=Y(:Z>`<9FE?Y^DL`Q(TS?%*_J#+_T%;IIHQ#I.JCLY5)*LZ+A_$EDCD%PM*HC2U5D>XZ!T!/74?#@L)UQ%TW3KV[43)E6`W&QO^-F6]%4<39@ +M4D"]9GY$0!SN4$\4E1_DECDG"B[9'][\BK +M:*BFQ5Q?.9P)\UZ&_S%(BA@>)?L'+[5@]T^5B`/%:ZJ%$Z2%C5A]*<%K`DTH +M!8CZ]HVZR[B!`=8FKELS"64N#_TD-CR$X>]2F%.Z2)O.*S%#D/.(`P"+.!F, +M)L&>K'UFTP1%IQ'P5BGK10/NF=?LGM51T*R1 +M)I(/L-';T@/EW6WU[E]M`*'E[+P_`MM749-O-/4>J$,4NMC=2',I!@_XB`EL +M4SPV@4_25`?LQO[8TVD@O\5J(;IBBU3J9I!@>S8Z\86Z%M#G'!OLV:E<]R,A +M&ZBTHTU>0>NXVZ1+N67S+8X`_\,Q14!M?"J`>\KB590J<":](0Z<4*2.S,S5 +M,S]B,%:JS'^YB$6!]`K4CG:CFAC+@9K'CJ'+5H>D7[[/[R(/H]]Q0<=6>C)H +M_)B,R5])>K7C59O/`J$TN7D-S"O&O/<*[L$(.!%KY!V$(?'TT8%)OOJDR_I7 +M5GE&2^4UQ$E6*S:O\*@= +MT@V15"D);=([TEH^U_D=;4^@4#1WHLN3D*>1N!LH+^,&6B+W%F_UTJ?'TX*5 +M'ZC[-]O!CA_>=PRLV9DV:2&(.DG%2=\[8DU;:W6$/N<=,/SF2,+!S&:P9CZ/ +MUNL&D4G=&Q\%9D\/9]K\6QHPF;FKHQ,`J:QEPCXCCPXDH$OMZ,]A-H_9KTQ( +M.TW;OJ1.)%@+R43@,3NMF\ +MQO68DZ&U'4'N!:4?#0V0!;G$$+W$=6&_G/(JIE\II`G$E<$>H)C`Z6T)]5N`IF6^;-I\=C%'6 +ML\VUD&F51.=JR&Y>3SD9D_XDFOE]BQ?\U.?6W\C@?!V-?$*-!7*5%9?R0^[! +M`MCB1.%8@#T'LU,IKQJ.Z?0V#9&4RR9U[M+XX]7Q]THVDE?4Y;U#V4D'FNF` +MWDX;623FI-B%*9(\:,JEH(R?)7C53@N@;%)FU]\R&?&@(ECF&FKO](4SNW3; +MWFZ[FV&M'YBC?)Q(V:B-TTCX2)\<.)G\^R"(PW`$4Z5+;&BX3^OZ?3&/-+#M +M)38%:G?'RJ2(^!\4D[BV@[9<=%'8HSHS#)6U@XVYD'=KT`=(/MV)E0K6"7-K +MHD5?$LPAB]R@CA_82;)$I&3--B/R7=8JBBE;/69YM^"#/<_NT@U[.WA8]W8!_0+G6_A=\PPIK=^: +M$LHV,9EP>:?0\C*XGG72*,G4$>HI2Q!O/YC\.?[Q5MMTFFLL..)].XR."%C) +M=@&0@S.\H8=SPH3Y+7%L0>QFQ^$N]CCP1H2<^&-Y6^ST[)Y]86HF"8^`8O?@ +M&W%2&W!U6Z9%1#BXM>+N]SKN>'%MNO22^DQT08]'%>_>(=+75B_,.06S$7>9 +MA_W2TR[C;<("X(6;W0%U%;&-'9#^__NB-,7#,!P\1%<+89E'VVH@).@[](EU +MI3YKB^&?O&\AGWT<)+\$QUS.\4%XG2"2?4.#VT.`WU@QI2"EK%=,4YV>V9M3 +M[NC0@`ST;G*=N#*,-G$"A0D8[3/[_<0ASW@L!#KVI%Z +M1@9Y"80S""X^P]LI*\R>P&IU@1%;ZNE1O\W\J^S1BDE[I(V=>LA0_[4]&QT6 +MQBRP$"&J8!3+Z8R\N>\B8'-G;F]FS#(6%,)O<]!H+AM85T;_$2K<0L]Z'<9S +M,W;.!6RSIG?<0CN5Z.:=@V[([CBO":6?1D;$UO6M[@-WGM_%FEPZOPAY]'D9 +M]L"/BZ&["I1AC5M2]'-;#,#>D?EE$(V&PJT9)B+Y*X+-$2W9E`E;I=`)K]H8 +M.L\F'X;V"D!V=SN33M\8$J@&3"*=8["(!;CF#O.<_'&C\]&(#IB<@S?Y=!W' +M)>W\\#@>@O76@#1'\`V',VV6.4]) +MXY/3GK[F4_70%)Z9#PT`PM!@ZKC^HE]W$(GB%_.ZW#LH)I:AR85_-UT:*T1V +M@PV3IE+C!]'5]ZY`-6YX:>_?ZZU"8:(3\`)8\AJ'?(.=K +M0_D;'QA"<\@_W5E"YSVH`:^AW)Q'JDB+PY@.%R7_E%L`[KUA^O4'EKL32OM@ +M33:P'4L>;GH@'AXNU[A+.%E*,GE7[+="ZGOM2=$@3@+5(53G%2DBVLVO2D*0 +MZ-.,>%S?5X=RLM%LB#QB?GZ'AA]2S5>J2Z*E&W0HZLL?=CX/H9\C7O#O2I>W +M*EAD+I$?8V9%9>.%Z0.%3<)?CF<&I(%90F)<2<%GYU`?@ZYA*0*7'5DHPSTZ +MS:7#I#3KBELR\25R^XA\6R1$$@Y6Y-@:0ZB7&;A*,FS7A/V+8&DOV5_OG:B* +M,-!#%ZG"]V\ET@*ILFX9D]`KP7\'.ZGL"T?G:^UBZ'^MF%^70VPSW+K%`GF5 +MM4"':&U"%4!W$"/O8_SJC_AVO2:GDF2W^Y>707F]3V\O4YPI-&!J8,)_UNL` +MDQE2L(JU0?&2KGSS5H8B;-K<^FIY2Z4T>UR4LLA0:UT^=!PF +MU8S[E!AT1S^CNB:\@5WN;0GL(]VM6!R2^"Q$HJB[;01));XFM8V@XW'[Z;57 +MO7@ZZRB6^9!$9`73Y-:'OTDE_J1#9;=F6/1R5A.YXXOLRE_A%6-]-OY-_F@R +M(^&93JEMYHI?-W#DA9`YS)-75VGZ4*^K>_*XO>R:V"4,4S`TJILO\EL38!;F +M/AX5@:N9?\SVT/8=6"!9&`[9M;;*SU;FX.;0AG[C@;CD>1G251/WK4"=)8?S +MN'%8"D+*S""$_XSG5J?#T.1O7QE>$^+2HB.=+%!YXSMIX9M6@P%(HHOY.A;3 +MDXV28LG(=;69"7@HX+27.NOP/)$<+?O975R']/QAR\=V9XLX\H1D"#K&]0!> +M77,C$QKKY\\]]J1`$SX%VPMW%^1(SVP;@,6,1E?7:%"2,+$U)&@P$.*G9#:!-I5>X(;8DN9^^W,F1 +MP[90.1XN2DTCF9$H$A*-,5S>Q;$7GV(3J^&9%RFLRUY[W@TL9-[KXYY1:JN$]NQ[`,]759>.?;D2PJ>5]+2C=/EN%?(%N7^68ZS'_'1P +MRZ:>[)^T`.B;=(D'Y]?IP'\^N[T#]PL2]6HML?'".A#WH"+@;I3D0\A#HP?-7Q?+YQ\#:A2[0JQ@N:)*4&*;4?.RS0G@Y25!< +M*0V>1^4QL/D01L<4DW=VN%( +M#$/4GIBR0T5OOH*GE6"M-*3FD[JJ-Q^84V;2;W.GQAN11[7%7[H>+$G&MED` +MXG15'S1/*_IN#40E!XEK#%`7>J\1Z^TQG*1AS.5;F*V''NX0.6^D*]A8'=OZ +M3TK:SN?'^@%4C"?TQ;,]H5,,Y0'4(#2=U"P](EVYQIM:N +MS!SU[.NR>=(=9(0'\=N-X%(/VB+#RVW]U3M,RE=C\M1O\KM')[=R((YY/PY] +MK^NH7UR/[">2#(._P/7-X`%YB4KB4;=_>TGNU";K,#VNC_-MCQKZ!!$WJ]6(:+O?1CD@.T`\CQ#^^"@3SD19Z>X#I*E]YN4&_ +MRMY@J$:B$.IT>R)CZ=>ZLM&_&VGG4"LF3C"HK-22V>3[_@N)KL[-+^8-RPG' +M5)_-!RCHYW1/85C!@>]']52T'U%J`IUY@5"G%1NA$],[P-IZ0J1NUZ'7QJ%M +M&Q=07G!O)._LX+&>F2<+ET8=5NDQ^*P-WEDH/.J"\X=:H\U(:OGR9>,PJO^\%H'!CA +M*(;3`L>/82=?C0R&=8.TXMYDN$LIDR!N%=^H+!RK(8,/(:D"T0[)\(14&I*J +MWK+&@'_!U+NC?'S;UON9\&%M]:):T\G-^E1EC7XC'=9IM8GR_6@KUV'.MWEJ +M%^-5-3\,BN1^ZC<8PXG=V8_<3N[U\1M7<7L()-PR8Z2.8:CM\ZQ-O,((HZN* +MS*:&Z2-/E*5;C# +MP.#7VZ)XOTQ+/];"854.X=@Z@Y$G#",/(R\5]4O@-<]\:7,V$?X>42QE2:R- +M:)+5[9M)D*2IE4RWU_0;![DF/IO1]V9%ZX*NM[UKS6-N&2T&=O`/VFLFVX). +M.!?:_C7Z'#MYL$L]'J&5E;B*O,&=S1+9:D>B+I'D-&3;+8/1OPDQ!HNK +M>+OXZ3F_QH.V(:@86,U2-9QZ +MH"VO=&L*Q-62$]M:DY0QAU71:R?L:G_! +MGDS'DFPW"7&^FX@$6D3GO3FS!B`*MRV(L$^A#IS1&7-=Z.+DY4Y'!,5C.78R +MBORS./4RT=H*`+85-#GT3V'72&04.(DEI_+6YIQ>'*R57"T2C?DS=PZ$*-@T +M_!)4[Q#Y7;2$QULP.:/XA4>GG]TJ-L^&7VJS?V[.>M2QAM%7D^^SY_ +M7LVU4VDU'@PD,)'HT\QV&C)]\Y*T1K.1:C2X?)Y50AQ^^=^W2V7.U\Q=Y6F[_6(5[WV/7\-V^/1'=;1GZD`"VT0#2'WO>/$ +M-#Y/IS)W;I?5$?O08;(Y=1#E['7Y(7Q'WL2/"X:R\'C`ND[ +M]R=AV0[!<.:P5X#LFGI3D&7"5D7R<)_QD!@IQ.#"@=&9N:;X%&'/R6!I]S9; +MHGM!%<6Q2O685D"%A/TE6-0+`J*N6I"&)99*P`FXB\"KH*3#/C9=MR.*<@@$ +M.D`0!E0/;M(B-`Z"BNA/I;=@G$7,O;+F.?MIN9Z&2XK5JTC*6LCPR(86;N?N +M+,6O5X$*3J3$_(K4L=C,(DU%UUF_H0/T\D,E0F/!TJ+,-S"A#;)<6C,AOE_1 +M\D+U?=/LN;*_XM]6/N(!\=AT..]@D_JWWT':L@+,@GG>7&-BADI$:XP9:$-/ +MH7N]7^.`$_`V6BY+8_#X<3>#GL#4_I[K4F9<"IG0]*T'/D(*=7J1"A0V!+\Y +MJ$*013'P_$D/55TR)ETH`TD<.<&+XK7E]^_1D.MU8>E!Q);P.G^$8M0^880A +MOBU^_7&O,>/P%2=>TA7Z$]$DM%JYKM+KL@7YG&F-?O/NE-;DM*IYCL@<[\5, +ML=V+"BCX0E:.@-LV,KL;!]GMK#;X:DKOH7_)00M"'H>JR9+/O&"3"_DO>M`[B?-_`I_.0IZY'#)/<>CN9N>"'!X# +MG5-+28G"'G%AH9\\M[7,?C[>Y0=XT^VHJ5OSQG&-R0OK7#83P:'BD01V0^2A +M&)^.W11>NU.;^>C;90G\'R).4^S2.EM(\.]84[OM@"P/+BI/.UST/;-YHZT +MFHM0A]2'K([6#V6OF/!C';:Z8OBR.9,7`3VYM&`A\3_VL$_<>PCYU5($!BXF +MJ-]=6P>>R_2K#/9FE8#\("8U+,!?8U/_&G*+3=.TI!O^L27>O46+;[7(&39& +M;R([::$!Q_I]UJEPX6_>Y1O"8EB1`=3[<&"6=KW,Z]2#&T(:^G0F6$ +MU!XY^9P2-O)XD!GXV#_F05J=B?O]B"T!$4F!3^KSXU;$+V(W-%:S(B,$S[*'V\19NO%8):@D4^FB--6/ +M+?0MJP=U",K:/,3[79&JJ5AOK;E/@"IW_&;V.Q+[=4;!V7X9>4(WY%;$-;,YDTJ#B64C,"7J6LU-Q1E/DE.CFG2+@6.^P_$ +MF01[;2H[G.[SE]W1@OV$R8:JP^1B0^3O<7G*9J-*.&?UIX4@U4IFHJ($L8%> +MY(!'$L.G)[_@1\Q:E1'R.CS7[/0AW\>6-@R_JTY2)]-B!"YT!,L=R5^+<^^Y +MW=?S-+Z#^"/6S`^:>?#29X:H]S8&QCCE9D<5:&40Z#RCU$#-@LO_1`\IYC$H +M3V>-^8DM2*_6C3.TXUH!F3D>1"M2-KE4M&>)PQM$@8BYD%GA6`#8>>Y65\)W +MG2!(N/:1XU.0P<)Y@,4:"^M``2>+Z2_(PTXW*1;=2]E=A^$^'MBQXC*%+1#O +M=MJ6SC@!HK4P`!4A8D)\BQ7XK'%JZ,V2_(1%[%8E(.ME11&(JALZY;6&G*]IV,V^M,9>0Y/'#'S.`YUYB +M)!W?^B>MCQG`8ZQ2_53+ +M17:L*226!IIU7&'RTR0VOZKAM6@+X2J!JJ**3DYRISL +MU)%`. +M0*B1D[027B1,""NFB>NR^HKPQ-Q*,JUZ3B'?[&XE2A2BT5]!!L(I@*2SOKB) +M,].)V5`DCZ9OE4P2:#`%%+7@M5E'3#*=)A?3;=7LR9`&S;%1#`Y,\YJZWQ2Z +ME0B'QE$;BZ\/.EO-&VVN0(',DG/;6:U#\4U(]DT\=81*%2:,/#,^V^D0D-.+ +M-#&O/$WHH0ZOES$8/Z;P#+3\1R&+V#%Y.<\];!;U<8P+,13>94@*;&D[Y`%U +M:4<_&WL7>B^:D3R*E^M<(HIWVX=`7)@/`@4O56%F0NU36E32/!]ND6_$Q8W`-MQ-BG0`?@[W1F2(4`_=6?FH5A3Q[)A#T2`/#E^@>$MUHK, +M2J[7:"6:U-S\M..QVLJ=*I92B`+G#OC61<9Y`D];@Z0^O21Q@DA3$ACAI`YO +M"$GA<;\!V+*MX)=U2^U`3`3YB_VE;2=\HA_)6T_<>"67=/$]"`EO:+SRECHL +MJW)[(GWLK1*C]7+3B4UH15N.R_[:\Q^>.6D,ER"A[K^Y?0_N_,CG0"_RQ-9)MA9O/+W4`8_8_C +MW/.I+>>S`B1UIQ*3,`B(K=H&**B +M]:.I[!VJ77N2N7P!ZJ,3FU^C".M0'L57R4OK;3A/Z_`\ASF#N>L!DYX0BE:;?V#D/82)!MVEUP[-TAHY%OW\*1`E0[MO5/3@6B2 +M&BH'F;)/%RY'GOV*>[)K=]O)QXIRHM6`#0/Q5'3HW/=>M9L+)S[\"5RTW(#* +MD53,H[C:J4`&F@N%DY>NF&C&U!M'Z*A&0W7$FS(V/@.W8[U6+EVQK;LXLPOT +MN>:-MWV82J`BN?[2$K(<;@AYWZYQ1UZIHM96D$\'Z1643EXL*@$MV[,-F-*!B*H9,Y +M7FF**+-1:Z\PB^DBPH)?BNRX'AJG?@Q-"_D_^8@.NVW4;%0;Z-S6@Y*;]\3W +M"9/(`%F'I+H\24(:_[0G4M8/.V;9:Z`#S2*?;776DS/JSDKDN`K?1`.4K"/W +M8H.ED6-KG=$@<)9(,4]>/!W[1629U[U)<"B% +M@*[QJW4BAF,L9!K$67I@R'^8Z",((:+$60]=C-W?0@ZB?M1:D1-%07TZ2WRF +MAOU2:B[S,4-Y8XK;Q29(0\8'ZRR0DWJADHN`.Z+=$J'P`XI/)_I.EL*E@O`, +MV^D>M&R/P0175T3(7>9![6Q@,7*)HZ.;;X#54L)6-K3YD!RVS=.H7+U[>4;5 +M&]8N\!B[3A:54)T@A)?;5PO&I-.+U)IW=B^.6XVZ$(CHW>;L.F6.>9*+A8AJ +MQ%)2%^5)VYLKE7N=U0<$W4@$Q%;4TB9V"][L/-@`/J=[38W0DV^U]L?'C!:` +MCTQTS[+!(2\:+(6*F[RYL7OZHZK:>W6`ML]#_P0K^T30G^(B,= +M*?<_BNDDI<$5BWGHYLA\C?U*\".[-TN$.8[(GF^@C87^G@)':&*?"&@SR&6T +M$M+]LTT:%<])W*3'FY\47K@03B;S!ZD2I)LE/RTG-C"4MBI4P$A8ZER;)UE+ +M5B-Z%9Z28A(4JJ5LTMF:IJQP)AW2$\]@BEE."#:P$_+["F(27\)+-"5P@3A)5[R<9;=1*X7 +MLEN8TH5Q(9`/]=7_F/96:"=M=HW:0M$T_83O'@+`@CS\'>%$&?HK"3.MVC-6 +M:4[Y;NK@GBNZN]SLW(G\)C+UJ]E,LQ!#LPY/YHLM,UK5\[1RD<^9\C\=Z$?O:0X +MHLA-NC3.^$B+XNODSNL3?CMM[,&;JOR/V3)/4:O^17JH8]__Q +ML'%$[,5PW*Z5=KX7@:8I>_"JUF]%KH?+H#HN254G?A=B+-W=PO%QI*#>_WPL +M\@,55Y%O](^9P56^*V[M"8@GW3LEX8A6-1)OLS5/J8@+15'HT#.&-3J$;V39 +ME^$1(A6>[]@WXU12GY)N07^N!_O$(RT97=N.QN<"TOU%L``.$ZOUAK2M6?F_ +M+UO*&SS?OUC0V-6+6?Y]R[%YBHF]\1G3TM]*=HKW$EEV97NO*_(7C&M68<]5 +M31HZ9RT$L:2&?N34G"JA+2QNSYD(LY-?6'K_=%`>R_GE\2%KA*V$M",S3 +MX5W!#:P0QBK1X.^NN3#76#S]`1<,E,(1W'C$.9;]_M;>52S<-/JMRQS3?*A= +M'DA02P,$,P`!`&,`C+`.10````#P"@``HAH```8`"P!214%$344!F0<``@!! +M10-?`#28^HI%'0`#5=9G6#6"0,3X@]5T*/V4,LB;4>::\@#`J-R+ +MU7J"$$GH'*_\6*/*JS%\RD*^0`09`Y>%7T39&]JDIFXA%/Q-H9V.Y#["DX2`>%S?CNA+_%QWXEX +M.7_?L,3F(^K#])#!IL3Y=AJM;2F.!^+]`5N^:8BE`$S\9HA2"1-*TH#0N?&J +MVDH]!Z?NC1`FNHGW[\X?>:8G;5I1-"JVVO+?-!/_][K/(L6-XRYG`DDQS741 +MHD^G&T0;.9/3N*CE#V.'=LZQ7,!E=->E+_I6LIA]$E*3?M>-T=Y_NF4'D0:\ +M,9ZAO]J>'<\@%]RM"!%<29/YQ_,6%7E=7L<./!FU[[BE0BKH7VYG7TPUN6Q2 +M?'^CX`X+A'G4IE*.Z?2:I-O)6;Y,#WV6*#+Q^UU-1_A-WV7?6_&>9@#@1UU1 +M'(X5%?4_QO"KB`6.]8'6ZMZN.Y%(/27(L:&Z@@1?7&DNO5DT92EP;24/_%+? +M#=@1O4_1Y,X>1J>_P<4Z,V3/E:@T7PM%HQ>-/M%@(OEB^;U1V;/\A=N)VR):BN6$0/D`U$N59Y5$] +M'=!GJ2@OC;Z3\88IS7IG5&$2-0`Y$R.>1\N!]&#>H_9,ZE]83WG\GC#\%J:Q +MHG;$4\%K,NK"WP>!1^]]HN!Q\!JF!9L7WW)?:5& +M7CW<%/TT)&:3ROA!=#`6Z%X%C8CM8J-4W[?P[Q'K=-=/7T"Y3@F[#!L`EP1I +M\BN.0)&>P"J4J-6)F=$L^:L9/1T9-2SF'SU:E9@%$B!%P)#>2?M_8D^!9AZ4 +M,Q]/)/(U@@+KMWARBHZY7+\4)0\?=TRF0X=3.#*K103_&X7O)]4GSIKQ&T5C:+__!5Q[N+B$C._J4P'4$NJ^;R<`+G +M6>H,/6P^.ZX3DF-DBZJB"M414&<0:/3#4;TD(.?1XY_%6T.[.S+OX8\1QV?" +M)GH/'#C?R'+-:K\M;O00D?WA1MJK6,DC4!;^%M`+-#V]?"\QM$,Q19CJL^K!OLMZT%69.X/^)`".NYM")U5 +MG_;/!O<>*P;[^5GF&3-N@P"5"`T5%9Z&4B"&U +M)-T'F.6L,B\-U>;J*TNC?,((EOOEQN3<]>$K^4%%;,S.3A#KF*[@(UX$4*\E +M\Y"F2F2T(7%L0G#.>4CO%$J_/L"5_H29?Z&V"W](S([!U]::1L3Z:[-`/Z=+ +MR&.VE$%X`#X@T`82<-E(<;U#T%;<_G`XL@B?$F+]"JHSO&YL@G-L!?]WJ`"[+^$Y^6=]&BPO&HE]? +M0F8N*H0JCM74G]L3?FM+X#Z@>$M10"'JM_2!P1:C:]N;V!+%NT1:M^)J-W;U'J64CJ"RQ7&;H0GW!:OLU`7 +M[.9B@K17NIW+3!3&)N\)VOP&R0A@ +M57LF'U&[/*KR(%S5>02-S$VP_O9D\(GI6H\LO_C)\4GI]YC#) +M3E)%V:,#SXLVG=-?&"E.Y#`NGDO/UA(?X6H(Q;YQ8/9\%O[4I5'EI26$'R(< +MT0R1*F0CDQ@9ASM8;QM\2D=IP\^H&[[8QS.(X;A&_5`?.TXFF_'+(=NWP6!3 +M_M\??DM8[,LOJ@8\DJYS'K=%?='W'P'3"8H%LXBD6V`/S2"$<_H,4RR@LX:XOX?;MO-@S`"Z6I150=]IN=^B2$2`<6M;F +MS>WB]5CL_6)R,WD@^X\\87WJAX'[A>PMX"ZD;9:C^Q(5-*7BLB.5)]Q]%MM+:JNTQ7< +M+3^]83`-P%]Z.V7_TIO-(_^$:5J(IK>7)=,87/]-YS4CZN-QUD9'3.-KG:6\ +M,Z*O))Z#C:K2;@Q,WB)`KU,?97S-^8ZC6[`D2Y8BJ\DD^U9* +M6VQG4Q=S6B>(9%=$T[:OG*UU'^`/W@GE0\/G/_& +MQK(G^=N6:NIT)\!F#+A02TY*I#4*@9[W4MQD5^U,[]9=?XJKK2@*/PZLM:&J +MV$9V@]UUHZ.:':A_K:I]8=E"4*Q3Z, +M_V'G#!3NB'JK1.0X*(98=*?LH')M+,&Z[HW_/HJDST8HF'TK3$-_T:=$-2!= +MZP$N24U$5\:&JINR_^,QX4*._^>E)R`'%COT:NORL7A=4+L7>)M.4@I"4;8O +MW$M(I)X2;H^0$4F?[CE02P,$,P`!`&,`IXL.10````#($P``FW\```@`"P!C +M;VYF:6&9K-#`?1A;!(O=BR:MH4HP(A3+W`U`V:J7 +M4+U8&T`EX]!=<>[A.QG!FKSBD69;D)=JRW6R@-:_CO3(OE*Y;BF7!!A?B`N_ +MXX;MA?%;%==EXOD.4W($'&':$F5M-"^D@I?Z]7M)MTN$##;LJ"H%H\4/9=T5 +M6HM<,!7[`.IQ&F.EJQES`>_FE+:D<^IY)^7^WL=M-O2KZL@Q_DEN?X\D]]E= +M43HT%*]"$/P\+!5=3,A26WWUVG6WC:',>$'\/5R,(_BZ(8GYGEXZVN^6UN,/ +MG=;.]*UYR#O?![Z(_X\2HX):6Z7@0;>LE$U=H;=2LT-+6*]&^L%CEUNRV1 +M&I,W3)V/DL*6HD;/2WQD#&I\BI(/HE9MR&!*;=O!F>S&OIO(-H?V960(_^[L +M1H#'R6B4`LLH@6/A%"%]RTFKPS2%J)+(1$\6+7?4_-A9&G-%4Q%_'$F]T6`` +M*('P9SEF'IA43@UZK")#5U)$H0E/E`[?9)39]#\L94TYL-J@2:Q&0;#EXQ*4 +M8S$F;.C.&;Y:7@C7^7&\,AX$%*UUC#GZR6$0Y+]=ZOFWH_8X26M4ED,Q4?Q< +MH_OR=F[0T_*CFIA?.-R`S*A"ETNK)10(`;3Z"9B&&.`43TI_ZG7E;7\ +M=9S:`?.$(D6\9HEAQBE=V>T/\@9],@+GG'&W;Y/<7<,^-"F>`@=UFT:2V>KC +MO+-[FA'W8Q4]"HAD_CL_0[EN#;H=^"%#EPI0)VLOW-`>Q:;(YN?JVX- +M"XD!41@JV,I40%*F:#1H*KB[&5PJH$U=^-UD8G1V<9W72#`7U89(#:("%1_< +MB55:!DUCY2;%X0JYIOX'N:^#F)4%29D%V7/=<4@M=6,?,3U;@-D!:!4P!*I^=>/&VO@@8SK4007@8$*10T@9N$8!2>=%^=PO?5FEIA.(]##AJ^=P>68^9XK +MX8#&6QP/*F!%NG%C\-6U:IIFB*X]8-+T?-U8IY4Y(?F8B!/3_-T8DBV.*"\M +MVPD3O\3M410#?RFM]3S=8NYWWB,9&%7@G[W +M<^'`,M"^1-@1[:MOJ2\G>&QW^APCP8QL$RWBRC9LYL(1E"01N9K,&[/4`8-2 +M"0@!1*'($`J`F3[,#MY280`3'.UO8U+NB>LQ\SG:I#$*#XM,W4\&1C\]Z:6RB1A<+8K1(\*]TD>ZU492AO3*H4OX0RUVQPJ +MB4A7IL!)S=^1T:BM3QUA1T%E2LGY(+!D!6QWKB]_,G0YD7HB`V+\1\K=)ILK +MF:HW1$HH38YIRG/$-R>])"QT6>JNUT/X/"J-!MR)3#XS7JXZ#JOJ>DU?':*>SMFI'<1+Y_QQH`DN[2A;ZS.\",Y$"E")Y63"0@G.A8XT]QR9>)0Y +M,J=E9?GO786XW"5A)2Q#AIX"UQ^^P8W_.)56#+TMEAM;V8_2JH5'':6Z-_\Y +M_NOQ/)X0;<76P>?4190)<>4 +MVY)<`3%"IS#"Y!E5':?W_8:.*JF'^CTIF4TS))#*S_5UY[I4@8%OOO^SX_9(XMZ,@TAN>Y\X9'7'P+'R!P$A/4)RV'J +M?:2?76"A*1`"3^TZ-,!J4_N20(Z@I.:J1HC*4`_:1>1#));)9:\5T0T;J1K- +MAT%7'XDR0%01:CP"KYJR%Y@&\YQC_;S?Z($LIE*R" +ML5[W-3#LD<,%=^PY:[IND%PE!3)PH5R;IS!F/TZ$#7``"D,M)2R`M8S=Y%IN +MY%#7866'H\`&*!HC_7MIO/+]HJ@ZY`,6 +M<5/;&+*$PS3&"%<&?9RSTTLS8I,J6JI=?\7?JS^">],J3>1N+NSL_\]$PX\] +MI23;B?UE/$9%Z?JS1:8+EP3T'&&%>/S71!BHWC"2(7K?B?83!IY]H:2PL@Z= +MS3C\W*NH<"W5-"0&3-*[("4NQ7ZU?'&?K;T4>`X'7R%[*'-W#C"9A +M-DHGTY;>2W*T&+FB5L*^PQI-4#YH6.P3TY%G+4H#]Q8>-[N:8.M=K$? +M;P"(9Q)F"HR;;+\.FV3[0&I\]BT@$:#TR;UH6._T!,Y;2JS>TV5W-X7+F\#[ +M\+T%0.]DZ0Z:UC)K.*!5DIIWTUG$\^\AKBMU.+L!5BW[`RVGSK1*)XM%.)*K +M?5VV8FE0Y@VOH%ZH= +MPSH=>P+A*$G0CKTH=XD,WAAN2:`&PS)B+J2*9W]O?1*1Q.06+`W$ +MA;Q]HZ4YX?G/8L?09IE-PFIO)3M"C%$>2E.&BK#46/NC4ZTPO$\]^,1*NK']/7(N7!70A`E> +MX*=I"GX0P@@`TR[8?/DW'V'ED^5+LZN^=!-])*X146.N%Y8*#OHC`"WW:_NE +M/E.:'1DL>"\?(;B<@W>[=$#8:(0`/4><@3]9!_9>2)2\5$R^\'7+4UB0`,2QC*])@#GC2)$$2Z&(8(0Z%<.(2O^,3-SV-QK$ +MV]5!$,%`:\JY;RNU$(F&C(KARTX0RV?K`KYC``+SV?PW$3<231WM]-Y=\7-:#;FUE2E*)H="(4^;Z&>E@G0J9*P#A&02V:;?Q&T].&%?$..G<]H/(#/D?8N@`J +M"$]'TCF^:&&TZ/H6[`LL!2;/#?Q`F!^S)>LD7XNE@";L""#,#%]U^J@?S +M>%QLE]JJUBH0Y'CF1BPQI)M,U*R+S][6W8["VE5ZKQ4'#376..,(#2L)]BRU +M^P"P6*+AA)W>9[L8S[>J,G> +M<1HH"T5"ZE/E)[U=F^&987+5O);>YT'_V@+([//T5RO=@*.C>_>$`GORJNLN +MEH3X(G>]6G'KD,$OF4'1)HCE42R960M"_UU2O$#['R49&"; +M'9JM`CTFRY8%M2B^<6POD<:C]KJ%?@!'\/W0O!0^H_W@>^_[(N;LG.]'GDD. +MK5+?%/%CQ]'-DO%?%RNC]K5^\6]RYD$RDRNBW#%ZD)E)*K838\%2RU5`(A.MG&B:VG)YVH-HK7KDV2)+ +M#'E,4U+91^%3OD5G\1:UL"(%JF3HA8(!-Y(9BW9Y^9K^!_/7^!^/WJZO?*DL +M"P`N/%N?XD.TIG6$`KEO8@5HHO;@#$99]>D#)E;><_89("CBSHW?DCY2)3;< +M9!X#V#FG^;'XQF1JNX<3D"3RX&;3GU8A=T]UZ@4^;]TKQO"Z/XSQ.V?,HRK2 +M4@$L3534!&DCT[Q1`BW%SO^<^-+KE/->Z`5]K1@/4I&CL\22\\8"=#C#U>?1 +MS#*&;F0%>C9@7W">,FF!M=BM_=0T^WH*Y_&]*J&.[YRSK"+004&^G6*"!S%= +M[[I0Y2-[$`SHML)!"5V>LV +M(CI+*,QHF9UY@M:Z"@@FVU]ONFD+I_+6BL83K +M2!8ZPOCI*S4%4H*LDD&K>=?8KK[>^U0>"KD`'V(GO3,LGIK=$6F'C?,.R`0^ +M%Z#P3NLV0=4Q/(]Y'H]9_(SJ8H-QW935HX +MEDPNU;CS7:<(>6!VO_>,$\\)08P2Y6U7K$=%OJKV3FL@8H"Y'7B=4-[3Q``X +M<[;Z3F>-/UQPT'&31`[I1K@ER,0S<-DBQ-BHB_"N@LNYX:9M?8X32QY?W`-+ +MI#J(H+$'%[46(AV1:%X_FVTBZDNL9.K._DG`J$AU`.MR_[;Q*TD_.6K^;M]`@];0K0ECTX;O2;5KLGJH=J`U?^G1W/9Y/?Z +M].]^QFX%NYSCMK++TT#04X.(3CO;M^#0QL5MOGN/?WTS5?N/%>_)P7*[EQ6[ +M;<8>R:IZ5ZHG2/L,@0OST#DZB2%B>5H:+DBUZ!9WE\GN]I7D6'1+C?BX8I$: +MU-A'D"$*ZSNAUS5A991Q7P]4?EI*GIC=-"4E[H@\DWC._(BO6WFK`9XX"M9ZETLH4")#9D)0<4OH>$X]Z0>JYLT2U]C\/ME#Q^U3 +M9[!:/@L-NLDL-AFC;]V:A5,#M5FL5J"'[];.GHMT+1B>5N]"^VT$)<,?P4PY +MIZYFW0WZWG`;\-2F*P(]XEB<6K6]:<>+"JRT +M_1D]0FW>?-()+\R*BQ@Y;Y!6#N(+@%D+^KG<4'!W\51, +M6WP5OBY(^9*8')\V,$;5IL^^Z'`61JK,9T^F#US[+`5&L7\@NC;;]%SIPACT +MIR`BHT=P6[._V6%B6')MT33S6SU<&@#KPSQXY3'0-LX(B^?RT^F&, +MNKAI\'0##X-\H084$PP=%;S[J@?[9"&D:L/BPGP@DS_=T(5YTH/'E6#(Q'MI +MNRM_(XLN7>@OU>F@##[B.BE`^THQWMQ/,\W1MISF<,N&+4QILSK%7T8[8/@? +MV:I_-C/$VD)H41C_32VT?P`+=J9A-90HIRQ<"AUG_A/`K4T*(7//[KK1T"<. +MMK<:EYYG7SQ0Q@<--L.FQ^GVA:F$DLXJ_"GV(;VS2LBX'DM1<1IP<:IHZFKC +MXB56-M6V>"0F@7E##E>!DJ/]Z$64BM-L\H#5"]/=G%O4$L! +M`C\#,P`!`&,`^*XC10````#@`@$`:SH6``@`+P`````````@@*2!`````$UA +M:V5F:6QE"@`@```````!`!@``.(/<+G'SP$1AE7G"I[<`8D\5N<*GMP!`9D' +M``(`044#7P!02P$"/P,S``$`8P",L`Y%```````I``"M<@``!``O```````` +M`""`I($1`P$`3D574PH`(````````0`8```\7%,#N,\!B3Q6YPJ>W`$Z55;G +M"I[<`0&9!P`"`$%%`U\`4$L!`C\#,P`!`&,`C+`.10````#P"@``HAH```8` +M+P`````````@@*2!/BP!`%)%041-10H`(````````0`8```\7%,#N,\!.E56 +MYPJ>W`%&:U;G"I[<`0&9!P`"`$%%`U\`4$L!`C\#,P`!`&,`IXL.10````#( +M$P``FW\```@`+P`````````@@*2!73+#D5-F]+T`A4``)M_```(``L`8V]N9FEG+F@!F0<``0!! +M10-=`("FO[LUN]5/O%Y/\T*]5>ZFRG[\#9J^` +MF:ZW6FK06M\B9M.9\@8NU&"NYPG+`G]S!QG:J='SS0( +MZJDX6N]?-JP\02/WMJF:I<9++GMX6D0?(\K$3R++0*L4==_\:N4-ATO4>0@Z +MGT::>U4Z^XDDF\((-V-.A(-"H\V33\?F7`_O9JMG48`C1'& +MEBD,VS,T*$*I)930?M+66YR)Z.Z*.-,HP:BGBB)R"J(PM"`:,MS0D8^+J2X# +MQ*]Y^C;%=#4E#U)Z\`$/J]/?=U2G%HX#%N[3H4STQ8 +MD84#<.^I]8L]EHMD$>TKSE/D9!]OY8W%$8O/N@1OR1^24$ +M;REM$[5WB&)80'QK_A1;C97>2`]^-AZ(=UEY?!5?:5'4`<-\=]A3F6Z0%PY$ +M6USVD?()9WD.+&_45@=M51S(<9`/U(<]MT8@+M/X!O+T2-E?X>#3T"2Z8]/+:UB0AV/2(ZFJ +M_+B5+&&$&T-HD,(?"3^'Z+8[`<8*Q*-[Y8$OS6W@FOAY./[]<'-UYKZDQZ1; +MGU+P!:^U\DMT1>U_29'VMB9QK%^J2DO`W"K!GJD)4SFQY-#@^]0`EP<'6.?S +M;$**![%"D@87R\'&P@\!WIBNX&TIX1!F+@2=)D&<&E0Y=0H/QW:5UA#Z<-]B +MHN;J&[(IE#1KR(2MB1!RM2PM#L&KP+V*"@SH(^8R2JS>]Z<5RP5CO?;I$OZT +M+>/*3A8$OKG:3)SZ1W4NXT5;QT-D_4'<4N?(Y>G86KZ,-P9XROY+F?L'3^Q; +MM*,P.G#8O\9O?7`V(C6,(`T!OZ9]?`@F^.*8=Q"TH`+7Q$' +M2F\W,T8^U5)."F=R8B-Q-Q34Z[47321[0NPLBW +M,H,`!A&?"=DO,^5]VY."\LJ^Q*OJ\=L-`="^XA,3M\1_04+3DQ-FZ<8)KW4I +M/6')W.3T\`O@7Y-7*?(VI%-I4A?#U/;,3?9@(1ZV*L20K=984+\W:\.(H^YC +M$3#`.N\Z9['%&@[GW)Q!JR`D+?4.BD?*M!A>8.*'_$1G.H/P.^SV8E8X)J:K +M--I+,W):%.EIFW'$J[O\)2%*,5;,VFBR_@FI2@B-ZS8QSCK%$YT!N3?@47(U +M2GS_,NT-CU2+QR?JE.,F'5?ZBEE=KO@D1(GS;IS,M!CD$F-@&T=7E;OS_-)6(`)4B69F[V[@.PX?A +MZ=I,`:/KQK!ASOPJV14&DW$%BBVN71"O546XH[R5;VTU<>0(W6RL`-9T8GDL +M*8*IXVT#VA"NEW0<69\]85OF\>P;<&WVQ73C9082TLF"W)`:6/HK97(D9"O% +M]E/\=D+4XRFI0-4DN(%+&5"\9@D8WQ%,#-D91X!^+C;<#-%)=Z7P/30T4,Y? +MS=F@(UJ0PO!"+HJB0*+4P3`+K-=1Y7IP0C*55'/\;RP+F(QZ+36C?*E,Q$+. +MX\U]F2$6:SIY)I^2-3&A86*=Q)O2\:?^TE7\C1"< +M`-/?T3CEN[E&S+/$E.%Y?$I94,*[H\O*"#?QZ?4WK^9&1XO\)#A_97S/FGNI +MYALKR83X.8O&D8.X]HDUUS`6S5CI@.2(12FK/."A+SD%_ZP]<9)'C*TQDE&G)N%-1,K95^Z2[7F2-_(VDJXV"0\OATG``2>/, +MF&D)EOQY%M%_I/:Q(5YL23H]7TJ[\@-?D.I,.^Y99UN!Q[/XL''U`P&1@FY) +M\C*XD#`O)4_Q&WTU]$DZ8'^W\RUML(.)A(V#D#E`0`>%UX59J^8WV+^K?3<,B47<>L/NV +M&7,L9SS'ZJ,8E5P/2PC^6,PZXX)S#KWH;#"\])STF&6G""_@M?-W-5X8U7[L +MS7+HVI8ER6H]:B[51F$9C"SD7I3N]/(&T]+3U*;/U'GP10RP^W`)`[3K3P0R +M,^B4#OE$;(8I5<[\B"6?N7Z9AD@XJP1,DRVX2`F9_$IOJ&J"6-9-$-"XOSRQ +M(M5SEJ.OO,H[:(@NTKI/'WQ`*MF(X(F)M,6E">92_^R8#V%O]T-"#[:`B:/U +M+C&O*KK:RMV^3HV1H@YI+M\OWES//HW.'UR[!M2"=-@_%OVP?VSS<=U+&J7? +M1ETNPJBUG!8K6!K!Y@L*'RT*R/%64^1;6/!']B%0O#_'Q&2#_EBY5@7O:>5[ +MAFI,_O-$)5>?0&7N<'5.@2MUWO0K2*5O";Q5A(%SAE8Y4&I.(I==%2*77V8^ +M5_(SMM$5,`$I:&U)65/[O9CN7%YA!X$6 +M!O??-,36GN+[*B2H-I[>B*.V:5G+':C6^`^!T<=/98LA0-JYW[4#/-"]S'N= +ML=+1N08:@:8GAR96#8[FX]$]&$,*P4=EUA*FJ0'"&@'4)LX!]9ID3)K7FY2> +M,6&^&(6"KRI9CW3=X/5T472EY'`CY6TZ9)B1OEZXHZ*QS'%:^$K>XH3LB!Y0GW"G7\7LC[AGU0A&RD%];(P=2.#_C5`&#C +M(18*>O%=QC[?.^2(5$Y*PU:M\(<[AWE3=8N5`%JCB=]5?(Y!3&%,5&(!#,Z= +MH60'*1(.B>0,M^O(O*_"-1K0LP34`JIZ$D67X.JR0,5Z(I +M5-D7O.*AYEDZ!WOV2VT?8U%%[;HM?P@/IGWVJ$Z"(HU8A&4U`=I92K1]MM/3 +M,E"V;AT=D6`+]-PJ]X-OE*FX2/8MY""8"7>-B,S_#D2%<1[LKQ6\;X^SY8J\ +M:"?'=I+_WEQ=E'^8G!MDEXLSW]7,A!G52;>WYBJEVG7G*CB4,O0>F0+M2U&[ +M$I./,K6"Z@)FR%AL+*[,@>@K_.RGK:*3BWP1M_OY,5B`B,XBFVM`=EQ"A]U\ +M`+\V5Y/*DP+0I8P28+=B\[84X0'=I:DNK9NS=&)CU7R +M_S9:9W,84&OP?^&B1$9!#I`Y7M]]'2U-@X+=%)>:IVCPMG`5<:>%!N;+I#;, +MC4S^:BCP*I1M#RA]L%.!N+(NA%9*%EY&I[()2YS7K%<^\\BP-)=5%@&+I\!( +M.]-O"DL+VL9\6SL#1XBK4FPPE;ZJ +M6Y6VL0$:PO9:6N:`T$^D84%/A3^7ESZ-IV!4 +MC>I%:A;&/AY_$K&K$@,HH#)1L&E7!3\G['M:#)W6^WRY`<18>,^;,%`<^C!& +M3>QYN_+6_"[0^=Q6H[VWV7*RKBG]'&RY*><"Y:8*ESCK9(7'@,B/A(5NY`-- +M^;(0IU"'NX.MC5C_A:&A9<2<^"W::C-&+3&+`[S1MJI"[KMS^/)#]VDO`4+-U,/YO9SV_)VPA5$8+7&NB]HQX9V2NK]:8Z50UT>/Y\0>3W>4@T= +MI??&6-X]='7KGF-&VBQO)&)->W_W]6,IS[FTKCDKTQUC!7DK-+'2=']DMUOF +M+M"6)6%;K/)EKCO*6BV"AD)#]8#"*JN\"6N6R04'W!%OZ7X3$Z;*D\:-?CHL +MVN;32V@5,*!I1Z$L1U>?\JO0/H_$A`O:$^;W;0*I74@FRE4M!/QWZW+?">[! +M?ZB_<#&_`,'1T4S(ZNLL6@,2R6_?TQ'VAMG[PC!YO:+A(XCXO:DJ&2[)5E#M +M32\388P^R#4A284K0HD+QH+-.'_%NJE#M^>!QOT(#&54QRQN&0UGU)M@S387 +M0C8T?'XMXNUX?"#,UBS@^VM`M1$RK7UG/!;ARW[%I^2UKM`(R]_A@#E//P!@ +M85?M"O!"L,+1D54C'B/*W/D!J)..W.>"%3(`XLT8 +MD8%D.@4`.`DU:KG4JB`#LJ]/C/AJXLWEPWS$LP2_?COYJ<4,MPSF#87391CM-[@+J$'^<3W()F)GO; +MTT6KDJCDU+!&34'6>QP7T;Y>)Y@]I\IW-/?ED$!]QU)N+:(A0OYC5]0L^=%, +ME'XYNA=,^'8.W.5VH^X;6HN;39V*G4@#/L"V=?D[.6X"/\_P4JN1^+E5FL': +MU,,29JN\T.1\NA+T%3.%\5:^NK;"!*V9ED&^KO52%];M[<+6?X7Q#V;L%>RJ +ML4"<,I(L5SAO]K:/Z<#NI=L^;/41;3ES7&CL#*1%JV6HUDU[D;;$ +M"RJ'I55R,R)^!0.V>LIN]`'(FR8"L3H'UI?DIO]J:_SYS?LO[4#3+.S[*!++ +M1?9`_0&663YQXO@]:]\Y85%S+^93>)]6\"RIF"J5=L9EFS,#"=[E$Z+T7ZWK$0EP8L398/SQWU]CB.J)3)>^_+-#1'ZQ6$Q\$;X;U>*'3$/L] +MFO0?O4\?_%BJ(SJ;,U3\^'WRHA1ES1UP;`E$,'FDCSO2>X0XO)5MNPT!#R>L +M;[XHLV`MXXQ4:]FO^:B +MO)$$&\1H([P[D^,6S()J%2%A5XC?^7BS(`I=N4"@IO"3GS`ZHM\J@WCE[!F[ +M0XTC2:DRY!OGW\+ZS!51F+4!;Y`@4-38P9@^"]U"E4^YRNE< +M9>[\\WOKA[7RY;W229('#<0F!\(G0[&P3P(WJP06IPEA/-J=O1=X)SPPD#Z_ +MJ()3JL18)))U#K\'P,ED#]7TP,^HMAP2N?!?R,GO@I;TUCHDO3=RDK0^(68X +MC?FZAD5^[[!'JAIK_.5I]IV0('7,?JM0'^+5&7KS@2Y*9,"2EZY=S(PM264F +M76GT-2C`M+_'YD3=A&L.@PTH=!8WY`X3J]AJVFLU<#NZYR:MY2TNC9`_U)E\ +M(HWW&\3!UX.ALJ;O#=FXPY+'U0>?*?^'"UN+W`+C,0531S.`#=X<;%Y@-/G^ +MH,864EYRE^HIE)X((;BN$DKGZC=D,5*(FX)#Q_00G9:SE4ZHJY!L]CKM*?D_ +M2)C8W"W7KIUNHL&RY-50^<%KS%M!HYX=_'9VZ)NE!_6B3E)/'Y/0"9KH\M?F +M,;,-6X*T,G#C_E`_K.EM"QXH;!`.#UMM<85`.STHA*1;7+@2(59)@XJ1JH,[ +MF&?H@?#0DB,\S]RZYC4ZX_%=V6QZUO0*LUZW(;X=H>Y4@/M$.4X>4;G4V'-( +M4]=1`+V]R=XS'6]`4?;5JUKMNU7]):`TX#$:]B*[RQ.*I@/P-)>NTF[5O`LA +MT[2&/`>Z-6#U,36L(OU9EL@F4/9A5RCC:#6!5H?RW9M^:MX'U>0L/*`-K\K=(G(<5G&TJ=J/.S@X&(1WA<2)K05`5LO6WP#BX-"31*SZA7A-R!$/9=7^S-V77! +M8$ZF>2JVWC:[&BB(%3)OFS?W=(4289&2"Z&SY-4LB(F]I%[^$)7&P'/2YK/L +M]#/LP9D% +MRP3>U+Q%DRJ^.1\CS2@L^)*/U#946KABQ9+TFD(M"6M=HDWV,71/+4HVF&5& +M.27MR,"MH+9KP_]M76$E?!'G1R##V+&!2YU/^HS".UVYV[E>R'=R^>%4T:\7 +MIQ-1)?;F]E%\72`+.^6);+^+@[MIN$7\`Y+JTK!/Q-.Y:N^H>K[D][E'KW-,* +M*[/%4=XPQ7:S_G(E/)"TF3L6?/`+4%/O:E6[7W",E41P,\>#6PD-1NH(H,><+E:5KIC.+FN%JA.`\ZRW8A\FFF= +M#PF!X/HMZHR>ZOBY=L'&L4B,BANPD+D`BP12;!;&75KYA7F%W$.*H_L2(J@H +M6-P^CZ906!$QUY0F]B3Z7\UL@R'>Z+2\_&8]",WY1I$ZA.CHD%=[0BM5^W:> +MB`.>5A-Y&_/F_1JABRLP>1DYHA$&[%4F;Y8KS&:B7@GYE22E(Q`EOMGM#TSM +ME>V.9OZ`)E:L.>W;V8@W8.ZA&$?YA;8R4"Q>%K+:-6)*VS8]UWT\06R&JAX. +M5HFX)0'\Z,:$G$V74T4<1?[^KNPM2/?1M181N[T2+63>>?-'@43KN9.,!]& +M/QL!`&LZ%@`(``L`36%K969I;&4!F0<``0!!10-=`/E^F`^0B0H#1GUH4:)N +M9HY&.E.\T#SM[=N`_$SANDMJ(>8!R7S@P52^>;KX_^\>0G/G)S5.%@9#C*^^ +MCP^35LL3879FQ$?W4&36H!Y35I.5#]/@K(&E*LF,MU&\[.V?-P,J2$^4.\(8 +MOZEU\R0]EMM95-!@D"K&UE[C5[W[L:N,C'C@!P:O:V5^LT\'JAEE]^':%R[4 +M8G69I3@+@/K1I^+,IL698ROXW,>#!T$!:$]*EC#/LL5C0)L`%:X`SL99A>#AF"X`30^$RZ81^(N^W?2&2?L,#B'LM>$1Z3& +MBQD]:;:R1V87_SUR;$M6U!?K+^^P,K54Q0M\G9#+NIBV-`!%\"DH^83=J[N% +M3[ACIIBJYYH@"H'Z^8I8,!=@RM]LI@K(4,;%)-;2Y_XQ9>X^6>7_!.D76`QE +MC5_^`++J)PAY%*F3'+A7!>T7;#//'1)4*,Y3H:.B[/!7(N_#Q[MK56<\]RBM +M0?:[][9S)OR-SN+Q%2'.(M&9E-M>IWLI+MG2)TG`)0Z +MIR[W/&A:LU=2?Q'93C5B<.ID`C(WT*1"PT>L"O:KGW4QA$2[N;P=1H62GRD` +MJ'O#,%AQQW5?)W3F%2O[;J:-%HY4$@-()7C\=(/0+?X6$/UL=5RJ,0?1V*'8 +M]6;26?IG^B9!TFI/[3"=USM&+TDF'*QDVZLZE)\!(OVAL_<*1D0V7QB/!VSE +M!WS8I-6J9;V`"^'(;'5%T"]P8(A)R[0?78,R@%1R0AI%-_P69&%AC#2#Z<*6 +MJIQ=.=+$)#(?+/R:Z@](G;SYWY0@;F)&`GMR!&7@`N,6G(F`GE:?6-[U*;L) +M5>;QW#+W\N]PA8^5X,I87\"A$-..\FT)?A35YW3,QV?4=2NQ9I+%+$^W:*Y3 +MN8H-"5-N,C>(KTSL,P)^AMRRPZ.D@%H\'WPFU9?7J>+5QJXFT'',@FG8C.)T +MP]F]Y6A58V),ZL#?\4&UTK6K +M<"6TKG$?Q9=1J$0,DYUOF#5/=QXS5NU;ZU](-GAUEJ8;G),_POO/EJ1Y1()B +M&F\6(E5&O:?ZV9*)X-)`IQB1T2=#@6;2B#?U5PN3D:8GV*'4/_A48(VT[#Y] +MWC29);,=">)`#ZCQ`/CYZ1\C&S:+=;CTRB`O,CLE[49320:\#)OY +MD@XX8S6%ED&=,Z];)7E.95-2EPZ[.882DNCO!^2GPHCL,U#M)*9@Z"@X@Y5) +MF!MV'MY=CR(>L&RGZ/1??HXI585;!0^5PXN_3'A&TU1(7OI20SG<9%E%TX(- +M.)6JP:233P2>^*2WHQBVXBV8PO^TEVJ9#COQU!@89-PM+$$0=!.<,]8$ +M0#3NK'`AB5S.YT`[+<"$P(U25B"PN4!I)W +M.Z\D",LB2)1EUZ(]G6FZ?]BT^/1P)$*XL)'=<3_`[;UFWG9@E?*OF1PV7612 +M44E.9C"DQ73"9C"1O1ZQGP@XXFV*M=HF#@D;W8".D^L2#$5='U48]L^ZH"]QP=/OZ9D6^4'13;)I+BI3;=/!60$?MZ8GF$XVGB*%XL*EN/JBS-)XH6 +MQ81HFKV!$,OE`A(A96HVT*XE3PA-46(B%&+T8QL +MB0RRII@OK9G^S6/Z8X\:L1^^4Q18Q'/(2;:.5FNA^X+-B+5A$4') +M?3,"G_UKA/HY(;L`SG'ZY/OJ+YD=P'RI[2+4SAG2ZC((;V9^)1Q5G9I%=]M9T!E.673;?[;51HC7A_M$29Z;O>_-WIRNK:1WMKFP/[2.,YM2)13OJZ]TZ_Z`!GF-FU=-,0'@U.!Q/%57G>$Z]C +M9DF$6M3YI1;3G`/CH25J5-UM=O0713G!O4@03[7D5'KV&VP2U-G%/F(1'V*G +M3GPRP9R`CA571]?)Z&6S,^6S2/Q#"ZP_?RF"V%['`Z%1,^(E+I!2B@`KNX++ +M$BQ017#IPSLPY,')O>N\(/>^5(P,:F$FOV9$J7]&(^)_!K\)D'6<9V/I/P$# +M!.`-)_\(>Z=>U4)/;!"?8.$Q:2/7(AISMLS1D$(J1XW>+=6VIZ3;OT$%SF(+ +M(E&>F,]&Y$+J97CP7B`-^-WDV6U/,H&WPBP/NRQNW](MU3^VH:G^"K1_O8O$ +M$21-<.9'67>.7FQ2K@5+`H%9B(UE\]6F[Y"DF-M%\J2T$]K(`[CWFXB(P?K( +M@17<5>Z(_9:1E\KTR^S6&NB,[EVHMR;,%*WPM'L8&;`ZTU*")X\YYKXW.TL] +M7-PMBXB?+-T:,FHOIN;L7`2@]O]CU506<$+J_>#'3==NU!^>5/3=\0H08[1P2^?X'!2)C)70S(FI]LRJI+%8N;EX=L+]PGG*&EXT5SCZ*X&5D +M3^C)01)6M>L;?TIZ=_5K:$=J-F2.-EGBZ+#:VRE5\<4[D'NJ`D$&BY:"0O3! +MT`U652&XT:$3ODA3G!.@&)>EBLC>=!!J7`!2E1$)%`+>HB:-#^U'JI]3F./2 +MNTL,CM))G*1//2W6AN#R-P7._L)79];4_5R'B`T$\BU\,6JMR/T0"/4SO$'5 +MK'B7/;*,9B46\3U5]>U/N/:H,,;M>U5=WE&:?+:G_*[WI.2SLDIG9#D'"R&> +M0_5&N&/*$ZKU#Q<(?+"&!(@#/_DT9$&P)F3#%D`&HXN5*`NQ1KC'#KR))M#' +M+)]_R<9AZRIZZ;T-@IZ2;E:W1^)$S!$CD]),H^\$*<\E4/%//'(,K@H#W6'+ +M,!GC5(0\;%12\_0=\EG^91"VK@C>S$;-S','ZN=K<,D99,,SQN6#+T%4X[2= +M@CKBR4$STAB_'JJ@\K_%0^@`%CV^WM)#6,_`B^?V9X=NLE'B?'V'R48XF,.A)B35/>C\T1VHI&EV=XF9R9S+D*%BT1F +MKBBT'AD:Y4%TF.=:,TQO(8YH*&ZWO?.@*/5X,F(B]!3J8E$PI=HML?P*3Z8A +MT40W?;4UJ'GD8(,*;$1E1H:8G@?_K)KXHH&-#FF].N<+M$ +MXI9N$+<=V"-C(L255>;6N3-MQQ/1F-5,;"SI2^T:$RZ(1>WUN;E*_]99YS_6 +M\BK*<$6PII-DMXXR##*5RFA-P$JH0[-*Z?;_?B+1]2#AV`5GERD!1U#G(9GI +MTM]6TV38Q?CB_]NGE*`+';'.A!O@UPYZ@I1H4V]^7':=;CGTS7'MMKU+CL&2 +MHRDQ22I\`C<2E-*F`W"I +MNW.KLJ%EEJ+8DU.@G(\Z!V=C=(?-YH@-Q.T$_$F.?D^JXYH*50G"AK7]S8%< +MI_$Y&_D1,M%SM&TX.6\PUZ>PZ#$)MW[Y%P\6+"C,J]\[^VP!MFF@CZOX>'?W +M&`H?5C@RVS!7)$19>..NAV`!A/Q"#JG$;9PLOMG%_O=";*MX5E;U-59^&;:>WRT. +M>H4%]\?U\DT135:4*0H3=8.?`M0UM;27[#J>"_GX70F()5V:B8W45&-_.'8H +M\E8B&\7[K.,_/]Y-HJQ!E":='\7+27PB"73TLXRF&#!5-SQ1/,T$_\@(&.KH +M[]IX=:[#VS80[^O\_&UMD0-MB-C[`D*<=K#UH2 +M?QEF'0NIKM'MJ1/MI;`:(]$94#,:'E02#`H,Y")N7G7)#KSB`+T_3)HI9UC7 +M18NZD=L_TVLJ>"WK%2OD[F4R$%QB\L11:)7I[5.S6$GKGZ02>+HVK'K%W6F< +M7$>2,!/8B,NEDNUV'[LR>DCT2G`:3_]H8SITCDFAN4Q";M+\W`8SA?B:[Y], +M5.^%0]`W1Y;Y294R[:\2W'+AK04KX%*@[8K;^$_@9M7!>I858(HZ.D)3[V!X +M9,?%O88;>^X_FR$]229K?!G[^Q^2#2J3B'U*NG/?0'[3.[_9_SZ6K8H0E'I5O5=Q>S*DJ1TX^EVKO-^&Z9/;QGA:>P7YP5'M;M\0OYZ' +MN(?*3!Z$"LQQ6AFI$5>]\QU,56=#ZM_1M$RS]([BQN4[;EH3L8"U.1TJ53O$>!0N? +MB;>S!+`-8E?R#]@LBBI/ED=G_T<[@GJ?>/7=0=+QS1#K6MX@=;O$VSG$"_/? +M/@E2#O$5U6L\AHVQWB'$)"NR+W8_N=$CZSQ0(01`+$[0VIT@>.?[=L?%&SE= +MB0IR6E1<,0&:QBBLV?4S%2T&0PQ`_ +M89E+JS[4%9I*QUZMXDSJP0T3XO1M3MD4PO3BH\Z0ETP0.L;PWF5?OY=-;J@0 +MSXQW4EXI@JLK*M3Y9_\WUBB8'-4)#RBRW>T>-'("<3F\M@PN4I!;JGRL$M;D +M9C59QQ>QL`UOEY(&(M47%A2>`3#&4I'2Y9@X^I1C")=;LZX].G0%P +M%RW1!:3"]4V&EQ/ +M)A)^-`+D@UPI<].UW)?7AG^I;RMFNFT$8)*2).BA+AF +M>FNW0A:0U-1F>HJH)$,@3K-`9>-\_F3RS'TSG*0Z]^I:S4;J5CGN8>MW,5^L +MM&XNLZO"PDMY/&[_D_-D>5:T_/FF!>'AJ-8(_+?HM^*"(V$]SPS-7'1=WOPH +M:R>RN[!>YTB#'7SI=\(2C;AGX,2;]REK17'G/G"U,[)?-=$FLB!S?\035AI; +M!48<8FEFU%;3@I(G<;H_]B[C`WVJC'2XGIZ+'YY_U#RU'H7>L#EYB]ZOM26D +M%TC4$U:K7:T\$$[G*,)AZ'#-Z@APQS.%6EPS4.MYN5TFCU +M$$7FJC=J`P7SZ4]LP/A_/54N>H1AF__00<4R8T5]926OZ00!R1X'_AQZ5KT# +M.]X\%=Q5,"U+&).6@F%:`X!%,:TC;=1N7CRBZFP$W^<'L>#R.L\,E:U'85M^ +M0U#U*D*]\'`9\=$+W7+K>L1)X99=.&K8TQ/X8PN)EY1N=$,N\X3>%_`LC6:C +M[$34HS-I<+\?3E/U,3]*/K[U^[QZ@ZTVB>>/1SD<#-G,JHL^^$(GX +M[UM6+H]7B"JN&CA=UFSY4LUG9MC:2"V$)XN+C$(CYJ7V-.-(KOLJV +MZ`.,W?CE)]'$Y)U!VN]H=46V0#7B'N-TGC13Q3PLWI90] +M?"3>@P!\#%5@[+_D"FLO(VX$\)/Y*CJ:P&0Q\FL.9$^&6QGW@V9]G72M^.94 +M4)@EI.KFFW:TC;1#<+WR;4_("?L%$4W0JN4A;K<1Q7/]B\DE +MSOR"R+6R:JQD_TXKX()\L683$_S6LM45P&X&?;L:.:?\[TJMC3,P%;X`EA6* +M35#GQW\:F`X^'2?^K(QQ&/#?F%SX?FXOI10C'_8?\@\V_0R#A.13YZI$TIP[X!8;1NC%=KKIA0KO0>$9=6?A<";+J>=5,U:0GXGPK[C!MBKG$SXAV"30JL3'$-[$L2W'A!7 +MO(#)E2%"`F0>FRH9\AWZDYRU8!V$8L5OW'\`8[:\U)W`#,N`IIFZBOF[INUW +M%`%]?`RA@+5,72`46SC`5YWRH645?AB*PPS%!QQ[`=D"D^C"6CZDV'2'A@O! +MA,Q83XMM5GE&:67=#LE.4G0(L(:XSCQG??X5-6AYH0J2Q`4([5/G.P"!.?\9 +M.:_P-O_QA#50IA"M;[(U$EK[U57V(QY+;*0$36`V*KK\=;. +M\5[=Y:]`VK4D:#T*$R=PB9[)?W0"Z?2']WO\RNK%>082+'*4=BJ[I:LXM:.+ +MM8$U?\E;KI;X7.NK1>/MH,/"6)70H-HAV5@V]]KOM;J94 +M:EJ#M#&]4^+7&78^[&U982`#C(JK=?9_TL'/H:T3GTO=CG@L@>-+T_,.VK4N +MJO?&O/U%)*['XC/L)5F93^/^R%JQIUG"]N!(5Q@6SXCCO(T.G\+C-$91F\WD[Z24J0'D_"4J[M&,'DWG=5 +MSL^@!.-93#!]WA#[4F\*$!J!V>(*;NY<6&X*-VR*G\XR?23X0HVN":%W/>EU +M2YY/W71(RG09(G30_0!(*8$\/@1]FWWBQW26LE-F$L82(BG&(O1FUQ7IM=JRF;MJJE=;(.PY^)B"; +MSS(4P/.&QX>($$2XEJP0O/X%1/P$J\+G\\>K49)OFK74Q)+E5=`+^VE!(^^G +MM5Z4>`*29'C\II+0L*KUA&.[.DI=- +M-DRD&BJG%)_6EV84?O5]1("[3*4DI5KR%_R5;`[L"[N_X]#-8>8PMZS>''K' +MI-B^*#0"HZ)YC607Y439QSJ70X?JM">9 +MJ\_>%B)E:@K0HH%_VWO][.\LH!<.-T%)9`BWR`Q'_[U,J1*,#F42@@"?34?&V]S2:IRD5?P+%48^7?4$+6CP?Q^>W'53FQHO)OU\ +MBURJ>9V[=7?"5*V0VK?F]E1W5\;:;!VUZQIE-$_U?NTD*;&D/X64Y%NJVB=% +M62.-\Y01?:!\4+$UD[%&.1%$^N>$I`4Q\OZN[""\&&MD6K&Y*D#FHK#T.Y': +M?N1;!KCY@_)<["LXK7@_;\"\@(_@9]?7,1R@_E;_SUKE)D)^'!OHJ(^,=YDY +M;"9ZKN"CLIOWO!]6RXO66OB=6NZ(%5!1-6(FN&V4\U"%C%>81U\\[YC7# +M2_T/#'-6%K8;2.C/R96F3S@4;@:[UVXGB5O.HA/'K'.HF=[[*S'AB;NIZ.TW5TK-@/P80)B1.6`;5*9PP\=+J^ +M9!JA*CG!-=;J;ETU%QK*)/<4%%SD<3IZ.C:^R7:R="UTI*%2Y9 +M%.RC$AS3O8>ZH64]LN/8PU[]AAK\F+;A`YN'98.#!W!S'(;^N/0NR>6$.5AI +M)WY2YY:9&>!*2;/LS*L/,IW?]A8LQ3B%=@ZP+00%^JBK`:\";0!GH!R?H;$FU#)B3^IXKVNG2]=J +MR1>WSC\;R$!/4/\)1UQ+#4]B&5Z"WV714O>FO?9U9,G`'3CPVNUE]SP/]<-) +MSWLE4\1J?,J5H`FG&PSO^P/YEFP8-12(J,S-X';(?=`WI$['-7",WPJZQRNK +MQ:KY@[\;_[T71!4DS:*+.;6I84>$C&OJO;=E/5&CLZN8LLGY*6/]C6Z-/MM] +M!V'BKVROR4$[,-PK6@QN&%0#=:!V#YX_KGQ_L+"?L6!V;+ADXUT5;*[M,]X6 +MSDQ"D?A]- +M?1J,*P?O_(20DJ6`0G[^9A;OZ([W]`:K?,VTK7IC6(?Z%1]!J>^EXKMS[=>R +M^P@<2+*N[2MRZGJA(K0ROFELN!Z/--O`08!;`Q<.4^"[)3RAFX?19FC`9=^9 +MO&.`(#H1H41"-VWO^_LSFH^GZ13Q%T0%O2TL!+;1WF]5?NCLQ= +MH\C)R70EUPAU9IZX1^*,9$/*9YNM?ZP'"U!%P],C_W&=VA.R>53\'LA:4\8` +MN"F-CSMR2]_*]E.*SR..JZ5/.@E9*TEU&B8K3B9?X<3RQR$JB"E?[YJ^70HV +M!?[G!^4XDBS?5BG=J]"G+F'Q+RE&^NGZ[U>*2LQTHV-S:!I4=A7D`JJ&`(%<9],/7Z%]]#L86JD!!8&:ETC(5C>Z]6 +M\UOF@1FELP(G6>8O'>`[EU%,5X12JO-C;0BS*\>LF4.*1^\H;0)]0#DE_&JD +M)Z0M[RXJ\%+O;._W<_LV8Y\,0U]4A15#I&4H@K(*JJ+3V>V-N&@A`7%+B%<1 +M^7=@8G`'*>PMY,I/1+;';MYD=S:*4QD^)?=ZK631-RJ51`CC>%^JEV\.5'S0 +M^75Z]`)A(K(Y(K#SZ%[%LT%5_MCA]%E).MQI(UE(/N1E7%T\_2BK2CPZ<'0% +M@@3)S`YK[6T(<<:&6N61RJ^,;OW)D/==W9TP36L@%61L'6EZ1?@(R2HK_QBQ +M06JE374:9`^>+M,`G8?P2*H1IBBO2CAX7&<3'1F?L9!R)@8)9XBOR1C`T$SM +MK!'P&Q1$@`[25:>!<%?^Q*3M1@4AO#KWKSV=;B]N=7[J4G7D7<[J;Q%_T8\% +M.>-L?TOLYQ4@2*K0W1LXWEI+4](N'7W3 +M"QWA]O\7V*G,E=PU3`4)3FJ$MZ(?@3$)HAPR$.NW:DZ;T6`J9GLW.BG7;2+3 +MBDKV?774&)"[1(7VX=P./:(TY^`+T`8:>NR#L+=8KH<"CVO,;.,_,CB<(B44AD*U_CAX)J^8(SM0*(0H9Q.KV;#E<8)*4Q?UI">4^ +M_MUOD:1KF@F^!58+S35R(OXXF;0KR=]K<9X('R218KMI,U +MVXRM2((2*#MI-O@MMOR8W7=(O'<0>V>=-0)!5P,DN^G&EV.4[G+'XFY.5:Y9 +MZ9ZZ_JH<=U6Z-E]OYBI099FIP5,DF`V2OMB>IW8K+22;;IF%;0>I"ON$!4KI"#O->)OM=WB:5#WP?1V +MAD'*5Q8-OD][*TETLG7:N#!/.3^BF1SC]B-]_(ALCNZ&>M( +M6D<;S3:6!1*J'SJGF(W[W.IC6B(5]7&Y3(&6>\%(GVCO=OT$(,I_`%$PL&M> +MGO@%17P5'6XPKF^WU!/=:CM20(Q?M>^(B\MWPP17Z1T;1%)=PI\%1V+LS=3O +MAT3-LG8J57YV(9>02DT.*%+O1@=[@^+D54I'@/6LLY@O]J4&:/GE.$O-92AC +M6]L/R9?QE8DVL5_,SKHX2B/B)Y[%BA#DPTZNZI9MY1_YQ`7R6F_Q3^_B&V"; +M$6OJI/T)#]ODAZ%A89RYKZO4BY^]='--@Q-_2@34;BYJ=?)(**JZ;,0\X3CC +MYQHT[\_?KIGYE@4ZB.L'8A3Z8O*?V$02NP<"\`OG1"5UJC)[DZ7^[F\Y8SQF +M_45%J=@S;-:V[Z/9--5I`ANJLZ1@D +MY505CGS8X_Q*Z[%<4).+87DN"R]\Q1GP3CZLR.5=HXGR@V1DE%L:3^UB9^RR +MTN<[()PEU&G-Z@)*L/0/R9X7W=#3UNO'X0/LRDQ:[;6^ZIRP1J!\=SF_D/T` +M,[V<)V\QA3H)=GL!+]4JC(X1,'7+:.ZH>5HR +M?4Q\4*($O(G?#T2N,.LG5((@%-(XHHL0W4G5]R@5RH)/_T8[N +M;)&.Q9G0%\#0N;%C";XD*6S$_%/\.+(_A\FR^A1KL)=NG\B@IW>(^Q,=G:O) +M"`GG]:\#=<_XPXX,4RVT!A2DNW;SY$6XW)2$?@(1N$,]7VPFVU8IB#4*>,2L +M83V60K7/ZD+@.K!E]5)E'Q(ER%(%>CJKJZQ;K,(+I(A33X@4TB?G%RDNABKH +M..47K:GCBI0(T,TR7OC1^=@#,SG^@K5KRPDZ?4/*B@')GA:U[`N*)HP_[OR] +MR"5"R-O9/#@Z6\-O4,Q>*=R:[F=N=?EBY0?J]NN[5[PE<"G4BR14KOOD-\4( +M,;#U'H2]V%^%3.B"-U^%QL4\W^95Y?PF[0;?AK@2X7T(C&C4%FC0X;OT7$8L +M`!&/-33J:V[D2.XK&FG+W6]I&'(M^S00GC7LE4DV)+*1W&V:Y66CA,(.#7#+ +MEM$ITBR&?>@DH]F#R@NW\@&\X,V2&P(T+A;Z +M`YR`JV$)\%<*+RJBUM]/F.(IJL$4DH^LN9.SDVNP6+2=2*!@4(O[!@(@S9BY +MZKX:\<2G'3.;(U4>05`:4,(;S1L$)!_ZY"'85ZW@%">J0Z49F%4EI=HU%N@1 +M/&FW/:%KW.(T\609;SQLCM#)O&]?O6FRJ0"WOR&#$)!U`,^+:3U.F]2&6UCD +M04P-PW1VDOS90%O'!U2B%`]G;),ZHS>]N;A=JYZJW:H;DI^L9T%2)(--Q_#O +M(9VWD-:D2"NNP"J$GZAAC61HTP(N0\6+$WS)ZT$1%N!TXT=)6[N+Z@0PH?G1 +MTDIVH\#$7\#E/ +MS,()+"P&;;9CM5&_XDVW(VTTPBCW*`?DX-U% +M:2O5'JR'($GBB&(C2F30U/YS$9%RI(A8\O&8C`5[`/Z:),B&L5:3.V6:?>.F!48/E*S'&JX$^Q +MNOV[CO6IQNKED3;X35.%O2M=IS3BAY8]@^Q@IULEDLQ/-N729NS=0Y";X0%H +M-HEY:290NX5DO3Z8Z#/T^MJ_I--SX/M9+J==9DS0/*-#?3(''*H7;IJU`S/8 +MMGL@/HE0$6)H11?8A!E3PH7W'^WP2G/R?:IP%)SP6+)6JWPS+#69/!2$75)> +MXK**44^/C81'T"!5$1K[:L58VJT*RO8.T];M*Q!K!WI>F.&U0?,1:\&"Y-\R +MXE-2*CM,;RP[XTJZ04,]W,%XYMP@@'GMBQ"$@.R\JV&+YIP4&H3@\<@@X%2A +M5&]\!!*V'\CH+E\`UIEZ/^+]%*D^I&"KKWY]Z>RFYZ]0@6W78.CAPK<+:<9: +MX*XD5Z$S;`"%DZ5?*?"W1^>,Z+97P^@:/4\6;@&O,[,,_OY`^0FPN"R+V"Z_ +M1J*R7>D0D<450:\"*0A[*M@!E%C%M0ZYK>$?B,S>6'=R%[EKM(C-H%99\ZDI +M1HA/-:*!]O+L28Y$7MVEXJ86GPH,KG]:4HO*I(_1X#V0YP^DX6%=X..UCPQ- +M`$VUA4:R/;Z?M>6UOU?U-%>@-1O@0+GHK7T.L`] +MN9CP)U+]`'6-:R_M*^6Q,C@#NW+P43=DM/')_),ID51[5_8*[BF?I=^@'18HRR',PZ +MKX]O@;M(PE1NXVC:X1J7H=W.I`0;77,8:TC[8((W^BCT"!TL0 +M5.F58!4N0C`03L#*;5C*A"BPD^^O>@??S4X3=;,DMC9_;_$0#U9^VGS<[H_= +MS9,T_4)LZ73R/6`?/]D4*N52:XJZO0<>Z_,08!DE2`FU,#/:"UMB]&*N>1>P +MI5R=IM*N*?4_RXJVYG8VY19C\IS7H-@'!PMH9(:!LON+E?;F0FOB&-<5#"M2 +MRKE?:N>\890'/I#'AG4&&_=7MQ4WD611G;K@X=H9-1*EJH! +M&YBWF8O;@*N,1,FL?<]Y<4U9\X?A^V1BI1SY7OV.0[O[EA1"_6"T3BZP3-(O +MOBDJ+87$\$2VY/9Y._AJ#B@R1=-^S>XN^JLTPC+AAB"ZW"!P(YN9D,2$W)>6K!M*\3FY,!9\.<'9!RMO_T[#T`[">?I+N4)Z$9-OJZ +MK:L92\3DR:AVB72JCT/Z\.:GMZ`ZWJYW%?):K<&?ZB?3=^B:?N-;Y[8U=A0) +M]5E02LL%E17+;DE%I`Z7=&C)%$G,7@;VW3_MDT(6&(+$P5-P+8U*EYD?\38' +M!('UVE(:*!SSV5&.[SQ\^((ZH$+!8N\*QPMFJ'J9T'O8^@BBN<>"-O'[N-1\ +MJ@ARI&@@G4(M/3V;NXZ]!WHO+EH-%(J9O$^4\I_F[>C%!_^T_AJU[(-D50D4YU"39!&8-;MNL +M&[++FROO1Y3Y?'39#,\D71]K)Y(A]O_FA0.`'L_03\EQ&7]XQ@D_Z%*-BIX= +MX\2R,%7-+&.CWHK'#]1RT0!O;%GB'6:9A+)$D:2]0N2-(LIY=ASK#S&R%*-: +M>U8L4[X^4E;4D+S?:.4-T5!$3+,257ZA!$-V"!9A)-UXA9&AN:@KOF_#=VU9 +MF7OY=D_R10G]*F$[X5'@#H:T=^F80?J`N9;^YJN+M_CC\0#.2)XW31.+U<-8 +M(I:?7O70"M7NIJL50NBOD[FNN3+L9%C"W^Z;%"*Y?%P;F12\R_B%P@+281$/ +M%@VP'8F8<-7'*55I5&L3-7HOC+'SAAY0'*UNP(S%?@^0735O&[_@U@:G`D=V +M6;'F\K]:"#"!%E-G;3)%*AD! +M%>'4$9DN>$^,[DO9_(!<++>VV*$8BUC%XPU.!DE:MR9;5-'7JXJ+3=8XSO-` +M!T>VEXW;T\0O7:%@%NK(L'T8ES"C8Q+P8#<8UZ/SP[(9^E32[_9%N]? +M,'0_5+H*$F1V75/9Y1"=@Q=B?/C7)[N&ZKU6H"3+OSJ)NK6J$,K\3-!(=85S +M0ZK27,#I5"8544X;1=!8$Y+BD?DL[@$L97MQ*Y/"YQ=WR::OH(>U.[^"@XYB +M-/B$S3)"4(08`#]J,WG:$=1?Z=!=DQ)M%[IK'CUN3W(%?.>K)9K@ +M:ZJER?,4H.<)B'E<+[GJ=UY0!N-+H-^M&:SXCN6IX:_,^368Y%_:!#PLA$AM(D@QECJ]$#?[&8^>6^\N9[SG;RV+H')I![E&E7U77UY`I)1> +MV/A;SS\C,6\(ECF15OZ51$P'EREEY'7TY>F-]DGPSB]H1 +M0O@AR.@",/(D+7H!B:^)5.5Y:E[\EH8:1PKQ1Y+2R9WG +M`D2LIA)M`)VWN3%U`-F[?O+#'9KH`.K5]PQ2EIBMV)+IA[Y4\]#?41=R/4^] +M`&3SBW!K?O,^(EI$Q@`%S(9R8P>X"U\1:PP;LXI^+@&+A,(A^XD7`!2&\U"( +MT0&(I,O?;:FI'1[4"3C@(YU>H^<]TK$,?O.X_D?'4,!B=OC8\%V,5G\WJ8V$ +M,@XFVJ0?K!GW`22_T]QOYJ2SY4^.8@#/J<)E.89\Z_YFWW\8Z.1(Z&@.!%N& +M%9CN&[O#'7H_9X>_QA*V,,3MK +M("*1I04`!J6YQ\.:I"P4X8M?&T=+E8W\UWK)'=7UL2T-W`-<6/MG6NQ24/G^ +M"76CS?!J^Y3R[$>:4*T\%V>6GBFFZ_X[$5[!?VED8F1Q(4N.1Y.5EUO.HWPX +M%5S#E`(+62\;T).\#6$U/\$`X\! +M^'1(7S9@G7J4\^]D^3Y@56WY+EF2G.%L)V'70QT?#,].';KOG74R2LXXZVYL +ML#;&/^KK)>L!.4^/_&@"FI\OD@`#:O4Y'4N]M\?&-J'BRXSW^UR +MM0`-9JU#]N]XM;@3>V4>V;@E0]@L*UFPHI[NSSJ5$LP:WX,)PD1RGP<(N3]X +MF,%EY!"\+D$A3VR/Q4HC^7X7`=K?21X"E?*@D>RJ%*YH/JMR"`GS">Z?=@V: +MG1XVF4G1@K!W=RS +M33B:(Q0GX%DM&]LOX>[]S1W'W0B0M(_.G(T`J4H53JMF1A%^YK+,3IL6Q(+. +M?]<`GH#(@&XH6DR9VY?L;N5B%:UV/Z?%D[K'D<4LC:]:I,2QOSFKR@W;13R[ +M)8WHC<]KT;Q3T>5]=*C>7^V:#YD<9J>HPQAH0JS%/Q-<)`UAQ\P!QI+=RLQRQ1=AJ$'M-$8'-B,]!/HTFB!@8 +M=@N#/2#3RD)M6=/J0Y9-V-F++MJ(LT/DWQ/C+-`==T_(W' +MO9+?V=VP'Q<[Q'%HDK]8W/U;M>02T(-%&<8Q^_L>+VB8GS_"H]UT*A!`A8GB;I0T'YEHSWXX2?A!&ZR%V%FYHVNM6HZ1A3Z_T)>E@J%(%-9YJ* +M\\\]3K-Q,7C6YT#D'5087QP??GGL;WT)%@.]*W\P$IJCCXCH)V>;Y`4"N(0] +M'Z5TJC`'#*T_Z'NB&0N+W2HTY0?W$-D<)=:K'CL`0BLB2Z6>F/^2Q#)(>ODN +MTPF2T?/8U"!&.?0S;-P4VP&D%SY9P5JV*#*C7Y+OI!&CHJN_\&V;LCTKE(0# +MU13L3U@ZN**6NB#B5JB0X@)CF93/2-R2*"M]9%>\*"U0*X1XA&V,4\[TI81\ +MI.+KC$3W![.8#VL$,9$&DC.JPEL^VH=,&A1SF3W4$)@G2P4:9=,,NW)"XQ^R +ML3$;I45QLT?+-1YJ;SZ)@HW]G/S&C2/7CO+.H:'A$A7RNZ_=K>*HOC+E3&8= +M0?05!K@'H4H8%:1L/0MHVQ*@WJ<5;5,M&/B#'L"%))+.[&XAA)+D?J1CM5.% +M'MS^MX$!>5S+[[.D-YM+=S]2JUQ%2F08_X78Y*=V?)P_8]IEW==J+Z7ROU$> +MSP-KI(KY7SBHJK=IL`)#5SCCA:[K:$6YQG:TY]/EGZEVE#\%F'#/P3A/J<`HE4HL?:EU)XH<0BL +MF!H-J3L%0YX-89_XKB#NA@S0RH_^[@?8M/C*K86'S1M-*:'\@/("[((7]HEA +M_$$@'VW0&ZK23TE:%"/R253E0_#X3A>,V(/(#?NF9-F&#\(>,?%"3"^M5R+L +M8VW"/8R^Y&U\E9VE,U?4YH*H(IFV"%."8U?2!'UE0_+^[7$G$@@0XIE^[<"F +MHA&H4M2JCD^'X+SW)4)?X\.$'Z.L^S>Z+DD<+\%^G]QNDK24=/3XSF?+NVEM +M5JYI19FMIZKX4\R^O0ZTU[[F9Z\G3ZKH_/B,T%*=$"2A +M;OSWC7GLM6ME/>>4Z?>'H2&_:H=O;2:TXPK_[2E$[;-?"$DOO";"\EK2-O7O +M=+V]4V83X!5P&K@\FVXE7;DPHY3YI6LV4]UL7&I3;IW2H4,""=I1%`?^F/RZ +MP_L"9TA#^JI4)R(WDS=.TXI,TO=26D^6SI'6]C@,6T>[JA9:@QY=93[_?U-O +MWD^TC=VYQP17LU4P+,-VZKL$T4%R#CJLMK +M(]'MJ'2;(T;>;\ZX!#11MJOX<>ADVZ_Q'C-GFR\TS+B3'F1A&/;ZT2B77TTL +M2N54N`)8C`76)>7(?(;=E2D>2NAL"ONUI07UCP^6DI);^ZB9B.'7-F5UX^=1 +M/6,6KV$$._C5.A(UT>))MRUB;N4)Z@T[I_;,4J!`VO$1L,F&$K(HG:'*,3T3 +M)_GA:()AGS5676:$F).<:G#A,G]0JV`U9@7B]92133W]P#5T72Y(\%K0NS_\ +MBGPP/:B:-0Q4N#]/B@1C#>/.3^=DTRHJP;#[5CO"O$(V>67ZT?T(!)7)%`-@ +M%^'K"%H66V$C:*D'QGC/7WCE8H-[V?!,&YJ+BXX1HU-KTR1_SWBXY3&KDE2, +M]91)/UNN2ON2]0D0[30<)0W:JP=6>]*;RI7(#(@ETIV/;Q8G!P/53J,Q\M7` +M]N_>PS=ZJU4Q',J(B$*,VDR_1#L?3$C\]U+0_47^E048\#TMMD\I6>WIET$W +MB.ET15@JCFK_::BTD-^"=4X;15&V^B/MB_'>)-5'SH.AFWH%H.E_;.OZGT6Q +M?I=E_#@')B2_VAQ>&YF*!UWY,!BAUPDC"5A>'46KK(42\;A5BV%2VL]]GTWMA!28F=R\2?#4Q:`I]WWG^)C +M6-YRX^3V!SC1,R_4Q^;M,2G;2WB5NY#-*3POCKC&A.C1#L5B0;M57.'6(N%) +M!_-9NKM#.5-EGC&I7O&/K<5/DF+9\[R,$%-4[O#BL$SL>;QB*'.3%_[I'"%J +M$4?WC1BQ8':M3EF^U3U2\TF;/8S/,@/_I+L*L*$J]+;T@R2#_R=1*_GQ!)_: +MOK:-P)P?2_'.2:3&5=%F]COG("!/Y3JJJ6\V&#'I>XJFQJ"3[*%1@W)+RJ#8 +M]WEM\9-QEKZ.3?CIOIC@Z4LHZU"#WH9`JL"*92R.K(#K!/&>>$67[M"(:?K%0Y&&_J1G[;N@#LSUF?%S[B[.OZ[`E +M1&;/CR=_/';@I;M4COC+)XC0T!W[P4B,8A(GE8AD_A>#,T4KUU?N0?BES5,X +M1W"72.'D^JZ>+9TV=_:1N1@F+I76I?&&PA4YPWS,PK\RJ7.H9K>3+*A+^VJB +M7VF].Z73`6+;!]L,*/[USX7+1B +M6\0YW)?BQ;=#$K^#^%X$'BF8#FW$Q--5EQS)IA0=#]3EFZ4"+M]L_S[;DN6# +MQ,LH?>7NS:L`(J3:N1X*>V=0"?3(8;2Z+/-5GJ(8JWPA5U85Z +M%!DRQ/HYRS67!N]1B+70"]*UZ:SL;`0I_57Q\$-]WI-G_YTH`I=_4MV=N.GY +MJ/7W(DS+I7RX)Q;RE3W^://+U3T5\C*?`6Q^;+A+JV))W=;!Y?]YGJ-1/GK8 +MV3<;"_#'.?AQZ4KWV[&8O*<0:\\:(@S79S56*3IDZ5]FQ^ +M_WQQ%VAMBD`>Z9YF%)@#?PED,7&`M2J^F5<'C)*S7[<^CTTS/$'BW;TX_A", +M66"KW*; +MG!SN^L;!B&.Y_)-STBGT_Z:64GL74ON:?20+M-9@`;2O,@LGTF_BZ&GV2,YO +M3+I2S)`=;)\('C8PZS6ZGF,"3U6T!*3/\\E5*+>I`IC@VJ,2(.@IFB)I'`R9 +M+8XWMS>PGW#D.([`H9Y'.49F[[RE&O#+OU':*NM6Q=E2+4C>XSR"H7JA%'-Y +M!UB<8Y'/<),80E5,:]$<=8>.YMZMKZ`4=>QZ$#]?@L)MCF33KMN"(_6=#.;X +M?1.KAGCQ+*/JRV.F"'XWQDA<$1#GO6X#F15C/XT8A)#4S$AH;<$:]4!?0O^( +M^$1>!`[37`_XJ6F"<@#(:H+P^/V6W;3+]/,1NCMZK9F$2IG2LY:A8[J]=!D% +M_,#I3S'DL7B]H)["(6NKI[7A-\D."'G5=2@K!SAPN1\4UDC(W?M^")+8D=A^/+0 +M3!*Q+("+U_W:TTW4PBU^(N/(J;PX2,*S'E61U`3;SJ..^^^HL`+>(YQ^UBCY +M!+!)HZX$\#6^F-Z+\59"B4&U;*?:R+TQD@A`O<,BPX_UIX1;R0+:75YT5 +MW:TWC7&><5\R>\/;DAO4A*O\CE@]*T'")`#=X6JVFLW:SD5##S`_!DWQ;'X< +ML$5:5.SAU6M"VK"5S'H5935Q8$S0/UR1MH-FZXN)8G/T)_2:Q,2>,%^Q5+F! +MS;Y4,2Y8,'3',W2V)%5!49M]1+[<1L-;H<`?_PZR)!3HAY:$]LTSC3I;,(Q( +M#(-R><849%P`0D<53:5-^R471CS[NQ\$JZ*`!PT:J_#+@3;(+^M*RFADD7FC +MO@9$\OP"89.>PWI1-(^QJQO>X-]6-K:>("LQY!"UNQ@KX&K9#I*GT9E?"NL2 +M/P%!6Z!H7Y[@BE3NY?XVOH8KU-.O0FWIDZJNP;OC_3D?&^B6)9-;QI/2W7"> +MBDKB..=RZ`M%F58Y'G=V&KOP,.Y:K)*Q41_6`SS\//3_O=J&TK'D9H`)^:9X +M!8RO>0EA(,5>(^L#:CA9>N+]IS;S9OTW']]GO^U,G8F!VZ"U"+D$8J5D+Y +MFCX=&4QPE`[<_#QR2!*6>7L)Q=4$;(LCN?W7T(`@A?%>K+ +M,2>S3H5FK)04PGX60?L:DW-@BSJUV)K0/SSYT4#+8/.(D]:5N/?E2L]XQ\+U +MB!=[PI0#*Z9+'H^*.?*K]P5SB=BS0>'!R,J/K(M5"`*X8=DV^P()6H>VY?!O +M7K1_+A+LK:0S[Z7[QL9N)-3+\ML["^G^0P/ +ML779F-@K\&@8(R`[AM_=RH$0&X7YWE+H!VQ&+!&JG`,`^3/ +M9'NN`/B/^^5236X<=MQ@@A.? +M/9#4KGA''N8#]L>R)?XC3:W'X6!T/R,B]/:VCBNO]QBQTG/$.#'W5G>GK`.] +M:#M8E;<,TK@ZG-#O$4,.0IGUF%:.=J3+K-@YTF!U/MR]B!;$`CX^>;N=@Y_J +M3,E06>9YNIP7T3AH6L'S`\^ZQ(:T=9`U4?I9C@`21Q(GZJPJ?/HZ'`HVN="4""H[2632OU?<1[,1] +M:S&7@WP(O,`>A2@X%J>+FX=Z"-6I]C/:\AOYQY_BI)>V*AAI/_7\NDUET$.7 +M4CA&H-/#+8M@5S_\'VGU-$]`5[K%[D)"J4]@Y(Z+^B():3]2C7:S&Y[A%3>> +M/Q>")<,+8XM'K7G)\//G+V\7O>*_YA:XFN:?JC\6-\Y;$R`0C!<*TLE`TBN`;JRXL%I31V\?_\W94AQ&P.`@$650.:SMI4Q5WK +M\V'-4[BK_4\3N.%.DOJ'>J1K@J9&D2*=N/9!!1D2A1=V.6JD'D(/S>F?HJ]5 +MY1!=(KU]K=4NL@=K@%9/=+I-);U+X(S0(]'X'YHP=0^Y[%K[@C2S=,0:3QGK +MOQ9+[\LLD[7_-:+58YZ8?)HE@(8B@;@9)]T*8Y^!QI])LSY\?7C3KZU@N?B, +MOAMWCKU!E/?)[=3B"+[X8)\86CW@5\"XN"O4P^G<^ODPGPM-3B*R)-1"DW#< +MK^Y>Q%_>2-X%^; +M]ACGB/)=C4D,HGRW5SB"9D/Q"ZK%3"0D:Z/8D)#BR;EP*U!&'X,.G_`HZAL/ +M!9>0Z,:!<#7_@L^8/9MW[5YR[B5QY]LLE.2:JV=SS-M=B04;BZ!_9D\].G>+ +M;X7(`X'(#G!S)=T&5U7L!4-\2-.FEO;)[`.)V@"<["'C8^!.;?9B%KLTGP2@ +M)JZ7-$EO_`V4X^!?,]!!2J6]1.T%1H^*!%L;]4(6>'8$L3TS8-FX,U:`>6>1 +M:%,OY#TLBE7WL]!,DS:]M=L+L%04'M][2V4R7W>P;+$\U3?4HSWF6(N3\2L< +MYW!`+^##2[C7(1F]DY=M\"XD,.Z"O0Y8=;6OI2F+[.!=+3C^/8 +M^"PXG#2"OR#]QD(5'1K\U.WBW7FD4\M?G'K8&\]9.CY$7^9:XJAUD/5.X^8% +M(2]DNI]!:J=,8PW+?0/A&:1B]'6:]^RE!PH\8B8C*A7Z(D^=)?=V*D/#$R?J +MZ=>X&WH]V[8OSHQS4(:<\CPK<\JW\KD-Q9#>3"\UG197 +MU/Z9]NIZ^&VNM;'@1+39SNK$(ZPM:B[4+LUSAQ]2A%(I(N$S6*V%#W^_^8^? +M>72L'>+5NJL/A>BLVYZ%Y2WN]/.#(A"YP$\X#9+]760.8>%T76@D.^"'?]/5 +M\CL&RF?M[J8@=(5YBSGW?A).@(]9&%41Z58)*1;Y(.&^#Y$HL/`MX2(!-PJL +M60,,*B7R-5C1X8_J.K:A;U4NDD>G$^K/]$V0R[1RV5@"6\;BP:"S%3/,A"*: +M46JK&CL;=&IV*(8:`7WW26ML!,K +M@-4;Z3@.AP*O(I5@[HM(RN!:Z?5Q216_@.#4;#6`\0_Z=E9(2L&I] +MQ6]/3#K\91B3`T;JFNM)3VIA-/O2:8*L=Z/B8[!B>%'R<-,=\?2"+TSGK.MM +M74S[L]\K/:J0$J+J%&PSI6(MKU-!X0"*J?D').(X<@5R]M54-VF.$9=NE +M#``+3*&0H+](S\/GW]'HP0Y9@VK`R`)[.@D5^#(D6=0!\2!O^D2C64K&$&.L +M%)D?_WQ+`PPDT$3:XIP!J&64]QSD)N"_P#XJX>;=H:-OC@M?%0DXZ5-H]<[3ET5,.MG8Z40A`9E^SWK.P +MZ!:`C*`=(ECHHV)$,I>Q`3UUYGM^K!11?.(-"Q[**'=?8)G,$I<$*F(Z.M## +M3_P>T^XMYY%L$!Q@^, +M?QH+S>%@GF/@W52=3UG0V\!B\(\3EK/_N!'3FZ^M?[:_Y)/\7D1Q^QT:^.$+>WY9>!UI]5/(-.>$4'74<*YW\7U?M%U +M9>GR15R_9*+]/)@W*0X(HPSI^=90NQ?A.3?M5?M2NV3>%U%(5"WHP8;G?WS; +ME_>$B-ZM]@X6S.&BSD`A]PB!#E-[(AWC8-<'[?=O*F_(ZN=T/@38\4>DNL,3 +MP.#@7*"ZT*Q\DJ).Y\*RXX@HS)7IG#M:X54,2T$](L3I?0[R2EEIX*1 +M]0'"G#::)GQR*BA!KYL*%U2E/VNK0@0F!#RD-B4T-D@9[Q8UA]L.4WP^@CJO +M@Z[RM0M'!\`R0$L^HM!U9FV1[K$6+N(^ +ME"T-3!-8$EUJ[5(&&Z68#B'A0K/'`O>^XMNQBDAK-96.*Z%5TPW^ZB^2%89: +M2!)2\@N8EGWA$`3'9MGDTO+=I>$G@Y]!3"_^BN3B^-`VC=?`+K&->O!$7;8@ +MEVL<4O]B+\_J073.X=_(H@#<9_A-AZV*TBG$%D5T'=1$34-$(>*MA1'UIKAU +M>V5@J5MT^?7:$G"2&_"U& +M>!T#EG?A#@+5D*Q<9^#+Q&:72SKR.$_1CV[+WJP&B8^YYA'XRU)81UL1-?3: +M7D475BQ:LPSO]-1A+FC)]'1`7(ACIU@&8X/"IE=A/W/_;R3(.W.59H/;G/#) +M"`5ECH'KX0H58)9&9GCFHT@@L5D(M+*5CI6"'? +M:04N(9ZV=FA@B0,)7'I.,+A?PLC1%C9)R8>L&;F*BWSX1&ZD=Q<\VVK;8R7/ +M+QHF_THPH3L^PV3Z-"&L5N^^/PH3&:8408OLT`P97SY\`(F`)Y>$=+:#5`H: +ML]A*\J+*%80QGIJ`.DGP3V/.FDNDADI!TR&`_B34Q^`5KDC]2ON%8WN_VLZE +MZ0I:#_/WXPGZ95Y#J"3SW=:K,!ZBN)W::P0H11D;49JG#Q)R,L%U]9*3E4@+"/;N-W1M43'YK=X)0D=)`N +MAY"5XUU@PSZUZG3SSEN0D>YO401[3SZ019`F[<.'3:>W^J*(9>&>493@9LS-<\%)^A0UI`"&8BI[EOP?CDK'YR2;0>E.C9BD\ +M;P%#WX$#]_2'.Q!M=$Y$H<&VWR8I*7FB;X.B!ZU>)IZK>!&8`KI]`%_\7=B/ +M"DO*XNRLR=:RFSS/J.1Z,A,WPW+[S*P7W4Q'Q=LY-50GFJ-U.8R)K"-^0RK` +M`:S+35D92F`E3F'-E@7^V&>T.9UM5>.7.=IL:9ZV2L0U60C2HG4<$6VJ3MLZ5@VE2R%EZ_."OATI)%K^'>+. +MLS;R'\H1I`(!%;.HF<[S=Y#64;&;3[C0=U@KV*L\7Q1;LD+5HG8`/2E!E42< +M,`&F:"76B^1@S%I;2.(JRHG*!UC94>?DTF?^%'>\"N>T?I,?$8JDQBT,`HCJT.)PU_=N=$\H@]/PV[B)T*6D4M3#G,0%]#D((4KR"^8!A3JI,RR)G/DCZ +M.6LXCS*R2YX?B6KU=H]GVUHC55P&&DTME1XY7K";Q=0X1@UEH&^OGM8I\H,D5UUMKDS +M[IAR69B)_$07HH*!XK86V7YR+'3K:B;W7%;OPEJ]]V[;MR%5\#!%>SY^C5(N +MQUSK/NB(L`HQ5]'^N"1/M(Q;Y^DPC1,V]_WE!V#*1U+A/>-BQ"+%W#M1;<_& +M05+38Q7.84SJ-Q>U=T<*K?[(/6JS2US7]9#T/`$I41[-O=3DK',4@!7D`NQ$ +MPX:@M-U'HC^CYBWQT9)A9J/B+;*RY0-#PZ8:%35(@^1[*BK]=)YUX(Y.)LS3 +MLGB%B]TB&"%]QW:'2.5''0>\MJDOA7R29)*ET?Q`_@L;A.>%ZXQ8S@G&9PH%*+*2F7ZC@?'@C5(*V,#.Y:%2-5YLQ,DS%44>FZ +MTX/^,ZG/FO"Q=+W#7>[LKH,:3$0_IB<]+;O+E!1/FDWY.9K/ZI=RKXL`1@-@ +M)TZ99+<#9^H]Q5M3.FN"_$IW60BC.!0K7^XIX7Z/^,H!WFLJP2$=^>>&$^IR +M$<_'1&9KC+/YVF>=6XQ"%R4^W9^XM\]2#MX;Z4OYH/7;*I>;WZWS^+?_? +MS:'9,UN>@D;]Z;S3F*6T3XL9!VBFYL`WM_3?DKT9'/A(VSHFZ&F1EB/XL[1&ZZ"W.-.T0!M..P[X%HS8* +M8VH.*0S5;DC&4`$@?6-1\'"NLEB>&B[WJ9B,$>59R^II)Y.A0:CK$U['%?40 +M>W%W?Q]JA=7U8XR&V'0#)2'VBYMG=.TJ`86?[(AWN\07%'])U%4/O;XD79E^RGGY4"N-]TP +M<:%UH!A*%Y1][QV.\G^R^])7W`6;8[<0VQ=)#6$^>;VZ%FG]0JP]/^!O7>-$ +M>JT'IJZR_`SMZ.JE'\S"\6\[5*+#&8LNAF,WKTH#9UGT66(9'EL'SW'!'NC! +MG_5\P>/\+]-5&DEE257OZKI0X +M*&0ZYRY1976L-$C4-)R`7O9G7\*%`$O4BP3O)U&JU9@T!C9:S]-SM@>4F@B< +M-/Q%<[3!LJ[9ADY@A:H?'N?6ZL_M44`+C:5"(T35?P?`*T?0A(#WRMV>'XOJ +M[T"]0PSRTLAX3Q5#6YS<[']7U7$XMT@GTH\7H(4#0*HTBC-*#$H5R#\$/533 +M3)/D;8M[Q$!4<.!K'V28%GZL4>TBE<%#HME7TWQ=N@.1F"`DN2,[1>AO6#?- +MS3/6?XY+R9M=:[I:,7S7T`ESF;M/J]+/GIEC0A5KWDS+B\_XDOR>W\7=11%9 +M3!W7X0`SY#AC`$9+]-4??U,`M''KNKMZH-7#%XG''CN/`**GHV+^7NVBE!Z) +M9$\AI`JLH5V,4(U99MC4FJ$3+$ATRT$I=X`QI`>?M2MZ^=];?,$3PI)T=`R" +MZU@\"#`P.ZS,_,QI\2'6-),5JRJ2_0QMDD2P:DM<+CPJ#`"M#3-Q3G4?#$U.Z7 +M:H"J*%(,8VV+C/G^TL'QC^ES$]SC0OY[321R,[\Q\9L,8&*39_@Q2-E<,U^! +MA1`FB5,'A]:*X''`*T4^T3HG/0(8FX(SY +MO2.C!4)48; +MO(.MV-UP85MX\YXE0NALK&1Q2FH5^6*5@OS!J@NKNQF*<=BXF+6U0& +MT81HCM]]@F;X>G6WNE7))T3`DO@&>,J9[++\RIY;Y'F<_`F>P/U/@";/)U37 +M'*NMBJDHW![?T\M)>MD1M?3#=+#3/7U8J["@K4FVYI#4+9N!SR)]<@_3UW?) +M50VGV*$)E\KCH)+&[\&SU5>GLSM297KHJ@QD*PL,+2G!;114RU>-#H_^+A?U +ME2*>S#75SJXDT"Q@D-K)6LRKQ1)^CJAV>N,H9W4F,21H@E5D4.@0!0D/%6DC +M1FI[<-&WO<15CRH2]B3Z\1A[C/YERL-$:]C6N*`!F^B%Z3N25Y/WH]OPLMVJ +MAU=WS3/FN?X]==Z"CR2(S7H719)10T@-^]L\75-KZHS9&,].=^7>%<`L=%YT +MGT7O:>LF +M!O/`/K'C'20JQ']C6JWL7%8S5:24AS.2$..O5**GGR^.,]*/`B[7E3_B[-)2&R.\/E1Q9,^#UMYW.AG)H@_#`YL.*? +M9QJ#?9UJ&[U*'$?02WUMZM!?=B:JC#J!O(LUIQ@:DNRO(`P +M4'>&'.*%_N\IF@&VN]\F+#]K[TGA\]^4$+_+$$*[EF`6RS1?*T>0(Q>F@(*XB!7VG_AGK10S.$0L^-B)'18!\-#/,O7C6&O"?2)B!P':9=)S;1;P_86 +M'EVRBT3H-4T+LLR;=Q\D/(O9&)?S%XX\'EQM\87$_X]R._CH5MX]P.I<:0Z* +MG_MBJQZ?)AR.CL&=-1)8DINN<6R6Y-U7":&^ME9Z-B&$E3H)2>0C<;UL5%(9 +M%40?>[=__98.AZ@,U]],%WG7!'UQ^[Y4_2R@=ZUB:7'"!VHCPCVA>))K\&+" +MIUPU'=!.L"F)K5(Z.3HF%/GY;L*T_1\#O.W\KW%/J`D\EI009;9DHMCTVS=T +MK4J+%72SWOBZ]RWF\\+6[XE53-]D)F0CA>)>UH+3ORUM:%E[2''=FG!&!*CN +ML\.2^$L-<4CK +MR&73D>8#QL9@%!RA%Z,^]NB(6&]J6Z37E@E]_X,\?,Q_B8V1X$#\TM%/M$>K +MD_$KAZU2I%Y4LIEX),R5+FX[E9%.@C%+P:'2\LA!P<'9YG_>D%\<3FWF]-V; +M3Q6QCW?O1O3'>(:[NL0&(O(=!>]6H[N\'#@:"54.74)G7L>@@V&`.Y053T(G +M\:+'%YN2Y07'WD2G\F!B$;$P;*0N%G=YH`_+A>Z9.2_![PF::R7,H$K#KF"9 +M8FLOV&];45(C!D1@.E&@%A6UE9SK?#9N!!8N8: +MWDJ;DL4A"AB1-YUG2=N3W%N?[Y7D6?[YCF?NHPH:BB86Q.:5F!4S+>S#E[EK +MWRHU<^?I7S/7X1=5Z>0MDRU$N/>3#**&;KHAO2$A4:&JPDKP_UQ@-E(ER=.+YF/38N!@6^7ZJKN3VE;RX] +M9;5ZI>U5$CJ',]D,^W=9NB9T/\F[HQ-FM@2[H:4@-!)>)ID];_[\S>?192&J +MB+XCAGG9O(*I$50CG#3LCC0IL6K#H!5R%=ROW542:>C\44/EU\6XI1L0?9/C +MWV,S:?O+_EVFD+%-Q[.@O@YG0L;2KP!N*\E_M<)\E1($@TVOW#+=D1^-E-(.@*MBCGJN9,^2V@-?SM^=_`VKG2HI8"&QF!_>O?]R[*H)@0EV, +M!I%4,Z*,%'@MJ9.O`']I3N*4CMCY^R[5>8\KE//K/P7\G=52UN;-%T)CI`4#[<81B[[0W:KRGQE$;5P^A]DKBQC3;8/PNV,EO$GKYS7#+ +M\T"?51![U&;`VN2L@[SXIIE>D^)`^E\*%]M9-""R>42OXZ2BWNW7'*#VT`F! +MVNX*_TTF9:W +MH$M;4H4BJ)34;+CZ-;"D,Z2M>/\1LT\Q[B$`AYX>O93<^6SW7WU2HXH;SFPW +MKNZ\"S!+&9M@-QHAD:H4KE?C9#?ZEKY#XE&1]W]R9=1;+8L2FW(.$EU*&(Z' +MNL7I6&M#&+"RDC:_N3[@3NVU,X],5HBKO-);B[=JR6ZX!K%+G4X#XAL1GDPLD<&+_M,XTS%;`MJ,0DB^:E!%)VE +MX55.SZEB5^]&G)XA>I'D*&)*4L\$&BEGP=2PW-;I(G>I$0H>,LERN./A5V]0 +M)30`@MFW5'L^7;:/=FFY"X,H_VF9T-]XC\K5>RDM#F$.OC!9OU1<'CD-GR7" +M7\Y\6[!1%%D@8:LT$5C3L;^:[EN[FOMNJ3U^1.0ZO\R9C+#;1%M$7@;$3,J_K68 +M`+&"_YOO^&)8:(JY^4;`0"%#^QYO6/UE3BD31Q1",EK1;^CY*'BFS"J!?1'Q +M(R."[4),E',N]XJ'.R[&,:R(&[WSRF>UIR\/G\9I +M0:`FYZ.3>)W^I3$7G>@9O%CXXE6%/)NV^^3AQ#.76U>A5C^MBP[KSS!W"KA^ +M=S=Q!9:;%4"/@YJ0VRJT2QFM)*(>Q:M#HY.@+`(I/D)GKXX(W@_7]1W@P:#Z0>%W:R5?T\ +M6O#X$I9XZSR(*ZWA5B1X`BS/.)*'0;_T"99Y?['$(:O'>_8D,4R07:R43J8Z +MJEID:,(_=_W`[N.<2R`PWKO[34XM\*YI^V9;<"-O!!WD%S=O-^)(YUB%3"7D +MOS50MRZ1BX"&BNFG?8PBK%9W+[=BP")EC^R-/#6'Q`%RF6?6^*[+NK&.6>OA +M&=E4?I(%[81S,7D\%^B'V50%IR65PS35;8'\2;Z7@.%_HTM<_?9Z&].*I^Q^ +M=XYM(_W;P%JR9,?;]&'1*:)S7B;2F4Y?B@#*=ZF(S?:<[^M5_S8:PM\V/B]V9ZJPGVRS[ETA-+`["Z"YX\-F/_1TTXR0WABKZK+G$IAH!0`;(<0[[:!OO(;S>F +MIMX'Z\XY+?^?_'P/K5^&&4FW\T!!&J=0=)=)Y5/8W8H^6J,((OK5`$7M>4?@ +M8E>'(JBOAY?/NH7F3+=V2.[[;Q2EK"\1TN*,4,LF>K:`[M.;P;T19B?2#IOQ +M1ZW]U,7)MCZ/>17-*TVB>8QC$BI8-H`G;4]`>ZL(XM;(/\_ +MZ;%$-(6IX9JA!Y@9LK0>.Q_]Y*V:A9:[VLBDS95UH+:&!@NT'<\1A)^%\?J02'VSH*RATPFL57>6P1`[6%_MT2C?>4OJPJ4ZUK.=5%%URH\U>Q%: +MZ-/,6:)I[,A;?.PQ[VVQ +MJ'Q)VB$)><-'9`J+4A+5XMF6L8A3XXU@$Y).2(_881^-4*:[;V5@S'OY_X\7 +M((UPDTFB]-O88_:PR/J@!K5Y,\ +MUUJ5;(,CIZ&]P0P8J"B//*"S$ZUU3J'0^FXO$0$(6,")I13(^@_+.1SESP\A"Z5$\IWFVDL/J/,P +M(%#USBQ:(T"2@`70?D,1JW#%#HV/.WF.6HZLH0G1?73C>18!4/"-E"%(O-V_ +M362-O-5`]'\N"HUU17I\KF)^6N567&43K>K(YP:1-6Z0;GU%Y1&XV@S0([GL +M8*C,/PUR6>[@M^5%GR(EH-(!D5`B3@\I8').TNW7%09^W"(??,](-]^^3:"U +MTL8QA.&?/<"C6_>HB[Z$CM#D;O>(>MEJ]DMB"XMV8K0"TQX!#9Y?-4NWD +M-,M`T?UR*\O'<;11*>P>R%[DM,*V%IQ=_CK.4,V-UYDOK*Q[@8'_$@!V*RY!\BL`6^2]"SBJWT%6&$;V$9'BH1_^:H`RE]($FQ#:JM&+#GG7)[$.E>2B\L9H +M:T?#-1_SIU![*QJ$#NKOAW!:?'`P1@BVM0`4Z1[KNL:VO8MQGR)"]13J;$?T +M9C,OR,@WJ0T`/1C>[D07DP::;+0C[66L89!:H4HN9Y\L)B'ZB>SKRG-@9U=< +M];8[?9E(=#MX,W4MW8"+DNDG!I+-S-=9/>X)SUA/7IXU]G@[`*1J+V0>)$NH +MZ]8S]KU)>3XWFCM70EM!-90?F6X=!G$N=`-BZ`/0FI0/A@2MG,U+(*7BNU +ML^&$I"CG,5M`=HS:`WP:$K`,$%=?M:N[1`N)"X^.PW41_96&`(#V!G=1,$.@ +M4M@RLS'Y-,E=M2Z]0?^F<:.LLJ65>8B,R\X**8A0WLTASEAD&N;3^L*^GM?L6G& +M5BN[^0`>DX\`1C3T.R&NY,25!FK@>V?DLQ':S:3B]-*GT)%8$S[16H_PDC[C(ER'L= +M9R"9]E-80-99].@ZF:;*L=ZR:=-QY[.\7,Q8$[`:>L%WF&GAW&B,Q0)3 +M>?"=[Q'R,"Z."O6_9PO,W3.EC%+V_2A]@L0K@G6EL(@0A-'5A#/N-S+\19*K +MV[\<>H)0`3U.#J_OZ!Y:W*9U%A@3W9V7*][:,O(1)LS!3DR6``*`[%WBE"WUY(9W +M97BB3(LJV,*&RJYN-?AX)LD6JRI@UL)P7=^F`>TI%-0$PY.7V+?<\?KP?Z#$ +M)3-@\QSQ`=;SXZJS&N0BR_XG0OTTZT#PSTKM1PS`'I.\O6%%+FJA+,6M:@7H%B&+8[H+S2-^#F>LW% +MK/2\A#4NB4>8#W6##NZY5$6C8KDU(Z=N,A^6GU$W$`L9TBS`H:>UC?)V[=(% +MM^DSR>7BU/TR.\NO&X=-X-%N580_ZNGZSGH'^L>B\#!]4GB]*#(#X*[9RE@1 +MFV%FD(6NS)DRLSZO)%C5[#)I09+3!\[ZI[O`&6;X2'T45_5:G/F+GE_.J=`? +MM9CR\IA429MA)O!O3T&6[X5(;VHB(Q_!?\WN5_$J0+[^Q!LXP2NCNV)`7_:CW@04T;'V$<`W("6-E:M>\>< +MM.UOF7?_$)R?"SH4=/P]$YC/2&?3'[3:H2*A1"*_*H'K:T*JG(4^ +M4IP*=-<3X@GN3)VP5H=W)GVAM52F*'UWJ$E]M1T;6NII6:^*HT)U3]VGSB2# +MPG_9*\:)S)VHR?%\B_C/3XV8G!\S!]$V@[1\'?JN[U%I5G9O8E_>N!K),I0> +MN-G."9(HZ$0@#W17FUS=SX-&,JY3 +M;[KZ.I_5/0PR(SPW)R'B.B"#5=JZ0M5^F503UE_\L*Z33S!T%K.E'G +MW@:LFNMOD;YH,2\H&'I.^BZ890U8;0I\&7>)^8VF^I,;WCVM@8YGXPX*RKYN +M%PS[%@Y?!D7CD*$%X-5]N+C]C!.;A)5\&(]6%;6`=ANX")5G.("\"/%?"'&\ +M#*<#1HLY!ZABW1%KELD0I4:.SE]?Q8=#W4.:+`NSQP.$$]W]XPN>@^;!IREC +M;++EMTW!;Z"J8 +MA7UV?8F3WIM65OYU<.N\00I9UJV"3W!73.F6>@+4.F3C3>HN&`O7EU[]K,3Z +M[^>JO$,>(F.`U(409#%96+H3*`/31&?GE[POI"*#AWKK;6$>5V!.2AL[6Y1K +M5:)AI"/!B38T9I9G$_%7IQ#I4*6O?IDM`!N^<+E[NP%)]X.S5@NC:3`([!H< +M/>[]:P-IYP3N->$UJ9\*G@/*Y_?S=XT''<*^I&O":7-5EX6!A6.B%J0X&\_P +M@+D@?[+9K.^6XMC`5(K7'GJ&XOG',NZ]L`U:Z>/CZ'K'L=R:UB_&&2D^[SS% +MPV;%IOAC6ZD%3'(B+'EWTU7KVLS%[=>-6I]Y>OLF**Q?')?BD\U9K]2/-&J: +M`\GD6M2X:XPW9#7O7154:1*=)@2L;6;%RRF\8VQ=D+T%6<'NQN"A6+&UV?[U +MLQE`Q!D*/"NXAP=L1?2>_?L+R\>-!=0>K17@W*7,&;^10&QEZV#]#Z.&);4Z +M\JB1.%?4@[MQ%A[&5,^D,HS]-9?+Q?C=&B4#,V)&L$US!FRW7851SL%1^7E1 +MG*/*>M#8'!*5B+=.??"#1D,9ON.-$>G.C@S5Q>HC+Y9@[S/#M,DXO]'RW(G2 +M)/13+)9I_ORFYUY\>VU)6]:N@GLBLLP0&NE@+D.=58Q+;86\,5`<1&?J'@.U +M>,`8&T)\BSL*!QK'/\,=:77\/BN1;Y[@7NVY8$[)W6)RC3:9!G,G]:X(?=NM +MK:'/9"WPIV`&GM=>FZ0W\,'X!H40(-L$S\D(X83%EYQ8^EN>"N=T8]_&1/3^ +M,*N'(P'Z:!R.O+AR5G(=JS!?P)@[/I/7ZMZ.##>[+ +MO62C_%KT'0W1(UZ"C@[U2T>09`;_&;$?`:ZVNG+1U@7:+8>M84UIA14M6V?` +MZ&]R[3@"=$F&_I.N53($\]7K)S,GFH6Z@+`-\405SL8+ILOQS!KV2D*-@=F7 +MLB?\:/*K9=K=J7S/FU/:9OCH&E2DMKVQ$!S@@02@KCT +MM9INGX,6=O1E,'*'J.QHZ\I(FM"TYPLXWI0"OC_57C1/&Y`XH=8X+BOE++TL +M--\HT3"'6CCK[E'^45-/0IMT<9M@UK!JGLI#5AI2O8)L(D!HOZ[?*4?@F;,( +M4K6AUBKZ0&A)K+\<#L/.XLDMC4G3V0S18%PDOF-D6X^:.,?/ZNB%1.9]O5EW +MJ.^`6;VSV!#(#*D>FL)#A@[=AEJ&=YC2&9Z#YJZ9U6ZIT.@J-752KA^!Q',0 +M9J=_Q$]Y`KM4J_TVL\52)0:%<):9XKI/:$!_?BS=S6(N+9)=L:7]M7P:??_. +MM:++[Y.SL#DL*V`/9JT""HTSGRIE+Z)]?V<3]0,U$JT9>&7))FG`ZX-2]YR6 +M%@E\Y)@+Z(L'3*GBR#X[ABT[K#.&%J'W++`PM27)S#XB[9&X62_:S1G\;@H4 +M]?^`&D])0`3TM(9/?NT%JN&Y]-?Y7'<`G%&123%#KHLMKZH>JJ4[#$-:3/]E +M/H%I:/2CB8C-GXR=9)UR!05DA(H/O/,K.TE..J52]?EY64_T%.'HD<*C\*_! +M6@7FZ`VB\!-%I98U0Y\\T#!/5MQX4;N\"XR4S\]2RN5SX\H]H._@6RRUL<#A +MD1F(8;FP.:R;E):5Y-;IV^(CPA+MD%1AU@/A;[T/)K+[OJHJ3YJG";-46U&6 +MZB_;4_MIB\9Q8BC]]]\9ABD&^LJXLH$6(XB!S\.\LYCGT'??6#F_%YF?UA;+ +MF<")F;S.@*9B"A)R\=9!K"$1B''5:%W7623CXU1FC4`(OH^TPF\[&<.T04;4 +M-C&EU46G["0YS@6[?XD7M\`\%G,C:$EUAOHK07"/!`W1(NF+S*#V[2OYK22^ +MN9D?##GU_+#ZBV4V(EA;/"4-Y$QY+)%%63W%&.5^O"Y5G0(;NWCP%%8\THB@ +M!(QK]G(G2G[R#T%;=34NH-S'3UI[XX.9SS59%F+@;YM%KD&);'JFZP`!2V3M +MSM"U`U'85I:85LW%ESTM4W'-.S:M^MCFHROUXKC76FSMW"DD]V8LR8/Z)LME +M3B<6%=0J57^\WZP4<_WLZ-7W"QUCLMR$@8HAG2]EF_"#.U>JT"2<^XJ/Q +M/4K&QXV`Y(NI'(HW9L?@?6YZXXHJJW)Y[2/\[=,T"\:B80(P5=';MBHPQ-+= +M(N#X:8T47X\(#H9WNM;'SLZ;T2Q6]L#\;12FN8Y((3-,2K&QNP<$OL`'S.L75=S.[KP( +M%PS-^FP3DD]#+X<*^]`K`IW2YB1ONJ4/O?(@I=VN7>P0'Y'ZOSY0QKTO?`7: +MW\\=WTOHM>"[0_-_8/ERE&;J<=AE;_-.7Z\@]K+]W]\2DU\1S3J]"FV,PZ+LZ1/&*0=8VT[*=[&268)N4"\-$,>0N-XMX4H=XR931.4G=VY?4<>+Y; +MQOUB7++/ON'ZMDI0R_7C/S(5M%_-@X43^BM7$]IS.GNS];-NZ7U\[N2_(<_/Y,QOXYSXX7^`\ILU=<:_^3;>'Q\ +M\=VG]G2]WAC)'J')W0H[##(&B(3WRVAT!:>?!JT`%U+=@N3D7BA]^+4X>.'( +M"@9YJ%P#`[*3YQ-:VUR0"ZXE>EP[;?#<$'=&_Z2G8O?`Z(,F/HAGU=SSNL!P +M^KQBS3*$)PD:E\"RKWQC\"%5'5QNL5ISR?W.VUB;Y1F]O7:TR&VD)QQJ_P.) +M"A!A&V(*Y+!8C7CU><++*B0MY`(!4*%H:Z<0\5P7TFZ1831?\I(28';J'^"8 +MS9QMTP=84=^0X<.;#(6P%7*6":63-!G[H*"19DY-(= +MP\157G$?:?88*-X%OV-FN"=$5XHW]TVU&L1;29I`>/#IK42(7PN&;[(Z(M6Q +MLO,[1^A0@,>]KE,AM,G%_L@H,,>K'WVV!=D*TM[:DPUL +MWO;4E(;^V%A#Q>-_#R'HX6&MS:LNTG15+0INMO3#TI[D+`%B1124/NI.%,#^ +M_0I4K?"%] +M9MS:)*33%A/]FDX6I[-E0`V%]U>>"A`77&W/&?7R2LH16 +M@GY9`TOH8U$H&TF-OG77LF,%$,CSQ[*T]Y0E&F%9`[SZLAW^EF-M/PIY;NT?P;-TE5IV +M!,Z_ATB/&(1YSC^MYKPRVEY3#46O9KD[92N"O:`WXB=_?*1[UPG\![)YQEMS +MNT2JS%2?G5EK1VY0W!E^S._I.02%V*2BMTG5YV2TSTZ"A5(<+F^DYBZA0CJ0 +M^K-@?H2[%9N!:1HP4N2=(N8$R0D[:^O-EIS/_LZ%C(YVJJ*N<>][C,,1;%<< +M$I'TQSS*0K]GCDG(DS)M'ZVCB"=2'O,Z@C.3TGG8K=L(\GI3K*R0RPP)RX_W +MK'_;NXN]7!B&AI=ZCAP\H$L3CF2-QPN2#'VQL.-H&9Z#>/UK^;'V!@G6DOLM +M61P/]7Q*=R1T9RFBW/6DX-^<,S,9ET>^W[O`NJ)PT]1L]]\%X+.8XA5\V&(P +M_FV?%V1:5PD&J6J5MU/;DAK>A`?5H!?7R%4"K]9P8X]Y\M/KW8473<)+N/M^ +M%YVN?:(WT;(8CFEWX7<[C>![`SYVA>J+D2+#_8*,Q6[`LO^Y*7M(1=-KUMM' +MAZW@"3ZLA.<%;5NM=NA].2]/3W?35.0E$M:<,AYIJ3S5I+XKR(E8+B]U-+$' +M\BP[VRI9N[PL.-AVZEJJ*VUF2>/!`IY9,;O_F2FE58$,3-$3(+Y>"<,?G<5B +MQ3,:XT*6O'WCPM%(CD]GR%#$4`52Y+)&8/NRO-U3Z#D\JJMD?/;G/HD]HP3?%3D1R+8$"(B0G>9>ZZP,OMWJ#">1SN*V2[/_[?P[ +MNJ0+89+4[*D@HM"('["KMNM-S0*]ZLUUQ,J:P-T3P)I*'?")&>LTWB>Y(,AQ +M=T`7!-PQ0F=A*_0TYP::6FF!\CY4ZV +M,XD2;R`E04'#Q*`N"-&(B<%@PRPJ^3\.0:S!2X+;'W!*F@NB"P==HX+S>O>%KEN+[F\EG>TO?FUS1& +MM%>5R"9P_/`>!B^!B-FK-T;#1[\4,<\&Q`G4]@V!45._I@%-+Z*RY*FN:SJJK#8C&"P%CHO;,&[ +M$BD6UT!]_"59F?`4B1P.PU@O-[5+IW>G'0KGX>C`9!$K3@OWW,_4*_8%(/::9E]+H]_CO.,%/NF +M8]K_N$I_D3F$;'[;S0]C^Y/C93MP.?>EX*EA&T%3)]R%W56H3U%D$"6III,RPZ +M`[4W\!8)>TA7N?C\8^@;@.SSN0D$*@#?WF`!!R3EN"QB$8#/7D3:W!;5_)>& +M@ +ML&=&P([*<4S2,=2%VGJK13!&K>P)5N"TG@<;3!+09J6/+MV<%;_RA)JFD>NA +M6"Q;/[]Q[W;_I[DRWM6WPM5`T]Q+Z)H9-#.FLZ:W=YV:/.`=9?#Q.43:^X8( +MD>1#[SC7)>Y#(G!:<6!!<$4.^25;/ZAW250PJN/&N15Y +M9=9-IY2G*-^6@OUO!0#FU)>LU@/9R3&E*E@==_YSX:7.*U1V6[ +MC:2P?^N/_":OCFC$=80H%ZZC6W"\PG@*P!E?<[@1A_O@JGP7(3S)=YDA8L<% +M4'Z;TDQ'8":0-^38$`B1OK,E\\(P%FX9J:C1<.+"4+MB*=N*T):+I_-7N*/M +M/I.GG)8M0IOS26!X]J+8F7`-,-8V#%GZ?P4E!N$58V:EC7/=DG`\FM!I>IYX +MC2B88S)9>@[=IZ("]E8 +MQEIGA]G1;_H6P@V7[C;Z@R9';FL?V$!\,]#K&5)*_T_#ZZF^/W2Q\7YSHT)< +MY`Q?@35^;)_+1DC/X>V6*7A*-U*RY#-4UR#TR$"BM$!W2W?"+IM"]/L0(]O2 +M'ZN=J'=]Y6?U8?2LWS"$W%L]M@2=&GOT^(YLZB>T$UW#Y>$M6BU.-YH#B_L3 +MQ`Q$BOJZ-`!EYMKIEBYL1I]@,D'2G04?6SEGT5I7'3PNP$,35S[U073M$0EA +M?\DJ8`S-IY5L'?=$('H2E;"U3`(PBABUD/C)^K$:XL(O6>AZO6XC$"I\Q#(' +M@,R0*.4\Q.J9+("[CD.W=\FCL`J+JN49`T>8QFF\8T]WJW^0JT1Y)Q%1`_GX +M,'A<;VH#EWP:,:@:N_^WQ8D`GCZGSET;[YS_0>]G-C/SH0DEBU-2N>BB: +M&2F??-EL+IW\7\:W3J=[*S-Y8L?N#/]<`FNLJA942^UJ+^E__O*T9K6(=`O= +M2A(L>SH.1)J[]Y%7AH"UAC;1U0#5P^\J<*1]$>F6E_)E#^PBG4]@?_$+7-A/ +M6=8'ZUD+V7BN.$B7Z3,C#:(*'CKW;!LFQ-G%+_8J?L;;TX;351QIZX'!16J_N?&X/!!]PZNW;(_"5PM920`,O23;+[Y&R@,9,S +M4E6`DIO6R>"Y]6*E92M5V +M`!GH\).Y.A0/I/CR.Z0NF+T5X76;V83&0KGS/YS\)#@^"A<8^79`5[3@Y<2M?Z6G[9_[ZHO0V3>!JCR!$^=@SYW&0N +MK)()8`97C(SN?\H[Y<#&]>M/![HP]A>HY5R+]!AJ4XX_@`KSG03_<-]): +MM'ZZAI%8;0UWH.T-T<)524JXJBG +M(+G5AAJC/AIW@)7;9(HU5(#V=M.`&ZNG.Q&J?!]6DF&>%)@[.ED0 +M*VWITQTY.\/FX=G#0L.-B!$KJN-AE##AUE5E:VGRHB:VRN[[Q^1,4(.!M[HA +MIZ\Q^R/S1S.RK4X"AMI`CVUXF4U^I[W,37J#;9FN:Q",(D26%:27I4-5@`_? +M#;E++(O@V6$?OMQ*[62Y8 +M.WFEE6D/Q,NG_A6XKF220D>=X>L3_0KPTCD)E59]6>8Y5[RUK)T"0FZ95+Y'0.!TJQL1T7.P*N;>EX@$21E@;+J8" +M$RU%W3819;5;6A.YA(_[G4UJJJ9]G +M&K`/_*+0R3&^L4>5=;>&+H.9[[)6H5Q&,<"Q_=*9,>Y\TG[,SCY5P?9:;G^> +MQ/]:$>3U]&OQ5!,28AA!,*;7WGTG87*A72=`3UOAMDEV/N!36JR!G(RX4=50 +ME*DP3?FE6/BZF5YDLD0Q$K%3^1OCCA\M^UC'F/=4$3M)D>CA5X +MT,Y*P/G\N(A2!'36-%2(B2,8DCA\B>Y4Y@F4D,%1O9*CRM5D;H([\3PX#UW\ +M0M9IDD#`WB&;5$,A0[X_\*/OD$6!%0LV8'$N7*`,2`YH'I@E;%9%CRI*X(/_ +M,;VP%$-1TY84G79ARX]3)]:&*(Q0CD'X('XJQFY/3FU6_P\SIQ]A&(C0VLPU +M4X]QJIYU` +MM5<571@'Z"$CV?)Z.:OF3\SQB<:_9LZ<=.V4=]9_LMVQI312B3A[>VCM(."7 +MP0?&.^YC((8`L`E`$?5U4@*K/_%4K*C&`0+6Q6O?Z3N,GC6\\L<\W[(Y^G^2 +M.*,=_.7ODT3*VR+_;%;D^R'MM-,-L:2WAE"5\1EY:R*8C*ECK8L"W9JL:Y5$ +M%DDU=[%`=$N.^*Q59-:V8>$QY'\!_NNT!-<^R +MPVC-(Y"4DJD*P0+-0C;"=PO7(8`!:-])I^ASX$/O +MV:&`IB*BCU?PKZCF]2GHTU`W4/R5R[S@UMHV]=S>]MH@,?FG"?`1%S4YZ/'X +M&T"$BML6!2Q':@=P^L1)N*$!3Y1I<8?0-EL],W=Q2V"4,N4]RJ..O([?C:Y;E4\\N:HZS-$PIS"B9L';E> +M<&&R>YENM/MV&X@_+5J%\H41>2P7U//>3H6FA1M\OOGJA-<7-%45Y72O79;^ +MWP>]K@8`$.STBA,PML`VI,=F]Q/`^KCYRNGVL!UC5$!0*-"D\%ZI;-N="PN2 +MLS`<0%47C3/R`)D3MX!/`V*VT(Q3(\O%&CF4>[D=66#MZ=!@C(%&W:)W9SZY +M7\%@P&=GH=_E693CA`&(2WP&:J!R7J#L8SKH[.PC0*&:3$XN_4P3*_K(7V"#I +MQ\'6/^,"VH-(8%Y:'YWU,5PU!14WD!O!C5D3Y*##HX,G(3E#3[-(L&QV,Z*# +MJOV"+.Q2EV\6[_C8@T_U.TLLFW!/#%4!_.2SU6PG, +MDO=H=%=.4!&?2\Z%E,E$<>DPG'I1BJ=MXZM<\*;>FI)55.O+#05QMK="0IYY +MMKFQV.;/3#>(L_D63Z'+>E:S)'[T7'UG&@1ODUD5UG=%M),4FZ=W6+HQS/=W +M\2XGQL'11C:MAG!?P0;[?MX0[#%#38FM\K:(+XS;!O[=8%2RI6,5>SSLZS7# +M15BV'\'_,YABW9N"'LAB&"QW1$RGUWX.>BA.Y>SG[]K\=^QMD]]!/9+SB[%R +MJGSM(]H*Q8Y7:]#IL,.$S^3O$S#*SEAX%J%M[3SG)G347O3OV'&V(">Z;P%- +M/T#5GY/'&G&KX\$S:I:*ABW907*+%(]1**?9.[@/R]1Y)#'_L=!!N"U4CD*+:;S!;M8ZR1_SFL= +M'WD2K,,SF,GI4D$BH?+4ID.QP1YT,VMT&W-Z9VY"(Y+2H-9_1C7QTGXEM!F. +MN98.^8G3&->]]1) +MX$Z@3)?H/-&L,-7"&31BI7;(1[\3=[)2D(J(92#I/<]`^M1IK^">Y#"B;K"Y +M-0(J!S9IQ:D9-')..6024YPT+(SYFT:Q63.GZ%S'.R?8B#U.0"`JM9GCR8S)7V]XK3@F6H5CP\Q +M`%EU3V9$E8Y/D4?,$E'->_VHV0S`Z5.WM!<-8XHB4K?98P!/4:_.VN*F8CQL +MG/>\[9C(FH!>\$=4O_N*>>Z;GX%CBF/6F4:K,R5C4<."G7S"[L6Y70#0>?/: +M)?*`PU>.W@DB_($%W4=CJ#^L!A61[P3<%,`FX+;GA3TCES?9R +M'H%.2IELHWZD*01GP(9H8LUG)9I`@!V;^7.H`2AFW&.9)0$..U//3GIJKS/@J)%'O-FZ\HUBKIGP\XAZBB?="%NK+D_TLD-2T!0:AB5OS%R0-6K*"J).>.)SV)MJ1]JNSSVTP1Q,W`"3;[\350S +MFZ>C'6]SK8*3WU.A8*]>$-3SUKZZP!T^<*OXP\#XT4XL19G:U?530#38LQB% +M=;I-2YFHF!@`?T684N#AO2T!O:8DY+>ZA,G*P-;J*5,,G^;$'=W! +M8?T\IXR494UWR6.=\Y5W%B"7:,*6WT$B[_B)FO_T/ED.[.1$/MYA(/#B_M7. +MG8JN7>W>JGX.#T;9)-X`&]%E]]N;[K2T-15QSC[ONU_&1Y0FJC7U6W#AH0 +M)?K%*"PTA,AX+2M\C(<"+D6J>(==P0OD;XCI2#Z(*R4'7O9QN@[@[GHT%YWE +M@D8TWHYW=DQ-03=)4#KHK@[M3;FZ8BF)[F.-M>;7=G5ET@*F16MA\Y";D)"4 +M^N>%Z!MYKV[\>HH*WK/HLYH0AW#]:L-67AK(E;S#I\B=K8=#4U+TYL;Z=#F1-/IK0EX=K!QS`!]! +MGZ9O8OD9_6^@42EL^?Z_#2^,>S"L_HQXGCEL7-8Z3MB1%VEOZ:FEWT764[`C +M^IM>'>?9+K:GJ\'X'ID_1ZZ+4M8_2>_;5`&)W]=;#LS-3(I^"#@:9CBE\FI5 +M21&>]:"1/M:+*B-:W9-9ZH`T(N4Z7E"<9":"41#(@<6I!,594MAV'!-S,P?^ +MFGW*T#(UO404#2FGV_>U;2F!V0[U*#3,L!TVM,5`_;QH2F.B^-6COV?WZ-1M +M@TB(IP:-<0G<7B6E3"$/6X0IQ_M75GA9)K7,^FE&ASVVL<+HD&>++3?NF1[Z`Q8 +M*M7IL&PY+T``_LV'MKG>P,BKFGR%_#BQZ@?3;0QK5IQ5O+O9&.$K^C4S+))_ +MC@8[/!U'1<8+D<[D%HP&F7`ATZCI0:U--MWSO.%=3BFLB^IAKR#2:RC=9PP- +MTQ?U(BKN>_A=36O<(8$('LA9CC^ID`K^+PF^YB:Q0FIB`_#2RL1OYV)SNNZG +MJZY[AA.M&D%B`!E&V;L88"[8$#\KVA'.AN*$)3=D\BX=B5BA2RP%%K`7']$, +M7/7 +MJAZR.1S=HY2]C5^@XQ<,T)KY>R$('E,(^)D,N3C5,MHCS*C,/10.."S>/+"M +MWH7@ME]LMGY,K#S&57!M-K)>73=!R`'P/07]7D?JQ;J,BRI"RS^)7^+?-IX9 +M,P%[+",AU&,2)?(+=B$1@9W`2O`]=WI2WC/N=6T:K4$`N@O1A$ +MT@V!'S\;KY-&1R/=U%3>YT59VBB[&?A(T:X@%1""(9-W2ROJL-69UIM(LN.>+\C!Y#V.UK3MZM3FCR5><^5X=BI/`C>?306%'_M- +M9#@X7IA9:3<4RW'4-Z5YA#_4Y&,?;AJ#(:GM;3MNTO%@VY3X,.--1<5';O+X +MQS<$QP:ER36V422/.#(1$>_]DXC2%6,2;F3U&/3C6 +MG/P)1BN'@&2<$D3>I+OL#(*@X-?<'W+G=W'#BK[PN3(XF(YTC2N^=EG4X+!O3@%LIF@7E`/-L[^,!"A=F$X +MQ?:UV#O5#3T)G5=$H1]KB^H<\^]`"=$@@0@F/>0J48O+:+,0*6Z65(*;'%HU +MDB4,?"^&[F2_F$NG=0X\V<)5>@DO3P[.K<:TODZ44>Z/W0P^_:3+\5N.P/MS +M(*:_^]#=GCPR4U9]F+=6(FOUMF<5Y1=*)5;K7$]=/47KI$"3?,VWC_3MS:@!28&$'V +M2$DB5LQD>UQ\6YN)V+\@ZE_*PJ,$=5"9:@:T".$.[)+-',G3`\LRG"N]U2:[ +M;&]C%F%EY2ZNB)/:+P8'$RM!@9@[>`5$#_H!T/-\_.@X\PEGIM8#!$/[/3.[ +M6@BYD0BRH4^NU67'-9#+0CED,JW_ZAW.(Q#[AC4(_<=P:-_Q*HWLV(TSPE%W +MC*;ZN!4+,7\`KZ`\_F"CG/[*)(ZA#QS+#)6*7YB6)/*O]_L+LDUP%CAMW@GA +M`T_/1DFR'.-G3U));X=/M]14=V:/]05_V)C-1N]DPR/-4Y +MBM1#R'9A[,:!\_>X-6N]XJ.C"AP\J>:"KFEK4VJL3#K5B))M'WU>2I*I>Y`] +M:650M\F_*D'[M+AK%W*(JP$+PSD$2P:3P>K8UPGD^/N9PT7757'S;%.'$\X;YC"+%T6 +MRM;[U1.4L86C`*B]:2N>R%,_'W#]B?&+K8Z?:_+'\(!3MXLBR-F/SU^2M+%KK_!M=@7QHIWD=?Y05"%U"YE(G`1$)0OA6 +MA6VJB.^5).E/7+!.@-PAI9!I/9)WD):"9,NH6L&)1S,3]:OH."?X$$C7H6>C +M%\A_/T]RY^/GU5NLL3]GQ<7_&P"?#1.R3M85`E%TRENWJW. +M\96^6;I,-@WI%NG=E_!'"!)C>&--C&S>%'/\CM,DOO*U3*HUYW*&`PN?#F$] +M_):Y6`JN:,H2=J\^E8?(%SM,$.+6G)"1!$?KHKTQ:A2^P[S45DQ*J(ZH%G)2 +MS$97R6Y,O!JD)7+KPC"1B7W2DF[;`3%^CW^#:D[<;WP +MFV*6THUZ*0.4UD`7.332L_K"?22RJ$[B(?>53.]M.8Y1ZY1P7'=:^2\1Z=J$ +M00!6MI(TCP2()$POV<3F)C^#J'FQN"(=HM6>@7,6?8!0MNR@%Z1UM^`?L!R3 +M,B/1!293T_)7<#/1!*TN?B]R2AN,.DTYFU;S.V+6_$?,J/JVK]!Z2'?B=*B1 +MN!]]@R,325R!S!GYPA^2WB=HKBW8H$!:]71UOZ-'9'9K-)\%^+)X4?=*<3:$ +M^:#]!"0++DRZ*/>IM+G!$5DVX"O(UXW4J=O%NL+K42M])!/3ND&;'PX[9[K; +M]!V2YCH-DCMO+SH).9O;C'D)R^&ML0[2W&:D0+OS+&R,&5C01/[,D[UC<$+# +MC+V`K^C\YG=+GWICX.^N#4>5>/X?5?//^6L"^\)H%]LDO-LL<;W +M>1VP5FPZ<7?PT4EM'=X(:]F3\.>@/S4#I( +M"THWXB[8!6>.4J9R*KI'5K_W*:])N$.5=%Y)A`%S-=$G@_;48X@NAEK1GL\@ +M/7CAWJ7&G'$`I8YJ!Q"*47C!O0K\1*@=RWO4)%L8H^_K#QJCC(L3VG(`IHV3 +M2,6I9^5IIA.E[$N,@00OQYVH<(74CE8:(VY6I:GE,T=0`!:WM?)H)-+CVEIGE8 +M6-B@)1;]2_CWAC0)S9SS&&$Z__39J8A6U`!R\#J +MF/9C.?57E7&][IL_:L*2K?7-4ZB'H:/@)L0-5[!7N`R%0&\=8Q%VKA2.9<5E +M"X,49FK\+Z&R,A0Z5>^0+OR93,&[8M**-V=Q0.!IQ_)!3Z +M>G:;S56.+Y3MKTW>,$9LF#5L]&>=H7)F&7A-X*S@5EUB*?FT'1 +MNCJJ+PDSTD^C`JG0`#002NA?0OFCU<\8=T6E^D<8/*C+[/4"8"`UDVI!,"U@ +M^H4G:R#@.-."&2ZTABSDB]'Q6&\N^#5WXD)%LM`/TR@H<^;];2>R7@PLW*+Q +M4L49AG&(%KP"(;V6D?9YH/$:U-;[$8Q[WEB4WP=0+DY&0OM`]W4%?BW]MA54]>%2( +M4*/-^(]2IL2/6H?YB]62CO5[6RV<#YQ!19N9-`A`"P>P#5HP]_]=,L(CZCGG +M%=R.9TU!95+!F,PI@CM/KRH.%P=/EY;Q+T;>,$S>;2^%8J%)K%ES:3*.DTW/ +M/%[(U9:NY`D`,U<6P)U?-A7EI6]\Y\L22;\0Q#-=A"SR1??@ZTV#J$O'W4\2 +MO*``A@E!C`FNUW7\6VFU`_O&9RXR'M<7YK_!=`AGV933_(L=6=;F7(V+=,T! +M[UL>@,\B^N[_X"1<=] +MO?.?@Y:+JCP0[$@GC'?9Z(0SV%F&W\Z.=&=S$Z!67Q/@=`7Z%ZJ^+YW9_1A% +M`3GE6FX"@;QEVF^+ZZ8B\4<&H0_\H\^DT+;4MX%+0'YVE`LW*-RZ1Q%E>"\8 +MF;%=N!K&6`&`=!,_S$4>XO&5IQ5342VBE[#MY^C_H,D6FNO)\P&);`6&9?:! +M,*(U-G&.)*4G#-XV*WM#S/H5A8V`5'GO?(-^4CVXJ9JK'_*.(?(GQVT!S=5; +MV1L:WQ>[;2DT-@72[\DX/EKO&R6"7>E/(EOAZ4*TA+&&\K02\H4TN!P";1I5 +M"E55!L:7I-*44EFH3?_)[57X@`WKR;/Q^DHW3GG-^A)1>K"W74O,K+5#;#)2 +MC3EHWQ":P-VO-#-K4$GGIT+2Y%FL90K+ICFCP62NY-H=9KS%6/1K)<`FA@66 +M9)%YW\F6(&:H+\4R8P0,'*PGD5)@:5-R>`JV8,$S-GL_5U&+,>>-Q07EO^1,]3[:O:23)H&%8["S>1W_)"Y<-N:AFBV:O +MA*7=7"Y/4=BLGFP)F-#JE(IZ*[0/#-=![S7KOU6EK=Y^6$]!:2)Q7A*Q)",T +M7'_*`7W;X"YV)2?L/F5RW^E?P6D9@8\!>?(KCUX,=H*S4%L4]\KX6XQ9UI49 +M7!0%\.9*624#:LP'(LUIW2 +M'7/);-M='NMM9.K,L5IKY]MB1X1BNS7:M%%86_4_F0M>PXIOT"A`G-.624>D +MPUW/_6\4SW%;OU$<0$YCLVA?8EQPPQ]^3%#_[#4#DEF[7,[M0G;=50-REF.4 +M)BZ\7%+2"D_$DO+'$--5["1K'FDX+TG0K$8:9N\EYLS:-XM!=]['+H9)&9!V +M1``*,KU86S/N`_#(5"(*FX.$Q_F'#JJ+?7S4K+E8 +MVDY/1@[B:D<_7MY7]V8:&R.3,(20E&9MZ*P8]O&($GLR^"+)KJ$)>>)D7UBU +MY>W[0F[3=NK,Q''RP3B/=#?EJ=NM4BY/C\;SYV'#2VX,;N(+`4,D+%POAL^P +MT9HSD.*TCPV_V0^&W:@=4">E!]8!$@_B=R5^O@4;F$M@[@O1M':VTMQNCQE32:%PKPF(.K +M9)2QDRL99EWY@'@S) +M@["M1_[I+P]8']:8!B"$H+[S`Y3?QWT.QM@ZGGNEV3<=9@N17`Q:LB +M4,2F[;FA#I2$"%]D.8]$[9:N#`2%5^Q%CXR[2(0=)J""C+2M%0>D+1>#/8#_ +M3GP;YJL<]A0X'=?5P)>CES\R8332.-9#A7]`Q/UVZ8I)68QH99Y^;ABITMD2+`5Y#U`A'">31^%; +MU-5O4^3=/F5A-Q;&WHR\C:NY%F\57LF=E0)NW#>/:J^AR +MHW`7PK=;:!06L#=RDH%I&X$>B+F$XR4\XRDJ`Q0HX(0THW?H$\OUB<`@*<'& +M11+!]0^=A[9&U$[URV&(V7=[B72>8#%TR_@*U%+X'+.4#:_":;K][P),F&UY0:3KG4A=W]%+,U+T!"VO=$1KH4`GDI#,O$Z>KZ)?N\PB'7 +MYRWQY7WK8@Z4!Q+O`UG5F'KYED)GEC=L!0%+S6)6#:5$&.<)H[Z"3@0+J69< +M?"Z.UCZG1)HU,5ME!3V:["Q,OH!H,"MQHD!/+I,E;=#N_^,S:H/+'J18O5ZJ +M6P5/0HU@TPB\N("\WO[7?^ZMYC'R3.(?)`"K*3=;,K +M$3!11WL\X#=#G>$,^1"[`V^"^$]@/*T6`!PP#J,S=\BVY@0Q\DL2\ED0#HL= +M:Q@*B"W!J.M",+I<3R'9HL(,&FK`Y+JFO1:K+ED[L#(I$K'DXI#]_@+^/-Q+\#4G3!DJ,,L4J)0)F-KHIQD@'GXS,!I +MY!.3G&03WC^XOAJX(;+3S2ODV6\Q9&'!*`/A>OS.=XC,B)*N?'OEN^\/V8WJ +MFKI*;G7,JS5(06ICW/KQ@K:9ZSRG"!3=X(GY'7@;-ZY\_X["<#A)=:P2KP21 +MX1R$Q#`F)'[4T.'$]IV&J8Z8T')D**VI'!EJ\RZ[4<`5B +MALGB]Z9==4:,;%/>"N"ZF?2R&$[HHZT\Z2*M>?27`-WWK?;0)2B$TRZR'Y7/ +MO=(#NV6[;D:!S,S)^DPKV5YFS.A8_=1O-M^#&F"M[EWUF.0K>\-&!BQR^/V6 +M];ZJ>2/GL[4F;+-"+360XZV#I[05Z6W2],VIZ00X +MK_CGS&0*TM2KUC&_!@X"A^^"-5R8VF')4?AAG!U1%U1!R6DMNQV>98L!10:&K=;,*/OZI_ +M&4L>!T1D[8'MIYT&[KWEC`D0`>M-7\PDVILYD<<-1 +MA!BNE\:5^+%=6UEQF*F.T=@/XCN#W'<=)'1VFQ$<;=-NI+O\&TX6KVB;O37[ +M@VR.^!W5($!5!N)C)7_M=)._E[V%`\^/2IV<\\Z*(H]8!*_+K^4L2H4E8$H5 +M%1-`H^IXGVHORL&M_HGR,AG=-,L\+4P_^+5A+'))P"=VPEHU"*0M%?8M6 +MKNZ(7@X,WO$F^AO)0L[K!4P4T$[:B;4Y[DD?SL2X\!)U\(_=5%,<_T>,[89+ +MR?D$XOABB@U$V42P4CBW/GT32$5BN;$:Z!;_+,:O0$8"`V^OG?N\CQ4P*"8L +M`L$&&[UP+B`K@_W]84/B]'0@Y&AG,WJJJZN^K$RC8]*\H(79+:2MPO,`9_98 +M>A3F1!88SY!EL!(`O=5M49[GH^(#>*0::EFZ_Y'PW0F<1#Z@F9M\X^!3-%%K +MR.!V0VRV259O98(T]OQRO9SRIFH]&T.Z/,1)8R;NA475^GV&&&S?POK\M='Y +M_6@?/%>Z.[5+WKBQ[!%WJO@O;+T#@H<.=I=N/5=246 +M89!'-*DB1Z##]OD6RWGWD%"2N[2!LR.OM6567)77:W/&1[5/N-`[8+X#H^(" +M+XPX_`&T0 +MHQC%@1TE4>?JA%+`>,0*J +MR#X")9L6F=:0/?R76^@P,Y_H%=,?M65G!R+TL>&HVO.Z*'GCI8[8!.6@--*E +MAF8',%V,X-+!UCW8K)];UBC3/JUZW&J?6#OX8T5*S>F0$+'%`H@G9#0DG\F> +M=K\ZHUD($?876DZ^O$("CZH1V/))`WY8`UN/(=1A"<.IW+Q!_=$7)>X27GN/ +MTCL.[TU7F-TIL]&U.L>91E:^,G#7PZ('Y!$U(K[WXLGZ=)`^46)O'6^%CH<$ +MO^80,O$5RQ0`YNNC@.*Q#C?]6::?L!%.1VBKX;C[SPEQ!Z=9.1W930ERDP.\990UR0P((_AH6K7'Q!OK:,PBI.^(,:O+'/0$](1) +M52(L%59N8)"-PO"OI$,()1M_H86N)5"TKSM>*R5[ONN>MZ2WG!Z#1K9$MQG$ +M&7HZ.F>;9VY=?D\*I7Z4P<80=SQ:RTTQC-%(*-B+H&<$,_1%HE0)='2S3[&: +ME6#&E.S'0`WV`R'#?"P],_!3T+V07_K)GZV"C(/X*003'Y'!8V+8$2IJ=G]& +MPMB3O-)JE7>!!K^W06@(`H>4XJ%E2&[)D#>>(X#L&NT?9S11\Y\(=D**!]19 +MGH\=\'RK^S=E^7:F/X!$7$0G[.KB'`QW3.EJIRUD8-\?EZ<-PUIE0UK\JK%!=^QF5Y +M95[Y-A\(J7$1'WHIT8GULNY)$[8P=U[])/5N@1(K>(Q#Y0DX/60377CCPEO,?#XJ2AN +M)14101&_BXJ1I;A=T)W)+BMF`]2GP697I"!&R'>A"/APZ3]CO%'$)<#^O4JE +MI3@4\LQR&AM.\Z9Z3%&GN4`L829TSII@-_X4^Z(Q\<:'6(1 +M$X=_LF&EH23XPVP9OK_I.02Y'-PGLG9#R +M"UH=CUB+D?N2?D)"+NX=^TR%!3S;'K*9:@V1S/BL25+1A=P;G&2;Z/_,RAHO +M,66Y@L1AUGUU>E+3G?5"4F41^F60MSSK'']A#G8KU)XA?!E4=1FIW!#"%6CM +M_?739#O9:L[;Z'('BYEMRFX6FQUL,=3[D#_.:LFR+(%,(H+H]35*WE0AV@)[ +M(Q;5,4$O\$#B`HNOV5C[:'/O(,O-3XC>6-[(,13>ASRX^.D-.Y[+"Y0A:QX5 +MQ@ZI11AMI>TNZ249^@`D!H#JJDUD+PE=\/662TV-R\EY*+)ST6!(Z%Y63]!( +M.#""68KM0COMH64(0;=(/TE`F>2AN.8,W5D(X15Q$ITN.$_9Z:G>J-;O@^&W +MO9+(,$QX*15M=&M>T10\/7J$K"!`@#]VPG6<>N13,Y!(N*>#8WRCQ\?6G6H8 +M]T3ZE`4(S!\G\6NY@R[*]LQD)M'/$W@ZKG0!\=%[R^(*\"":,"`(IG'=12QI +M+-BB&J&>L`-9I3_MZE=()BKK_W#7-!A%BXK[HIV.\F6W7_7)]B/:1YJG@S8# +M4L\3X!F2FN-?64$N]C]"JW4:U$A<5C.<:DY)Y84\'JU_49E>]]HG; +M3KKV+K@8)OE^N.#/E7C=0Y@TR;%V)(9G3K]J(HOZFWS&)S!"P5! +MG$3;\W1U[398,A8_JZ$)]E#BVXBT\VL:#SR"?.'!+P#/[_"G_F'NEM:C,`N< +M;\3\Q-"#SI]3(U)G*I%9@@3#=GKTBH$O'\?3DU)%`A1%FR_V/=,"#1)Q^/M= +MXAV7?%=Y(H!:]6G;+Q)6DV0!.3?H7I$Y6DI! +M;O>S"D&@+0](I'S^6=[/UUOHW(.$IODTW-$K)*:H3;.?O7M&^49,/+*`4`3, +MD[#K=*;Y3%0RGKE(M[]%CT%0OPV3497TY5N7I'CB9_R$&H2H2[MK_RN2'"8M +M4TT^F=P'W*U2QOE:#;^A%D!-#[!^:$-ECZ, +MHB(<9[2Z0_.H\@O&EG5?`;.Q$=\+V(&;"_"?L5W8S&V@%G<$"0L8CGQSG=A; +MS6S_N$S:YN946`"VV_$OR2X;&A,RA#LRMDDU5S'6PI'K_KA%/A[%6!_]C +M2Y(\C3E./=1U&M?BQ*2#I`QK.WWP]<6D[@C+>?/'Z$_RQ)E#R/*6 +MVFI_5<6B<6.Q!X3^,E/EDF*8NE`TZ3'.IEU52F0#9ZQ<_OS[=7Z:3YZS39WA +M:B%\EA4V1VKN6E`R7-)>05!QHN@`([;U[34;D/EWDPZQVG(Z\F9^H#+:/XJ&UO7Y`PH+<-\<\I@B +MQ!-OIB.>+\Q84?MSW9>UZ85^C@0P?`&XIO)&P)K`NI4VVNMRJ`JGE=6]$+D +M:EPH0:]3J;45/-6Z=0YS76A85H1%_`?B!%\JPG38'@@*KA!A9H"T\:KP\G*- +MOPQE,,2P4&Y9+[5W;@$>P6C=?EYL_2S/]4W2`4W;)!@C#/3@O?'*YO41!;'0 +M8;652A5K=D%C/^RRUH\;"B!D4BRZ)_B%6`2*RSH4]U:8DEN-OC8%81S_E*PC +M7;%T.PBA&N]]AIJCN#?O&H3H=TH"YU)L391XTX//;E+L>*)I.NT==/Y!'CH8OY?Y>'&X +M3_J'W%7!$,1")"V8&N6O[(\!O!;^[>:?1^WR2ZYO)&*D5A8T&5P\PEZZM!V` +M9.ANA`=>74T\056#^F2R&I)1!EK.Q?J8\?4O.8R0T^Q_WOOIB'@$/VS@)"0N>O,N5G<4L=R]5AM\$W7^E6(J/+I:88)(V?@OY=-E.!I>!,ZN9.W4TR9J +MN"._GW()@2_*02:(N9&;N:.=@_L&4"XCX_[$@E'TZF +M$#3(U2'63/N!2)XUM]QG:;9]205Q+^S*1TIN23AR/J2-6MA].;G;W)HF7%=Q +MH:7_6,H^H:]EQ<@D/H-F%C.I[PWI)/-2SS4^ +MX++I([K>TS`@OMA0R\52*1ES!0W)`>V"//AB(UK:[7$Y'QCJ$T5Z.,JN.DX` +M)I5_U0S[M#V,3 +MJ]GT+GJ6$ERZ+;@V2P:$HK-4]GJ#W&/CV^0;H*C/,I +M,0OUN`?B)K@20.8+#M_T/I3=+/SF4[E?X%]="-[M()O4$?6N=!EF28J`:W.2 +M_P4=Z69/']('QA4T1$X6+=6-?[O!0$A%X+1U;(7#"!V6E[Y!S..*R9I&)6/A +M]EC&V"<4YGW5]V3_FQQR@&!]RSP\L/1$@>FO5#P&7]Q"%H?#]P!8 +MPRZB]/>Q2>O$EVJ(EG1BGA/JT?#S%$9=T#L^M]I%@G7^T`11T?C(RS[(IYR; +M,VG$81[]C=#-`7E?3CWJAYX5BGYO>K?A@!H +MNW0[/7AC@`46?*`']NQMNVDIR@'^K;^JK6KER2^XO6R<5G*G9O_BK>KNN$'# +M@MF,K#N!/6W;=UF3M$BGLC?#NPF_%SFEN^-/)F;/RT]I'M?+YSR/7!#MXM4/ +MO=XEX4[]!<]Y$B]]1R5)M33F:X9XK^L`?3'P,$DEO(KBD,PD$^L)"4#7<-$6 +M2;Y$3O1;+H@ +M0)OX<]HHRL)^FSB((*.F>'@'F"C_MT2&@B@ZV2K1NH9%T(/]^G!.WT=AU&C5EF3: +M*;WA_QOA:WNOI+($12,59ZFDU5%6QN+\("ZP+.)B3TIX`5?R&,P*0IV=PY]0 +M2A[<)4JUM_67Y*P!DWYQ-^$8@X<+"]?G$JVGDID5T4L%(ODGTY-U_&3<.Y]= +MXV62BH+\&L6/1HU[!A""T>5]AZ1+_QS]#ZD9XC'R,*:AEKQ'Q^._%)$U1!&U +M6:T#T0DK42/N:!524BV^[JOK_55'5LSYUJS.%$*72MV*U=82&H!4OI(IJ!%) +MXQ.%M<#53PG^VNLC^1]F-R[?#P5@2RJ-:5/BR2X($!"UZG'DC.]IECT!/E##,X,_3 +M@5S9)GZY[>!*<#&TTDN6-U(H]30SBXI9EW+_VA+9!DKQ4\$W6T%(C(^R@Y,* +M\DHND-4#XY\_FC2CF:GHBF71\"F5@ZQ#0(Y/3G:(/RSPEZZL`ZEK#C6A:Z(' +M$@AH+)/*I-LZQ5*(34P-RTCRR<8H2)]4D56EE"91QJK/;,@)X`OJ`9%<>"OE,D?DL +MH)+1P)JRSIC*4P&3Z4+\L5=WJ./GO[!.D:G#LCAB?B#$"KBUNV*D/^M@=&O(I?_9E,9"D"98G6'P=FI)O;*0;`W#(#)D;2Z:T^/LJGE,=E]H4H4/%$6Q`KQM;>#%8J>@[2 +M06*U")AS]91PD,IHTE/VG5V^_=F33*9LXL^RZ2JF]I;2%62]#/L5I:E,BN1U +M9'IKPJL9OB83SZ-L:8G=5TN9PPA;'MD"&!?-)^"),9=[UV/&)VV@&D3SB!;L +M)X"*CK2VBIH`95L1I2G1XO:?]6N8QA'*K/V1:9B=]PP"L@<\@`8\9<\&.X5, +M`/D3_UK!J>UQ[&^.L=D?BXV$:W">BNBB.7Y0Y\>QSIPO%)WIPGJFP7?39+51 +M)?X&4)/NZB_ADA=;OZ'I$4#*RX!'YT>*07E*%/9D4ZQ:[@RRDDXR\0\%+F9A +MM!M8#$;^\+8P2V@"F\=R-M'.JUW;K@\!\Q3`O,5,]\#:E=., +MQ4(Y[FL^DKY<#3(D1*?J&FH1**4G;3!KA#:+6ZUL\G9X2.P''?M8NMO2:-[* +M"SW_,O,"?O6$@$1BNA.;:T(3+0[*P%P;+2RPW +M1ZDGI9#(/=9/PVY4OW$E;_T>%#GDKDFJ[3]1)B`_PC +MMIT71HU_*T1:O`->]]`[40E\+^RL`M`@7]U2^""E!QX3B@VCLG'Q;>^LTOA: +M'UBCPNN%\NW]"@65!1G%3/^,!'-[NW)EJBU52^Y:XD>5AV2#L;+6Y\K\9@-" +M3RAU-\.I"#-00R%K4#!$_YAM#?Q&Z8)P?EZHR'U-0'TG@H[1I^#C"XAEH?>Y +M:TOF:D]?HT3U:'837\_3II0BWB;I*O8@_/Y!GEGCC4(_IZZ_JUHLI_*J^-O& +ME.BESV!:+Z($1;)XFA-FN@P1::E$5G`G=6SG]*E+:XG*"(7<&I/HQO$]Q5LS +MZC'O#1&_+(7T$*R=,F,71FC'T9>2(!YCSG&C%:-6%&P:MU^U1=N\Z)?(R7ZQD75[X,OR\`@"7$YD.]#6,"5%:]C3E4QO2CC$V%E&1 +M7P%]WCC!7RXZ)G#YQ`>S,3P?7!(B0I3/S)@=$OMUI8J@Q +M1\-I5BJ)=15YUV*B(#.XZ@*UG'FS_83AT_R*8%\5\:]RLWT)K6A9TMAOB?)9 +MD7;^AWW)=?`^+2S-'W%N6^O/S-EC*KZV.>G&'?H*7FJ_L1@[`*/BS*C]I0Z5 +M$:4\T%DEJ>6I9*"#S3`NJTVB[GPLZA1ZH=5$>-K\`11B;"[7_`U7&$!8&T&& +MA85U+A]G\H.WU +M(C+\DO69WW2E<%4VL\U#":I4&P2L_9]M'(I/'?S@6'4[?A++3)B!8&<+B!L2 +MRP23SSWV(\4D`#,2G:%_HY2:*E:T5V[I"BG^M#P"6*"JKO\'=I:45L-CCN>B +MC)C/4V2ULM&XJ"*/\USC/XCW$_;7?[-/''SSL#T1=XX^!K]HEO11E_G>=O$. +M7`9FZ]"FOLZS*N3_4$S*.4E`R4U4?!E4?4K\NW,\3\_R]A\KYL]]4^)(`/_M +MN-C$@TD&>>!"9E6-E07KMCE%.,U"6>#7@%CQNK';4>@Y/('$\-'`&:#SJAP` +MGHBUM6&LO<,KYTU@GZ,L +MSP.ZO5R?U&X!XTCI&E*/>4A3O!RL7[:RU^BQJ)?YORDUQ5:/&=!-5V>[,R$I +M'V$'D5F\W,"==6LBY+<_MW!/-O+N.%AH/6^W3*L0TD$\L9J&U+W#@]TD_^V#5$W9V.S,8[=ONEK*)\JB0TWW2O/P!@-<^6` +M>M:F^3O\LX+HNXK$?>OB$"3@J*O8%OK-\`Q;5K^LM%?]2FYMI1W\R* +MM1?>EEOKW/F\',Q(:JD7=R=84R[A"3,T>"PF`R(9_FL+HO!/PC0WE('CM_UM +M%6F+>D=W$F22:KV+\44S6]N:/+I;OPX)XO"FB".7.L!Y9;=P!43DH3FR#O7" +M2H^B250>%0"(\3]MP:;#5PW83NL(U<](-&Y*KFRN8?YPRH_@`L^7Q5"=[T"Q +M>%-JZ9MP.UF06IQ\N#_/2O^7S!F_=4CMGW)NKD5FJ9V'H^4+UBE_]7C2[T(+ +MH2",[JBRE0Q;CB69X'AD<)E04^>X]V@CI$1*<\34=V]>LLI.`Z4+KVZ)L%:R +M8$*BB`P,80S!Z4`Z/IPJ+&Y&O&!#2E%S'G;@RGE=KEM]#F'TARRGFO*/0F(# +MA/D/A1D<9P9;<+W$;16\:USOI:[1H;L:3M][^^Q@L3/-3QP<846S$$$ZF)HR +M(@.[LX]_)1UO.8(KJ_P^R73I^H:@]33A/8@A@V^FHBCQ2J1=29N?&=/"1`#H +M6FN(7EB+J#X>36#M%4"ZX81FTU-],A#RZ]5$DFS4EORZS$YKXB3:.7YQ7^\T +MB0X=0=/1RYOQ1X6OW.Z9_@C)DE!5@"R`9(E_J,W<[7M:Q(]$#DI'=2!+:'O& +MSPW;L!AWOEUD8Z_@V2K=@%7!3[+VY:-LE7!1G.L##E2+K\L]-0/8,F92IQ*%S[OK^H>\CV5=UTQ9!M=01Z*/R8;M,>P`W&N_697X_,@0*C`N^=`*4 +MO&>2;&+[<:$EFMG*!&1BX_@F'8M*L.1"PYUFU8^945H&M!0@M%59`VY/I[D3 +M,YO(4HP:/=Y"^5AJY"P(5'CZR0#;@#(-?AM&6->2O5`I?@Z11%DZR7N>5%;KWV!9G6W(^B882'MK@WG^Z)P9[E/;" +MF%YE7&X?R0WM@E6)@-MKN:2%57!H#@P"?K#QZV/'[Q\Y_J[^`S19R2^*V/%U +M"(N)ZYEF4E@,FUUJ_N;PZ<461T>0:3M* +MA!2,8H"V-E/J?0GRC;#;5T+`AI:5>W1D:;DA:?W*@W3``%;!)4KR#H]`"RN5>7YR[)*;J[/G$P>^W>>1_];HHBPO9!_ +MH?=I*Q--N4U-ECS.9?]M'-HDW\W1O=HDSB!T<.@(!BHAA/"VE4]1+Q3LB3B* +M+$Y9T:^*B.<.+"QN7U+PH8]\P]\#)U&\6CW,D->_--]GB(<>P7L6LE[$88=5 +MC"2U0(9-^D^Q8A&ATQQ/CT$>Q+T.VQ5#J@VI1LV6M*UBD&&1>)G0X6ZX?MW# +MH+90274D3">V>,*!R"LQAY>23Y4/@UB.6PER'^2B;WI7$T(N7ZW_$OA0\BOD +M8/3'>YI_.(^N5U=6"Q-QZ@4>@T;X1M&>(W:?[WESJ>TFY:<6P*FT%HE!)*QP +M=Q/AG(TQ##$BO&HCL9/#JI&?=0S67QX9"A:HI63! +MBR>AX"()N%M$JV28Q0!6"([_N!S\FW:'Q_-H=$U:S(93DRO:EPSG"9?3TX'L +MSLI&A\;C0&\55GE4!2_19CV=1JE4,=X];(IV0AGFSI2FQ&2#2-Z6DN3O=4NH +M^9UB_:KWM!6)KN3(.;F*`+TG%C?:I??J*3XR(7G]B!390L&S*+5^1_`IP3RU +M$/X6Y\B%T&^86.%.,)WD22PV>G?8Q2TL;HMP]Q'T#7$@U!>[FK-N-G[DI>N] +MG;D!QT5@ZBXXW<"1TOEF($5LLAIA\BK"?1-@2[7*;S#O(>A9!IAW\<'(77Q9 +MR0%$4OBS'"(P\Q0].Y:*R&BA'C+5^^O(-I:$A@TJ6E(H@0`<^$J]*"I<]KTV +M4U"V#1>[2ZOUP:X>RCJ`<--\Y!M*WP(&/3UI_D-='N3$U-P$3D8I`X.04W)! +M*WG\C+DUAF_:%E*$T/D7)[]2IW-RG.>B]3A;CF/JO8.W=E]O=E`A&MBZ^CT` +M\OG7<9W,E09?./1=_%(UB3U`R*X&CE>2]RN6:J[HL)0;NC\F=_ZF<&ZH+Z7@ +M+L+O&7/ +MYWA;CNGPG7%,18^&*J+N`'/L^UO:)6LP1D(G68S#YS41:4VTO;%C`X-/-YA* +MB8L!6+;^FL]IQY!BXLM'O3.B:_P=L%=J1`>H6K-*(;04:5-RVIWUV/-)5&X; +MG@JZ';Y*94U8)*\3"H;[_Y[/&4'F7AH4GB3C)-]#&1$XS,P"K**LM=>E8V*: +M;":%D5:I`V`>CGL11W0O2[MW]QOH56?\.1VJ\)/53X!&VN_GE,>V;]"P-^>Z +ML=!`A^M%Z-7CNS8"U"B)L)Z8\0\0YPPD]Q7N$]_M[$T``3K0L1'4IV16N;`` +M#S=A4PGLV,[++U*Q%Y\01-&&MVWJ/=AY=*UBS(,8UG&#T3T=TYBRWH&&J?C8`%U:_Z0G8"A2O[5B0SPD +M:T567QVN*^-GP;KY_@!1J:H*K!#*ZN';M/.CT)DZ/RH(H*/^Y]<+8P#&SWP% +MC*'UWQ/L9G+$;>^/6P52"3,(>'>>=>[AY5V)5(M!Y!E?%XF&7Y!3GE8-#^O/ +M#X/8OCN4BDF7GN?Y*S*5Z!^/?403\>1,?I+`JZJ=I_%S67K/>08M8I0WS-=5 +M8&'SB8*K!R*R?"%GB#`X,07S[7@YT\$'LFO..T74(%=ET)A!Z^-YQRS-^"N/ +M5M.Y83K?S:MG%7(<4A`-1PZ6(=@B-`?[\*QAQ.CRRT:8T,[F)2+6F^603\Y6 +M\-9MDI%0C%SBP)LBZQII;ZF`SDP==9WLI/>K);A]*_UB"M=:24_PK780HY(J +MR@B6>?S)=0_Q8YT`VIU)J#RAGU6[/6W!NYB8)LE;)[&Q1P7_IUQNN:$;PZ%< +M!99N<_)I^5,V&02.ID-]/)[]=,M$:J:TXY.?0H=M0-CPN1'<*W8!!$[Y2&G1 +M!66&0NQ]93/3(NL[D`S1,JME_RM/,4.BLVX@+R9>YD[,71C_MKALWW6CJUO[ +M=75$NZ*"^Q%A*]N/N8A0X>VU[TGTD]]_!UOR`(:5SD37V1'0?&MF6#$*E7K( +MB3-NEMJ4=XA>SY[>K^;&/S#3;=QYU[NDQW3"C\^]RB9R&I(@M7^'L,T8_=`8 +MQ:;'0VD!0O+_[H/L!X;-&4;571O$"@GB;0CF!N6RD[$WC)-[0;;J +M+NK`Y[;V0@K3X=1X]&4B+03P+VQ]1;SWH4<,\"1[71'S:#VQ?7@&R,$-!N*3 +M(L8LS@_WE>\:@TLNTQF>F=\*JP:"M(A?P++[\GR)K>!<5-=*)"[J!^_='X$V +M%(Y8B'JR-`(_7^L'Y%PS04([@!6W^0VC5=K5(%332(51K(_2.@(ZOR-<"=/M0NH5EQ_E-PPI8UN-% +MPK1)!:*R7>J25U:DH'.OM`+*J;9^#5>4M#A>>V9%#1X`^.6[C6(%LGM+-FD[ +M3X,^>'*IF58*0*8=]TKZ`V_$Q-D[7-I[O7X^D:6,NU9*CBA:J\%:[7GW!QC2M%.!57'A%5H#U`Z:F +M]/?TMNLUB]&83B1,VL_674!%]F2K^8HI6/NLUZ&[G=SYYZ+7%^K7RJJ-\_.Z +MWF:5LG.<7=$03"$G]$"G'5)ZW!??KF`F]=.^P36?-6@!1?:A46\"9.!7]A23 +MWC2(`Y27-U6"#-1GL>&EK)9F%M_HNBXSK9H"F3+DMPD*]`YW;YHW9L]UC19! +M@*7@=EJGM=C`:7UH#):1$(`GW/>7Y,8S/RE!GYCN@LT(FJU-;DYW[3'E62N[ +MJP+.7"#*,W>F,DS1`-#!`LVON..+%B8V;@V9I.!6PG`M6(3C[\G7V<)5(CI5 +MHK&:EGLEG_GMB,@4EC6^Y?'>0SLBS=E`T7BDH)C'M+H_;%Q#LR.,$U6DOM87 +MZL-M8$#)T,^M6#^ +MZYI*2HGQ'%!0'<0WB3"Q8\BGC\!GG^IE/B%J?M*A)A=.$&KN2$_RG-[+\(-M +MA1\?G0*.HQ4QSY'PUY?$*KV,<69A[340SEZTGCNED2X"B98WPDL@Z?86B#\= +M3/Y,KONN_2\F^)`A3P>DNT;$A7!T\*YS.B7N=*N?,=6`ZX3^I5'5UXUQMN(_ +MIO$<.]5,:)5M-^EO0SK]J9HGJ"\6=P3YM@8%QID\&7KDF(GD'<5%RP>WR)T9 +MSQ$W`]IH1'7$2UY`JFR$L39V]9C/_:CQ.`EVF`FO^(B9;B;GG/,+1R3<.O@[.XX""E:S229WT$-\&B/,N!H;7,L_2?S +MLY,Z`##RX\?AI?2)RQ]UBE=]=T.$(MHU[`U([_*0^8V'UEO,X+=WM]7:H<3& +MO?($L5?-7.G&5?D/^$!K\.^JJ*C8AUB+9)"O`]>,@_;0:+>VAO9"3[C+NC_H +M(*B^<5'S*Y\7&'W7D).A[,LL&7\C8H9[9NH690)Z%G*P?%8`I/ +MVB@X\2W89XDD3Y[7A]/W89GX1G*=ZY:[4KP/,3XMBFD-`"6!=-N^&:%A;3DK +M0S-%<%X#'&!GB:K#/(^CM7/&M)=BLM*VF1!Q5L^P +M*`%-.^W/7&K=6:&3:B4>@/;S`+C8+'RC>%C!!4Q#S*U9,?1!%/=ADSH\?0'&M9U>^Y&TK0%W$<3L8IY+ATZ1FTJFF$_9<:!AB)@Q0<- +M7N'FXKUC.KGNJD*"QYNATM(CN=0/R1-A^Q=BMIX>0("R2I`W,N15@S]-99"_ +MJ?GTRLC#K`X+-!IKV7Q^/00*)&)C=Q$O=&1;@OS4 +M@D3P:7I7K@51=Y,:KT_:Y%P8Q6MUESB1#1C'Q\$[?$S+%AGD9'5#`21,2\O@ +M(@.['4^BWN.+F^4*IOJT5=6)*5%TN5\#U_W)@@B#`RMHA,&5BE^S*DAX6=., +M87LU#<5)A;I,37`C2/%X;JR:77M&"CH3A#Q@)4TL^,'<(\ +M:;%"J2P/:;K+4KC5-X+U#^4'6GV1B#A()CJ_C#/+[VE^CS[H#K22Y##;>!+H +M^1;O\F\6Y\C0F-TH1B:RJDA@E%7J6ET0G9Q+A6R,>H+T?CK*]5^0E4^OP%?W +MY:Y,:/<"MI;YKUIJ!OK1/=].Z97K?_>I))61KD+.0'`,>2%^H"?XTQ:'U@/N7:S9:9#F$0.H::R3/]71YXRG2'G0T[F$/6?!(.R +MS5IL9DL#Y]H02S^:OF8"'(&8&9L+[FD-TR=]+YD@!,_^[,^]>DOG6PJ'>Y5C +MK#HPC]8F0F>1U'OO;LGOY-`4`#C@!%7S.?J4S$8K$V=@-H^H@&G8G*7`L\\'?ROKZ2^'4$F!V +M`PI.7:5V1G"(?CMNR5EFO^T1`YV +M@@ZF6R/'NF3(IGQ%%#WS.^?(5!;S$$#)BT/#I'WI#,3^KDY3U_IQ6Z7"*0;>!%9H?EY +M8D-A#'XE1,`P+&:QN<297^&!:DR'[,L?3J2I5R04/V:&7L>C$BI\5,8I5^9% +M!Z<4L`S/[U?+-D:2:!Z>)?BE15\!ECF',^S47FVG5E#]XW/U!!"G#F0J=\K) +M%.?C$@L[4G#'$F#<(ZT@5?5W+I<`.!...YV:(L9'\J.)Z0][=3XDB+SW07HW +MK"$&A4.E"C(3PK@+I!,6?1$JK4!*LV3M&Q*1S8UHSZ2G]*LD1LC"/ +MTR:EUDC7K`+,@_GE6;D8\#80\0"TDZ"_*S\Q;M?=4O#AX"?A^K5Q.A]>%L&_ +M,Z&E!3XK"NG)=?!2-,#?Z_PDJ"%?BI,D:!JX#-AX2T[)D*J8+U@3DPYZ<9!I +M_/`\L=%XKY:-Y4EF76N#11`>7R#1HCX+^.[0!4KEE=+GM\MNEAXS<@7T3.[G +M>/F3B:GP0.MBI-;G.O@$(EAH(_]R'R@A&P_$,[/[?O"'BUT +MSZ^UE\@NF?=C:3]DI9`0]97-1@XNN#NE)>`3MQ&J+M#JW'5W=LB?"@S$!V,( +M_R>>C&,CH9K;H[1,A)<%_I#6#WRQO'EQW"B.H)Q9ML`F^+JV@LA$IT;UP4]^ +ML$/Z:.#CZ[*R!_4GDK^N:2O6R\ABNH?`GNR4Y.2A\@F",*[BV]$2CEUD2XH( +MN]`T^!EF28`E9+EG*<2Y:'"FRP&(&2ZDBF@48?*:L(CGY)F(WC(4EWV6J5(&6&PPZKWU5L%&#(,=E$6YA7(M/%48A])BQ',]:R"1;.Q +MASYW;M]LF3=N6B?"Z%\-U.@4&6*:/6S['WU<`U0BSX5GCY32`(AR!7!T0W2" +MG:CE'P@A;M_#"5UL3KSJQ(#`O*A3[,;DTJDS18TR"2!QU&^;+`*"5#$^#0.8+&>.KQJ>&'!94!!Y(DEYW]8N3F4WY[MOK^'3`S +MJT]E3G5-V(Z9/'&4HF=KC^KY",[G* +M\MWFE.7@PVHJC-,XI6M]7X'Y3I5;?-\B$/TE/2+&0SG +M.&PM0V\U`-%EA1),D>XTHG&N!^-J)*`RQP[SWJR<2`M?0$="5T +M`*8EQ*0;2RR9(7$VVL!.VLL"O:TA>`7FET`;KCA'%15/CLFU@:X'(W&1SO&9 +M">U"_DS_@E#'%I_]6.LS-,*K1"[-BF;8H>F8AXQ\M946ZE60\FU\9UW_ZMG; +M9\1[A+C=8B);:5`A+'B&>,A33LITY+Q4M<:T(1VQ7..VW=@W$GD0WM9,7L2[ +M+S1Y3.))<53$SQPV5%S%%J39!W40P)-!4JBH]-C_0E!7\O$($`5Z@PDU.19!TSG$ +MYV>*$CJBSP7JILKN-"_>_9[NUR`]=IH*,*J+%/$1G[SZ\6T`N5A[H;()$?../ +M3!7):$Y5?/_&.E]@3(NMX!]2_]7^3>KT,L[!/#DO<,OZ5A%(OA,7WK#'VK=V +M9%6T\W8;%L\=3X5A/QOT!^?,;(Y*N$"O!&1V&MW84<>N-K?112NB_Q>51ZCZ +MSWI"^GNCPAFX($W#I.+^55SOG++_>"MFW&`Z8G%XWT3E!FB-M_KE[K9\&.^I +M,(3"8R3^]/%C&9TZ3HKG0B$FD@-YP<]\9@4+^!DAHR%A+SL;..2\]]]^A!>6 +MSH[J)0Q.Y/D;49+$HRT"3TS(A+SLN[U>05=_BTSKX%J[4O#GDJW%5+&3>JN% +MY94PH5=N*,BOT$[J["(V>BOYX\G?3^F'98VEK=,_53H\#_ +MFASJL\-GM0-6BW;`*.+8I'$:&2.$E&@!A42>L@ATL@=&U,1<=6LTQ]Q+7)LG +M(H.!EBQJJI9O9=LF:R(-KB&\T^4^23-8)D(M.$>9K7.4_*2DHT]FWGMI0)5`;WSPV&+^Z*J0T+B04T8V6O,R[P9TX.WVK([;C!()7JS*[^K9?B +M;:G;)T8[37&S-E`;?B*S(FS/!J2LB.77ACJF0P=52EZTX90[7%*N)7K*W6RO>, +M+3I'T[K?57MAL[=DH047_F1K9SX@89>TR`3AD-2L$!)KKI`@#EC,"`B5CIXD +M8@.JJR2"[VM/#+65:>809HGAXA73V[,&O^H]>A1DN9\2@!O2//W.I^`E@:=E +M']/*-&2(`&[5 +M47Z&G%BUU!VCN&/ONJ0YU[N?C_FH-O4YW9`UL8>TR$UU(2Z!4S<55RQX>Y$+ +MGL![F[#$,.*BOMC'+D7)I)IEU;4DJ1RBV_SB_[M$(;0^=TU@_&BJ43HU\!XA +M2A0BXAKPLKTWMD=9I`2;4=+)/0O97DN,HB=Z!L%_]@[ESP?'*+-+PB,HGHY8Z;*%%GP\PDE +MI@8IZE$2EBQ.F+;[0]->I/&IN1'/Z1D=GM>`86I$;:K:T64V_<>-I^OB0/=[KOV4%F\(08#"4H"'KM.N(`%8F9D8 +M1W*SJ2'-8`P1&Y_FG6,$.YT'X!>\1-)L,;6>V+2HU*8QGSAJ/0(RT?R(OSEB +ME^^_H,R3;]K1?(,()[D:LJ[X#I_XB1ICS)!Y8UZ]Y6@T<3G'\7&:OI#9E13[ +MX@**.2T^&U$!B.!!S9A?L_ZKH)#U9/649F7N8I`EV,AGU4E=KK=N-W+B&9SF +M.6$>N""L/B(J:+(AY0A6HA`@H#H4$56D +M9VDY_Q!77T':'.Y3E>G@. +M1)PN,306(Q6*[WI%.$4!EQ3,E%7L>0\1Y4DX>%7K4M[9"Y7`ME__#X_Y/U-=61W8#/;;!#)JGY5<9;G +MDXF&@'XP")H3!>?S^H&CV81&`S820KVF,QM*2.Q9!CP6NT^11D;;4PD)']4= +MOYO2<:SFDD'[!D5BGP(SKLARNTAF8?O`:Z5&2T3\Q=^K0@_5Y#C&:$O[RP\T +MPC#!U1V+!A-!W@C:Z1K*_CSZNL%5_Z9(0N*@)EH5Q@2$XN__C4_KR@/ +M]>2AT`^`V\W@8`KCID$/R\=D5X7+2"=L!E'?.U-N7#Z6ET?I]=)W)-]N.SKT +M?FZHW6G45MG4>HD0^8`C=\;6E6F!^#EF[JPMQ1LMU8]4P=5[6I^0*BJ;*6`I +M]$G;TFT^7-J$875?`,F]O6;&(BH0QF]/E\F;P=USSV61VG>.GB?+H]"A54!: +MU:7(KD3X!NCH*R[>TB-JFU^CV@_5%J@(\/=/.1I=.>N;7$Q/AM,C@6'-80/& +ME`@B[7XS+54J*"32=Q*![V$]?88:>5\A7EA:HA7GM_<3M]YY>\7PB=FW)OA$ +MD`+BA#V[\,3:L5MX<(KW)=@N!&_AG4CYVJA/5:R"-B8W$*1<-T%>T9X9A +M:.^OSM7*'/[CRS12LR&`R/1;[,@N^1"I3EGZJAH_KR-:]8^V("K0'[_;_[#WE5*I6E4G60YTU$3CH +M\XDG0KD82B43O@B16PE]0_!`L-XZY4`*#U!@^Q2ZEE<5F9HE$6H=RH(- +M^S[$DMM._Q.4T7`DX;4G+9UL"SLAG-,35K+MTXPF.]D,[=).""F7MU18RI"AN4Q35:NJ19N=RG'3N=D$U8^;_%NMY0;HZW]= +M*DW*5QT:,2D] +M`*5\:9>3RYNE=6K9D)^(%\6'RYXW9![:F,`C[CO(XEW.N5BUA,BCE"5ZLKAI +M?X*/PU7*!-C&^V8TTXTU1ZPJ%G>/,=80G#ES'+W3H.;_D7W2!_'8EA_'U=;2 +ME;3A:\6])IDT*;*&2ZTA3\UDK_1QKV.)7"?#M%&2'BQ+;4=E(O6S[A_C.'F% +M;$AW!>J^4,D[KC2Z85[D5=7_!:3R1;$0#1$&"7]0*J4('D>W +MJL5N,&B2>F/AF7\)2$JR+P$RQ`=E8PHP$8EL;_R+Z=<[;)4#ZEM(P!A`_-O! +M?J?:I7,*PPY7\&]N]>J4O+9C_BA.W?X->/^9.HA5-+4GGMLLERY)/U.H*6`3`KQ34L_$@/B+:>0O +M$U-?'9\=*WK[8$K]P<2+-ZYM9?=9)=C0SK];@19=I2S84#C"R>U^/2H,D'M& +M_-7EN\'@]12&I8;=1EH:D218@<.'4?"VR3`W_-AF@-<(N3_@FH*\CXJ?*QY5BM[9\^M18H1EN +M87/N%!L/>.@_R61?9G>-2B8\9C=]$V9$2Y"SDSFH`X2,:<>43::R'_"'C;+^ +MAW%AN<\&M<>WE)Q6-YZ%'O[@'D`FZ:);]S^@3BC) +M'ZFF"J=18[_15W@&X!?K[=T''O&WF)>\M\*?>,@28G2<8TO4+B>E@">L\/65 +M;S(F^':IIOUH]8[=E$[-S-!X[W:I..5 +MPG8'RO\+?5,@"4H#]IR6>\Z\351P*K0-@/^K'F]_A1:^Y^,:[^>:8S:0*2AT_8($ +MM'0#.M<5M!Z^!^_F&.%-I17HR,^I&`[L4P_W=2UW?;W3F=H@%-RYE6VF6BH0 +M#[:]A<3(,8`#:_L"K$"-(59_1MT<@UYF4(BMBSGO9'M,2^]AY':J!G,:?M2_/+PVD[LO.3VY8 +MJ4NYS]/+%&]UOT1T*1ZB!=PL%;9D?$+Z(OX#MU)$GG=$;0[,V.]"O!MF[2T< +M\ZP6#J5X,//29,QF$H]'<''%J2M*KX0;O>IA=C^.>4!D;&^`&X:&$F2D&EZN +M@\K>SVM2M\B=!KI-64)^%!,8\KW8K'7OAHI#;$C4,CX_99Y8MNZZIX0YP/G` +M2>_#*/!Y5/X>XSZ6&Z+.+"="<7-9]J/&H/5+TK%IPT8++G:?GA(6Q=:@/T^] +MW&.]O)`H"UBL#AV>>G(SP/9_:7>>[3GN(EM"WLGHI\/+43*^OHKCK3-W-73R +M)X>VV+,A6CN0]#\)7'LD7++&_2BS/\`JO%@2;7:L2ON*)C=S9>1`3#-Q911Y +M.S-`QH(QF8\SMD_D^*O:8-X)*2R@OJ^#CG?9!:2LP,#)V%.BNV'KDEOOWI7 +MB81'X3Y(U247A+-:M7"PHIKC,BE*FK@_?^>C<@3K07\^F`/Q[-`FYV4#BP#I +M?ROP&5'DGO\XY&3>S5$V0#730T:G$!=UM>%;;]&/U#Z=/4K^F35;I?Y#U3>' +M,D+O>TWT0Q8RAKTNVAU3^4;V$`Q7KFB2'Z+@1KBBJ!$=V7P".^W6TT$"E=S$`0C/ +M"N@#N+>;X#H:2'U\E'`SIK*G/Y"1O0702ZQ3'^/6%N6&--XVB!U'0VW(GNG,>]03E7%BX[$D[C>K6;V0`8[]-/;1E\>8J7 +MMC3],B16TH@Z_Z7S;M,JO6*E\&QLG-DIVR2*P%LFF$YD6!#"*&T28X_A9-/Z +M>,?3D!=X6_2V5M;))QBHCH/L2M=[CIT9C=A-D\0[H@Y3D*9:*RR\(+C/P246 +MI11/O-A9GRC);PSC`?.L0[R/\)7UU7^EV2+AD,+-;&&:$V[F1BBB3U.8&=QE +M\B-DP2H^^X'"D%"7LQT.W/@\1G9@PL<;6`K>ED'](,RV)I%0JL"_-7(.9A8B +M(J:/HNVTUSC16L^?96]KRB#$Y1]V7_+EB_7RNWYFVO;WM'W9A67K;(*P$_4' +MNP_7]%"4#V4X3S[!`G!SRQ\2N4=&+.99%)]X5=&WFAU]\[^0!D.GW"@VJ9G\ +MN]!<:.E42MT3RQU(.);VOA&6*6SYS(L,!^G]58'Y)8%[6A5?Q6S&U"F>]K'G +M,\/A%CH**<=BG!@?Y5VWOU#)+HVRDI>+;U_HD!SI?L@EMZZT%Z^#HBW?VJQZCT_UX,=8:87G +M.)SZ1?/=3#$S9P6Q$@12,2(AOQI\P +MI>:I+MOAY]*#;ZV>99WZLO%<\^!S;+DR1$@!.$ONQP:R>]Y_FWL5C`57]`;S +M=16&H8$[X.G"*/"W0XRLO@;X[&(X/9\K#6+*_BA>H7Z:HX'?XBO=U2?+HYP=F6\M@RRVL8W97SB +M<(FE.N^)9!.8W>?\2=J4;2=&Q!+;'$M'Y\-"2!QJ;[+OVX<\W0'RY485)!O4 +MY)DV6>MH_$$4XEFPCJV$M_NF$2(YT7XEN1Z!`U.+)J2&M&D=<;'AYL+#["/W +M];-V?\N/Z"VN4+_=U\H*.=2/_]+B==O1CSLJV.%TJYE'>#D3/SM6^W)QI- +M5O)+M^,("1X:F!*%L=O7]3[A=+U1>]6H?6)ARJIEU;>KM$%-8N]A+I;S`4F +M0TKRD91\$6XI)4<-P(A#?F#6QT]SN7E8SB)%&'Q6V$(+XE&*[E#[E[4)HD?2 +MV`3PN2KY'!%9N)?L.DT9HF0+XZ!"$M4@N9_=^:K]V>=7LK'VEDQ,9D6+-V28 +MM2S7X#::CKH1JZA:SBH<&VCE,_#D#J7_[Z8JZG]S9BJ-(C>MTA@_R0N0\?Q67-_<,KL_ +MNY9$H(2>(NN,JF?K?QPVH(U2JA8A3;$#OZRJF5PFY5(ASD7LR/A6^BV_$':. +M>U6<:3W6[K\]3,,TZE@GSOCO96G**FQDR(YQ%/+@=6OP/OLWHVZO:!SKR?H# +M,30E>//9$.P@`B@%C]UW.L_P#RWC'8R9E(?AY["^OF!CKR>])6G-G.'9HPJ@ +M&S5O#1+RH"'#"D1#I$>V;'!F)T1"`Z6+XQ@FUQ"X#*`PR,+U3H0\D8]"Z76Z +MDHUS<%Z5C&B$O3&A0/2F*>\SJV]!T-=?@0&V@UTVW!MG7O8*0;\M6A^/C\9[ +M6=*P_3NZP66QI]OIN&JQ!$RVQNMNIPY&_K(2?NE(S,.@A`\K#9^3D@P+)&)U8N2&2!AK77<:":P\K@^@0B+AN5T.['RZI_,J,V`(46]KWHD/092D-^EK:XRH=/;4V?@;_O_6."1`Q.5(]UJ +M[T,.W\#?#9A<`_?0R;2,%4_`#7P8R]@6,=1$0S^+!FGMEF<5N50&"(Y(\Z%NMF"U3[HG'B1JN%>`H-!X8R,X,]N%[:/_OC*W] +MU+/R./6X62@7;Z9_0)R+CI*=QDOVZUH\AOFJ-3XW1<,TL!U>W02'-K6`@IB& +M%>:F-4*1"20MN0X<_="Q-EDDMK7$T]*S]YQC2)6V46`.L0N[A(U7?>0@&SN. +MYJ&[^MS!?]$A&EP+`6;2Z"GO_:N+$\!]?H#5'M&0>Q/A']'P>]:I`&R#JQ## +M*7&2V*_P\4X1W!F`;R0'G$7^*"W_X#7"Y*OYTQ=D>9;O*5HR_=;/IDYC,>TL +MPGFWNKKZ$^$*=X#VE']OE%VHBX7\:/ +ME\`_86GCR/@_'L?!!ODO[7?^NB60LXNSPUC;;P#^^*[51`"8Y.V@Z3[IV\?- +M1A!VYJ$#'D[>J[?"!O_&W6,(BC%C[QL]U:K1.EJN,E3>?@X-P-L)DT'A"5T! +M+6;U'C*_(E=/]T%G>??FY=$<1EBG\H-7;#0K"#M`G3BRVAR&*>=4F!X](F8&`6F7YZS15&8C_R@.M8 +M](^AS^;TD5)BGI:PC,5!D-!8H4M%>L-8\;8PT+QN"$XY3:?TJLMR+KOX)LA4 +M[U[IQFM,_+HPN3E^(*IC/FR8#7F&,@R_<.?DPBNB27?UE*-(#,\L:(N4R#`= +M-).[]]),\L:4%TO*JQE]_`"X(EU.OVKVB:+'W?`GE6_1]6RP0#3$B+;X/%2& +M(EQG`4"9*IB"A'5R)C^:66:`;J>3FZKN4Y9-^G4^2:UMC*"*-(5_M)OGE'&& +MDD?XD0U[35-9WQ)R0(:]&?**4^4WOU/K[6V=^,'+(79XPAA)7YJ@(Y:CO!XO +MOK`UG*_O<`2'C1,3819.Y[BXVD7+_)7`MY4N\>WWBIVK97Q,D:`=1(^QVH1\ +M`KS1'&][XLAOI(MW^;R:CG.%G9M2]H-XI*WX(7]>3ZMSUHX\'O;7 +M=VMW'4[JW`OABEZ7?D'[2O/!IIW05LX\RH4LMTT9"1::NQ<4;\&@(CHQQ3HX +M#C>OWHXR%B>U9Q;R!F'SC="3A[+5[=S:'RX*@'EVQI&KMM/26\[1 +MXWG1M6DXG%,KF=4+$IIW5+6^[I,W.G]??0")72DMM:2VP`1LO +M_\X#]6=AFP_/TH_G62>=FH5*)Z<#?X4&D^75$MN582L0_[F0!B'Y'=7=5\4Z +MGP^Y_L-NZGGZW+98'U("UR2`%5'3YS]"-9-DGI\#D;>,L-6HSPFRX6?_9W[M +MZBJH@TWBPO3F!R5KJ<3A$7G-0[@0@?0\-AQ3HK@04J]H5H$^HVZ>AFK*N&.= +MDQ.W)L[D\;I6[4>$R-,&X:.^K1D6H0002T1@;RG7C!^*]DY^Q3;V5$5+!%7] +MMG11,_+R!?3BT$(:[5"V5`,-[V%&O]?5YH91UHREI@&':EM6,D?&"J_J*7GX +MU9M(AASEW![5CBMXXPL$AD0G$6H#ZTYB>@:!/4]B6DS57-=Z`&A$?-JC+S_D +MI^5]#FN4J@CQQ.5,[6B#SV#]/#2T:^%B$0.X.!3KM8C)9.Q6CUF@=TCA'$=D +M<$/`U@F&XKPV34QL#ZTS9$:.X@PNJJ0YPIDDY^RT)J4,`TCO&G2 +M(I*Z,Y7"FJ@'A(SP'BD3()9'KE,B:>TQ\H6^4^$9D`\J2QC%F97+0"QF;6S$ +M;-4&C`5ZHD->L5Q_?-'=\^Y7Q;+FH6*T7&`X0@Y3'IO +M_;`#-"9%\06Z%G=F]EH+/N\SC\JIOMI%S9,PMV35&KT!WX,'=^ +M^^:2KELMO.9[%JWRCU@(#IOQ8K!<:'Z\FGAJ< +M3T3HS]`$?_GTC0>!V[EG'EG5#HMO10H*3P:50T6<+*%-Z#`F);21 +M6:\;.Q77IC'!2YZ9%$'VGB\2B@&_E&JHT,+V]E8&0R(NPVF-()3K,WD0`_%=^7%/FO=I#?-L'?B/]+QRXFG*ITLQ#-" +M-UV7YYKB`*S,\GY#Z+;B!>+9O@*C"R?0/IO(:EF*0VXGO_[1*MS;U@F#8+TY +M06>N$--UKZ"Y:MF*3^L!!'LOBYFFO+O'_4]M0)%H3::HDM[JJ5;XD0?]\Q4H +M?3_@9O!X)]$5S4^L<-H_%85I6&^^HW$[)?O!1OTRP2*7:=RBF'A>/$4WZR7T +M2`E=,6H3S#P)"@0VAOK.]9QZ(SB)CX/_HAE(\DXTRA"7TCXPM\*%,=%@U/^=,K`1VK).G5FM#XD0IN$IE*/Z(S-P)O98:Y\&\6'/OI54,7 +MHN*9`P3*I(Y= +MH&C2`0C'NQ/V%O@I'_'UCYQXZLPPW6J,0TFK&7#Q$0`JE!?0)H/'X=6FL.', +M;XIJ:2/O0AT8VUL@H2/%-)!_E:IOK*:EEH"-S"X)UO2ANK%:=\GYWX<45RY> +M.(T-<7)@AK:=5DES`5]][XQ4UM)#R#U9%XB.Q=[",%[!Y2@)=!47?INPOYY(W1HL.\Y@UUM2P= +M;&ZJ\@U:CXA,?Z_NC9N(F^[#PM%^4F[H=OR@=ZJ7V^&8';7/)N'R8N*Y,B)BNA`Q3,DHX3BV-]=4W9[M`8?=`%8(Z%<Q!9Z]M`X@K#?L%@_Q=5:9/7"CM6_]>GO@>K9T^$[CPB:(1QQS +M^"L1F1!IVE`S+LK(I@4?GKV0GXT*><6_AH$@?_.D!(BPMXWF\O)(GO@W0UO! +M6F@5\%NFY^KSS@Z@B4IK)N!`!CNNV(S_$I,>182FV13DN?$UO%P?!&6%\H@; +M*_RR>X]CH"45PWOG*)KF=KRY([S7-/A>2<.%$>^4MW3E>,I-G3=&(0A@ELD`<_1V^FVG'JG?I"B.TE2H-6&;V0MF; +MHG%OG+"OX7S?,@E=I5,XEN25[F?!$?B*'``Q/0 +M4PS!/;[Z.;)^N)!Y.;+L"G$#F_SSA\*`2IFIY((<[5L;*6TPOLUAR^V`$!@@ +MU.J;L0FU4JG_S)72M_F9^O`K>2I\/R`T!-PVYJ'\6HVXD*(RHE6VT;<6._]U!"`6M<;I,=:KY7T@]N`D,O91#@]P=G91'>@`&KH*$GW +M]AF?QCXD_&,^L+PD89.]=\;R_Z64?PF2,U<_3@P(XB$7IQODA(;&[9_"C%%E +M+EDF*#0F(AO7XF$FP-@TX@^0-!,;[-U/#FUW#`I0LSN++U:D!1=8396.X*T6 +M]U!_]*H`X(<@YRH*QH/@H)YQN\+0[YPEZQ><3M$V +M&891]`F/US=/ADGU7OO]C4^KN`AM0?FMWF-[DS#)![TB;@-Q)<)-O>N&/(^_ +M&&ET4CI27?CBT.7$``\Z`F,:\!N7DPKH$^7J?[*&%[I-6-_@O>[_@),+`:A: +M4NE%<(R_TAM]1;.`W.Z)-?+SCGB;+8U'2%Q?HF@#JA58*I=@Z +MM$RK=`?W?>\;)SQ?XXL3-&WS%071AK8=9S,SKOK?^TD60^@_&N3T-N+#6QRIZ7ZW*[U+,=2NYD+_G(\Q3DHQ]\I4L +M1H!I!RQAQ<9#^:E"_+:ME,.L^H2'-UNU]9CX)@LCB-F_Z2&<_:\-U%'O?N_9 +M6E8J+@7G&&CK,!X[3?=OH?$1+ODE'DJZ#P`3/*X16*TPH<]:\(DA0/R.\5PD +MKK[8G./.C%$XGU`@+A8BN,_4)GDF09[ZN\5X%0;X0,GH1@RY;=^/; +M=:Q*H%>\^TG:.GZ;>=RK))Y_:&[]$@M3!NDR6N>SY8"=0=M\QV:%".V5KD3$ +MCS&+?\?`6"W?1.5O):BF5#F^HD>][M4+E#UW,9%7\&\0[2,@.H;<>"H!&.IXH(,MR31^U4:XL&B.DAC+E2X6;!<=_8QE>IMX\.4^D:T_"K.CP#00(\L0+P2`N/@ +MI-%>@MKRMFL?M_G2`[K57@S,7,>C+9K]RJ?+?HQ?5]@)AOQL@T&ZG[/--VK- +MWGNNMZRB_&>3^27J@?+?27OZ;V<'K3+K'!5CUD`NK42494Q!T# +MHGM5?7/"K9P+!M^64).+1\_63)$&D +MA``\,"SIN,K+_>'6J!B0F=EA%?9E79>K(2%5WF701V[>6FC)=8&3-)3+N7_VVJX-I%BNW!,DM +M)N>5P<1^J7IO&/AO!GM(%,&QRSEJ'`+^^3: +MC#50*DP-0YG-ZMH/5>YSO>Y@3UYU(AU%'*;S1A;OIKM1&(6C99%&*!IH3=90 +M1=27S*$G.DC`:&BOY!U +M_\-+!:,%F@@26Q>FYO$%[.YP8;YV>F1O&RNKLW9A?ESW$'<(PP)/^/LU'#'D +MTI6.<=_X52*3IHD%J.,@T4%#O"]RS3E95>"MNMV87("4*GBM9+5X[P9T;(#4 +M"1HEB_[P(ZY(H]3=#NQ%,F>\HCD(;!TEK3>;02)A9;YL]9/OF<^V%%<`']!- +M>+U0-J300&W)@]^/8 +MA@ALG9]RP^1R/=532H1WPU['\;;4H^5#*SPGZJ$$0(X/$_[3J6>&KFH+)7G`GX&65._(TR@AS^^L= +M.CV=8Q6%LJB9A_PG];6HXCLJ9!MW\ +M/+VZYJ]#X+ML/@JG7=S)T2@O7R;D+&Y@6TJ`9>J>_FAK,N_^M5.>?YE_9VMS +M"VQI]^?;9,D2H_566X,TP*A]43?;2GZ[:)W[=&*#=1H6>R>D"_"6A_V:_"DY +M/Q_&IRPNCRW'L$WN&0T!``NB1@;'"$L00U@OZ[>^))J\C!!?'/`B"DBD;46, +M;1(_40$I&6H&EQ;H5TUWLDPIE.L/PO7)T-S)ZS];SM*,.:%:I0%+E"MD`8.X +M\@^`(,$7S?'^;4'M9Y2^-3E4Q!-<"&?5(;C<KW`U5%LP@Q=!MK +M3@$#`Y!&S\3U>=*-.S\X2&"+D1ZX=V@S_)JF-U]G+IK2(,Y=_.<+H\O@@M.A +M5;R:LJ&IE'R]XFS<`-[VKWQZS5'?I9,U5BJBA,KAT6WDQ_5''CTS08%[E@0; +MX_`+8O^A`A01/V1A_M\<#"-798:/"$:WV_RF$_[&7CJDMTL#7/'=X\`I^3\IJ%BP;C")9G +MTMGE`)A%\VBVE%8O6",J$($<-<9Y+A+UL5XIP8B9EF&^66K; +MCX4WN2LVVQGU?+%D0!8,E_;DV`HE02%RXJ-Y+&XB8@Z +MN`F,2#6,$W03H"G`TP9[DY'T-]`C]':JVP'MT>X@I7V;'U\9(A=#*VB_%[DK +MZP8FF+SO(#.Z.`*&*;HKH59CC9C8@5$^+AC65^0K>?'4K'?L]`7;[-642(^\T=BOQZ=,D4^5$N.P>,,SZFW9 +MA/$9-+KEC!:/KL8/6;P/#5!%`FUH[&A6'2;?T_7,W(FOH0*K2)', +M"1GG#/[?8Y%0'>15M:I'BRCL(:F+1]./SO0ZK:;C^([JK]XXZ +MSS14Z%B#F9!C[_!N-:'#PMGRPL+D%B;5(7@X8A+!JQVDVTD[@N1<+/7>D:6F +MW_6P3FI32CQ"""3%3X\A'4QAQ%,T[4*O]E?0-?]"I"J,$[_DH!&V=/MI-"UEM78,U00=IB6K<*EXT +M`RM2OCCJ*?);/^$,:7AST?S/$[:L>2E-67@[UYW9,,R7"5?F_4LA*,-%P%X/DBQL>ZOV"@XJ1%"&)P06;N9& +MY]Y(6-S<5D_&005R*1B*TH/Q<0/\T +MRV:EX&F2,56RHHKVD311.T([V@H;06@VEWQ%\%O!/8]&]`=W.U#(MZOB`8Z: +MS!WXTC?8A_0<799BO[9O[,`16G0Q68OXL@@'TC\CF460<`(`IZX\HE1E<\!" +M(T2!/K"ZK6HI6"]8_[;/(]D7LVRR[Q'3J3YJQ?954PZ`F`6!PEW'H\-^C3M, +M\:+7?BWVPUZ.P`H<5M,L(7P@/$JYK#-3O)`T1(8'<_+C^.X6]JD@D[?E(1M1$NGN"MYVRF_;_=4+D4/B4>A^&/G*"?U?VB#JDZYDQOEYB1@LWK">I`<=11]-N7IL)C2J!N( +M1MZ,++,CQ$A.L>^3.5H1P#/2"X0EE7$L=VB2;ZV@>WBF%*NG@XS+I``Q;WXB +M`!`C(@'^K2$"\['>XO>;\(32M3B,E;RT,?$:'\2\M0H]YJNGCNS?<#FD<(FC +M$X"G1D@[Y@A->:1,]4E'SA/+KL/+NW*^`T8PG@@4XTXA\]`+D@*UD8O2^QNY +MY^:'8PT4@]CY?#I@U"!.&MH[E*&UXZ>056UORL$,Z8U'7[1[1>KRB@!'SNKIJVX`:: +M-PUS[;6Q_8'R+0"K,8D7FF8*4MH#.4N:,'C/8GLZ)RUCTZ_^^/\S>EV>P&N>X +MC.ASXYX8+IE$UI>KS7W]J$\#U#YUJ%9-R%:I\XO/;"X\=YGG%33*"6>T"-LI +M,631^"?#JI`@+ +M])B."B>U!GU0`DJGF12D.@7"8XA%3K\O5K(W%)S7C0RG:A42;=-!DA,XP^^' +MYE0ST2$4ODP02(E@"RO/#V"DR,ND88LBU-^FQMH$Q=:Z>W*(LL[K"RO[1HE] +M\&9BY:(=5G,D*.$&$7T[6<&''M4W!,!X9+[W4.<*5)(*%H%E`;5RW[;Q_CV7 +MSXT5(8J7A`3UGYCE@T8U&;>,>C!>XV^7?#*F=;77-JUSNG2-@B*A@5..Z5PJ`AZ%S' +MI\T(%Q,0[VZ#A)=<*TT@I_*V5_U`MLH*UY(^W1[`S0"#F3;KHS%E_JTBO\G>B+ESZ;&:0-W +M^W(LUI\\7K'0SQ14EB0-L*\1)VF'F?/@KKN"VR+^RG"CB8Y<.*A(4<3#J#\W +M"<(36.A%";@0FW?L'H&+M68_NE4\)'T&5*]<$I9@$&F!V<1PM:$-$$Q".RS> +M06L$JC1PPS-2D12T+G[$"[B8EK>B'1ZK<@#/-AAGF5HRK7?WL61$,1,FGQ#! +M,"H/_I/J@P>7(TO=HYZOWI_E?3(HZV.-7`.D=RGRFQ+0G2H,CUVL('(!?2W4 +MC6]$K9BD+BH<07-&,FU?Q[>9E=IQ]AA/U^P"]?<!6]T+K3T[I)W0``6!X^9-\&T9()'A7JP+[N +M1`3%89QM*@,N;4"F1MC?E*D#+._G;6B`29V&/%`C^=D/3!_AAWE/T]JE +M$6$W(XI>#1^QU2$%G$`961-JNF +M8"&XL%_YM!A:Q.IAM4"\_&"PL>*=$[H%ZY=?'1XL&3[*@ZGUR!J1(%7<$%,'W +MN@=!J!GGS0N,*EZ5YH63T#):K!"Y(+3?!53$RV?\+H2^*ZGE2TAE\Z:X0CL8 +M,4NMF.Z;*S0&T1+K+D5#/Q`CO++*?T0;]M$+5:?F*[MN*\@ +M"`],:7IG2OF'2`P0Z%@[@4*GVP'^L>_J]OKI +MB622M;RZX&_A7OXHB"S*0?Z&1>#2)76Z=X5C'9`\1GM*'O;1#-%,7 +M=@W6/F>YPQ9+CWAAZ5U#[T)1T^.(])@'5<7&@GVP?2I'FO!56/M1I++?!C96/^97::DUG*>-/UC;B(N'].A@_!IV5#5MZ +MCI6WTB#F8T&7BH--9&K%IQ@+\K$_T`ZTG#OCHQ<;-```*YHC<+@!EPD_?N8_ +MJ`O2\D9#+9+Y?Z'1])JE(66S!G7A;7.6U*_5+^WM^B7:^_6,E$SX*7[5M*'#J +MY6W@"$E`DUEPO^;'ORM)XB'SZQQ-JE$02_Z5V!GQCC28(J>+Z!O,L>GSY*4:$Q%3\S5773'"R?3W@N'/=$7RSD +M!:<-^V70TVL#:LR<@[+UNQ\YB4+6/RQ=F5'AM^,1C*W11;6EZ8JXMM*0_WC" +M,FBGE@-ZDXG.WM40;'N+#6\CMSA-%K4NU^>6M,DXV#!/#"P*3GS$ +M3#'MY=LMI[DQDCSZAWP;^3]894&(49L8;[B']*LP-,CSXKHLSUQ-LPNGFVY& +M:<:::A5"N#`E.@"!)-U]MOXXX&PD2N)6X>E(D92LG="<':P9_]*8%+7V0ND2 +M%8_TCY%P@-*O<2K*=*RX^141+EF'67L='>.1^^Z6.SX1%AUB,>GFW>&/K/06 +M*U1ZN<0KLVCV$V;.O5P'_T*[YB8C6\GQZD>0B[C04C^JBRA_8=FQ=D0T81[X +MIV;,TL1M(Z9](UQ3MNX(A]1&`0(NVR)>70\54[8N/]W!M +M0(I!9NZ)C7]ULFV_W44%"32'43P!(_BRLS8UGLF[C.<#>@KFK9J7^0XFJRC_ +M0;F;^0#\0DNFQ/:]&Y,V_9C0T;9"6M`)37QW=27M2W9"Y7?GF1#I$$1V,,(N +MNFP120FM6AUA8>\:*F8(4XU2$T5T)!(71E0.L3!F;%^;:8V4Q02-J%5-4DNU +MI>O=>"`U_?$I:L3OIB,^C$&%68TY<-Z?X98GJ)%*NH?SS35[[\8=[#1L+!-; +M9EEK7HT[(O^@PO]_/.'E8A#.<&L8.P] +M#C79-'2:/1>\O$%N)?['/F5_BFCW<$6\SDE=IINI.(NNB_S%>^'L5[_@!E=7 +M-6W&G*CH60ZP!!7"O"WC5"Y?);F#"!5)JYF:6LJ):T_@G7HZL2`>!!2];4FV +M.C@Z.WSOE0C\/(FKL>99'DOW#SY4Q#&4)`!L[C7NLW-\L&3[(->J9I,-R%/K +MI0_SXN?K&5$4RSQ=[]2U(D.XY[0^LXD75Z&+S!ZD!/!"?^E6@"WRIN#3:28: +M,?Z5UXU^>Q?3MJ$V"3Z!@!`$1JQ+/76%5X[HG1YF7#2.E2C"T2?PML7Q'['2 +M)(46H6[H51F6(I6U"%FST?;9E32Z>#\\"N8-N +MA#[/SA]J1*624@W.>4N28O+WIMW@=@.J2$W-/H1QZ:1>[":'(9+]77DHZP/W +M?XC67&,#/8?J2/V4(CO&1L.F#C/C>)8,.:^;O;RB&1E&[::Q(Y[7^TLH(;4' +M`9N>396!I&'0VKIU@>^Y_S8ID_CGQU)$%SD8@QT'TJVR;\7BO-J&$S5J`Y#; +M3R#7"?YS?W;0W']O?!;_KQA#="Q"P1DZ,*?UTL=:'F`!T8 +ME>.*[RZ%M*7]E`HMN?1_C'_>;1\'AGPKP!.+:!F,.F9J1EQVVF#]^.=$G!FY +MHW1O'U+^JFD:%G.&L+:?&FI1B5*A0##-T[B.G*@WP:LJ72VA`F3#$T +M:/%?2S<$-!L="*KTH@5T\K2;.-&J^EGA25RDHA4K$.="SG#&\E[DOC".YSA( +M\DI7L,??T=\C)5R'X6MB0L+L_/>87"YWO5BR)^$47%T>R\4C'17*P!>C +M^^9LJY;O@+,04XV(3L@4,\6N]B07Z]% +MIK;R--(:Z^TGXZ/6!@'BWZ$K<]"L+(ROR?]-LG\*]XB:#G@9F/6(ITBIYA"G +M85($OS*=;^XGX.S299*Q2[$_UA*_:U_X)Q5OYCP`1Y>?*45-H$'LKX^77)4K>$!* +MH,7)>"^5`GH';J?Y%H:H7=O;T(RBO&:<2<]I(V6IVZHTLSBPA1^X[5^J3,<3 +MRIPL6:.?`116-$!"$7(+HBBTCXKB`4R#.K*ZTP/CP"LB&1_3=?U67:MAHD,E +M/-R6<(114M7W,>=9-;?$Q6AW6"2`,V) +M0>]KVQ[(%E$]TAXK<[COASA05%V,X1K7A#4:O:OK0I?JY67E#1L-F,"J]JG+ +MGPK0B4B4J5.D,1$&NXYLJ'VEE@51NY*+'0[()HP,ZFN5:$9-TU-&4<+?E#R%E>2>!DI[*#J:,/R/RT_^Q.Y/?VB,LYZ+M5&D"BO%4:NHCD>*'S;LSK>4P*I`?+[I+ENXIDS7"VT4I7T.7_98VZ!&*8U;E$Y# +M@\F'8]4NKGB(K7#U+7O1!*@77&Y[B.TQ"A#;B,+.8%U@Z@?-U$?D>R\D5X-@ +M3ZB%0A&H\O0C/9\1#1#EO@N/ZU\4ZW1Q#O&%N1YAQTITUQ<\;ULXKD^&CUO- +MW%<$Y>Q&"=,KREBN@JF![H;J$C87!%!_A/J.2R#1R?LJ;9ITHU7L3MH>@@WF +MTE2I8NUX@1K?_IW:$J3ADVS*2\TS^BF+G):L%W>46M!^B:]&, +M1"IB)*BF7,XX@K:[#6U*1#8UH$+K\&7A3F`=N'&L!U\L\QR0G3MPC!7'_//K +M]*'M:;KYIGUV6N]OM*:1.H!;:AGYGB`/TM0ASYM.WWAB!W4+Y\/:<+J?%=^<8>/#KG.I03O +MU:=C\D__6^9S=#'T.!!SA!CYF\&&$U[O-[XB+<_*W2B7NYBFR+J,AF\BK%I8QMR8*'LNH#_1#B!^,^_R'PTX?;3J81BI%(&5 +M&+QN3,O;?IN)H)G3"][V^M,=>6=@`XLU)C-EQ*%(NH!UW$))P^5@JOQY(`QY +M?42;;J1EH,JI;4,$U63FY=GB87I@9>@T5G-.#09!\R;9T9$<\J/7EFD+!2S: +M2DD%?4L<.7^,:!YU'&:D))$A0_`*W]VMD;\+2&'H37Q-&$P-T/E=Y.O7Q>J$N9FS`:9OY>2\4IX-"9CDX09?%CR9D +M]E_?^[RIYRZ1LE_.&N-UQ[&'%628`Z@]-0#HT23,&+O46(CM(9RA9B?$':?2 +M(4K6#<>Z=_`E\:R\_6?&"$B71-\.5G@*R7N0S]0Q'L-8MF"O1JWZ[A;SL\U) +M@*TW#?>A7HW#MZIZ*+[3#'PXF\1+\_2U86L^7KS";)M]L(-_"RT;@F!2/^BW +M8-%[8]O?5%U-IF$6;?]ADL'^;WQMQ?7X4F4(17A6"`_C3>I5=9DBYMQ``:.9 +MH:)YQ=W]CM4-5@H]\_,H('.!,X,V3CTIP.W0AC6"`^8?'A&[-@CQ#?#@;=SSN';1*_'&8U>+&NQ9+)9H!9=P/Y[W+=H6`5+YM- +MNW2:V4FJLC97P`75.S;V@1A)G8VFM(W0"CVQN4`1*8-R.-2ER)F&OB:_S2@UW!Y>;^7(:M)Z=XR_TMN[TB\ +M%'(E/HNMD'"3_IMXW5/YWP7L*B_K)Y?RJN!1;3/],$N*A)-4->NT8?GCC?J6 +M:N(_#)4(;VT;8&P;OT&8'!4Z8[MG%1,/:YO!SX(_L/B2)RVM]KK=U#$'&BMG +M4&QY6K\?WMPM2::C33@H+DBJ?7JL"/@[ZH@\&]./JQ+8"L1MM"!%0WG$VTVR +MC3W*J6@MH;>U0K\Y9PLG'AVE>A*CG-=9@I3_%<8NYQ9DP6;9J7F^C30W=O>. +M:>!)?![]V#\3(VL,3G,Z&[:BE?%:M:'64X/M +MD)GK71#]@X?.U%#)AB!-3E5"7?<^.I>-98)RM;'2L$%Z#B<"6>>CV"1%*^+5 +MMC.3\A?62^O1E^D(K<#](;[FIQFLR=+8/I`95MA0RN98/Q58T)^\2,2-Q@`^V`,<;6-V9+1R87E;EDMT+CYWQU=].)K^7X-"3< +M;KKC2JKQC:&2,M3<H(S"-7\`- +MAHVO&Z0-QDR?$8Q9Z'ZZS&18`",N/>CYK,Q,,U3F/T,8*B2H4V:O%K'LX4`K +M^'3;.1X@`9Q#HTK)^$U<@?)%G7[\75.0X>^;H8&N)OL.OEE/%(%KG<+S7HB3 +M3`>7!',P[(G(P3?/E@G0BA6:@:)>Z"[[9;7A"@^_G"+HJ?%<#:D,JI$HUX;H +MU1.-[/U2[X^>QG!=U.-UIFDZJ7XVQA;PDV3)B@#5PXM!5E3MR-5>H#U+,K3_T0(+5ZZ:*Y,$^@<72%\3Q=>C8 +MG[T<)BBW7B%Q\XL.OO4,NE2%NZ)_VLHPE)0?R>I/+6%/K!K'N1&%/6H$IMK6JQ);+SJ,YZ$J))I-CRN@`./ +M;'FCW#>4=*>.)(4NF8&(%H)+BUX4*BA?RNGA7O"05E*NP:#9X(VU&8KU+[_8 +MLIYE)T%];Y-`#OS[+Z&!@\!>A=Z^21*>]A4V[;Z9Z:_O'T&^!2[D?7N^!9/_NNWCS[W%Y= +M*K[3O:1KEP` +MX?,5HP4RSD2THK?D$'$:LJ?Y%Z;(&Y`M8^<%PKA$P!,PL1O;M1)*FPUZ:61R +M3$0BRD9(I!_.JH^PLQ35AJ*N+C[WX" +M>\06FJ\B]%BJIWF"X&%-1JH)[P(FJ,1?@1,$N'FOG.83F[<2ZCRR$\C +M!%S9%5RM5 +M.#L9`XG,P/!Y$2?#G9L9OI"#>0F$R!_>9%^%_$$D9:IOR2,U]-'HP/!W96GT +M3MTRG3=5X4?R5:H?P^?Q3"\P#(==C%"\Q952?3''LYP<$8EN&$*G,QR0.S;? +M4O5LARHZ9%[BH4:Z&2C?5;$N=%%SPOA2?B3H.$OO$2([[W*T#:_#GUQ/?OY! +MEO+F@\SL:+M_^I1:*%;)G3!XLWT/_K*I>]W^ZQ`2AFEP +M(6MNR2'4?^XF]"0MHY2\_QZ4T2:3LL5C.#KQ/$`GR%>\'<5^KL6RI4?MVJ/+ +MZXY"!=O[_NLQ#-X2A:'X'`NL\Q#7-D,)@9=8_9:RHIL<..I1J9^W`4F%%I10 +M[3T+(<*9.A6`ZK8'!QM\QZ:B,U8R68]@XB-&CO^'BI3".!AFA0`VD\F%V2"X*%1TJ@E[7P>:?"TUIB +M1##S95!N7C7K2($LNPH].;'E9#:XOU602-$USMP$G?")7Y$"SQ5'S!E\KWI6 +M<$--YQ$,&UD,Y3K??K!;U(U).)GTF9(H-/]E!PB%Q.?G +MDXUH<^,)DJ.!N6Z6AG1IL>!5]T-N;H*"BD7`MU7%N)%C=M?,V!\C`->AK/.9 +M_+F>!%6U)8\711I]*C_L\.>0(%1;[B!G>ZSTEA_@%B>^@<_8 +M4LTRZ".ANN,N1YOY1!*\AD?CCW21-9:Z3RLF9G,:9[M,,CX?3C@-P?TL$?FK +MKFV07UWNC;E49V^OST"*K@Q2P<^=!"J'A0)@!\G_YACJ/H@![+@1L56I15#Q +MX)"7.1\O#]/%(O\N@_#`!=Q^[FH(7TL\[U"T..L>6-LN\J>_N/A"[.Q?)TMUD8NC8)D6X/11]QXBW'@ +ME%?!7`,$+38"?VGW%()Q:GJ043M&\>OU$P1OE]&*H0B.X;K%L/A](+T;93"P +M1&U5KC_[+E<&H425IA%9]"7/@$%*.RMB#[7650E+Y@1S$$@MY7,9X=8V\QZ$ +M+&3:YPV""(LPQR;#G%]E>-5$/:$[0_WL*5R3&!R?4Z01KM="FN?245E_IUHNQ +MM1"P`P]0X.K/F:MG#9<<`.??]AKG"F&&O7E]:^E482F0A<-,![-H3>:7J74N +M;#GS#ZV-:;-YGOKU8X%=#,@]KG6399V:@X`<0QZ]N,[_=_0"X[]8)V+[8@PEA0SH4%:4@72HK);:T1Z_AXI=%)\DIIA=W`0(0GH +M_O9*NN:*N$F58M`FB+OY1ZAY7U!48W&HP\.GD:@MOS,+05NS^="&8>3>M=^' +M0*M#HFAWK^"%G'I->/UC"V:B=V09O(CM,BQDZ-DB&$HQ#%HU[6=1^E@B'Z&9 +MYMJ+5D?\=5QH+9&B<,I#0;2S,E@DB*S3-/<63M7+-(/J^6D\(> +MNN^/(P#/<97E?TLP/XDG1I6K(B/^C7@92?4T&=+?Y#_5)#YP8+M"X_:?':B_ +MNL'E*M&>0$#X*I!HEG-%'MQ;^>"#U( +M4S9IGFH`A7N`;JD318^+-^9>3YG3/GJ4*K<[3IJ&"?VNI!'N2T#MNS:\MY+8 +MVL'B),G0*.3.;+9V;_(GE,RA%$,LP-M[[WAB$1<4)XT'EE5M1,IO#5V7A0R* +MXH`0,*:_-4#"(H!))ABU4C5+,'T>`TL^*^]X_A#AR(?DPK6&0MW/&G;+80'' +MKF<>L;6%D@JE5CZM?V:>M;M,TIWNVT]@4W<@UK;PML)U%73I\;J3-S&H;=). +MG[;"-7'"1(S!`SSWVI%&C2VBJ&G;;=/@DM`$;9]5B$2@3AE2G/SFS8/%HZ'P=+QJ4YGR2P5PJ**KD/I[G]XQ&6)/Y +M]F0E\0#(C1`)#79AB4.UD_2Z8%)5QQAL2MH4_9N0OP-EB`0L+$_$4R0\82I/Y($.F/*TG<:>__UK'3Y9]&M1LRIR+_5]@M&1`,\4)+ +MVR.]+.MWFQ'_WBL^4T7DAN<5E:SX"HPQ#Q&.-HC(P.[Z%5`&JOH^$N$@J9W2 +MD@%9OW[)I['MWO$D)!9(Q2C)389%/DVZSZOIV/VJYW.2Y^:@R9]TL(E)>%I,)+?SEK>3 +MCGQX9_YMX1R,_@>PD9%>(.O6AJ5P#W?[619[MKT!GAOBB*,3)67_56H-/IKH +MZQQ)P8UQSX(/"Y&#'%/&[/4^=#Q%M6O!J>1Q.+"1S6(G)?_R)/\&%H<8^'`O +M9:!Z"440CK;RZ($L,BYMM'Q_"3*9%JQGVU("<`Q/6&FM0@1!+U%K?(@R::*Y +M*BL0%M.U/KO=F_V;N5A+K'X +MWC[%AQ:^Q9OP&S!12,?H,@4JKK]T=W`=_7]P8V"D-^K_F`]?6F!X'VEZY?^Y +M#/]XX=>-8*>_P'A8VK6*+;&*_66<0C?+F6\U2OJ!OJQO<[()E!Q_&/:@R/++ +MYRW#M,,6OO1XCA2]#A1@TLW!I*HI)U? +M1W/E/;1Z6'G%.14EXG"6'':>R(XB<+)HM\JZ(3ZO,/\#8=I^%.>QC+)F*=7V +M*3-V2A#D%:L2O/VMHA8-/^+:JRM9]6B.%BF)--9J2D.F\I!4!DV$+]JG8>?E +MC8\%C3IY#3]V^@N(8S!Q.,E[!=0,<*I\3;FXZA`G)@Z#6<7)7G]KV.)?;7L3 +M/&_9IIW;PVC%9@E".N?4;]/G>)H(V*HD!X^9QGJ";"'`D@8&V+Z^@GA.PX-= +M/?9*-H7T:TG;3!E(P4NP:>4SC9G7-JM=N/<4XLZA^P'E?&\`TU$8/SW:!"[G +M(//`OWX,VWIM/H*,IW'+PD-T&[?_$FZ+H]B6=;'"Y32D\%':L\&3@H7=&@1; +M'-L5VNYQ#CP\C@_'=%$#:W+LI[[#':EX__M0V8MV5U#(?Y.:&-7J8C"%%1):>Y)A@B]3E[;N&MU8$HT[ +MAT/BX&*\E:=?B\?SFIW0&L_D=YF7*F8!^7CI,92%9L*`.GGV38E/K>CB,"GR +M9;C`+`\;,Z=&-8#U(*I^I5>*;)2<:8FL2)"CZM,YJX,FX!AV>I3(,L%5Q11* +MEB3]KT9/0[!A<4&->][>RSZ">WG_;H6"<#<)W&Z\,'4=BJ&1[,N), +M90]PDQ*1@Q$K9#"-;;J,1F._62!&[47)](JKE-JWM7$2SCF[`[[M&W<%D(/J +M28#7P5[UJDZZB:U\;]\)I#I@U(7(6T3&=5C52]YHV!*:B9RN,'I$%_@P,0AM +MY,T["B;SIRAI`DA-7`I)@:0LDHV&6V$A56QN&>-"%#N>46:$9SQU&Y68<#%R +MWJMA2'I#QT.8DXQ7MMY8]WL6JUT4T"!"%F<)ZT"R+*A33S0*O%/^5?1\VECN +M)C[_!?!B7*P).>0$=':[:1686A\#ZFR#KIB.WQP8%5E5\\>.I8A'O3.<75IY +M44A]U):=MCPZ3.P9L*<<,QSJ:?6C`,YX*4/_=*,H,#[H8D?PC`J=.]R,[$2; +M>/$!Z66,PC/2=))O+DB\'X**^-*B,%PC$WWQ+^(GEM,)O^\+QID3:9G^\DICN^8%-2IF53G95!T5`\MG[A$GVN +M9,X3^6G*N'=/(`/O +M%"%HZY\+IRDC.:)SA><0)#>0741\HEQZAXKCA/[$@%F7"=W:@FPOSD/=A`WQ +MUNEO03F.Q[U(I@J/"Y^\$F$X.2L1B)W.0;.#/'VRI+5N_D=R1\U_Q +MQD*!.1)<:Q*04;'B0XX-JKOZ!"#3T(8.RSJ]83`JS8"+1[F[V7R@4O_29A.C +MSDK#\'J-]_6OP8ETLCKKRT#(M=_](CV*`WR +M=LAM:]WPL4DQ0S\2@J*=07GAH!,@B6\*/GYT[$R^Y.W]8^_6'`R$G!8^]XN? +MHA*JJ?5>(D?K+?,RO^+2.`S[!W6N.?V1+'FS(DD^$NYV9ALI`J!R-.5?V,41X7)!XTDK5'"?EB1S8A7&__2!@,B&^EQ>1(H3R9!_ULZI+2=Z8( +MH[F^>!]OV^<+TP[/#830Q?U.4IMJ\JWLP<$$:-QOUKHN_,)C[R]ML%ZLQ_D@ +M>#5-NU*0(GS&;`?):Q +M?TT(';MMB<,D)JW"PUVG8+K5).8L=U[(MR9>V)G5<,W.$.?#2!A,5(NK\9:' +MUO]`>DJ%9U""\?H+_]MD34%C)[MR>:U-MT(HY!8&/.SD).O.?3HF)TC1"K7S +MG_-CX;&O)96C$3WY/-@SL7'A,3R&"/4/LER="IU\)$GGQW?B"&R\5%.T +M*(V=FI1\-[Z_+H-L;MAX)(K[.O_>77)-(F5R:P,F9_)'6^E%'7W*ETS^""/WRO6Y@#+H;#!98`ES3M0Q'9>T`<2`&=L;81`_W +M0[VE6."?0N9AW??!,D(SM793>MGBZUX94-*Q0J^+L/!4*^#?RJ.CY_\R&B3* +MB"!-_[5/NLI*L4!IO1N*(\TU6-R@K@?=$<02?N>EJ"*[7.9"07,NR'4'.`&P +MX7%K%-/]$=*HJB1(*%7%M7UCM=9*X1&(5[#G'OW054LXE9*V^$%R(3=^1=.7 +M[VAT'%HOK!4_S06C@(.ZL],^M7N\LOT:!5B,(^+*<%[[9CTY@R9JS[SZ_WM` +M3)WMB+1T?5!+`P04``$`8P",L`Y%NY!-AJL*``"B&@``!@`+`%)%041-10&9 +M!P`!`$%%`UT`UGEB'26CO7-XW(6S0R5R:M$?6P%#-4#49UR!$?1BQQ`9FV\X +MCF0\G*(?%H,W\[#G>3X15:CSR,4.&CV(Y.,@=B57*C31YOU;35RZPO@=VJ>F +M+=CP;,J`C*<-V5;Z_%;*S;GX7C!8-21U6XN)>$H`]AM/,.95<*LML_`5ML$B +MS'DX35/MU$:9_^6\#,2M>6&3TSB=IDNUPS$\A47+P'$1NCB!6WK'Z[U+0TV;',,`]V[&">#1F"`[&1(45YE`N) +M=W!@GMUBSMG8691$GIN=`,,5)RGUDNW!]([HS;TU4&DG2J2+".TG*PD"@Y\W +M%H$_,R7?-50SM)1H5#U+&-6CT$;KPT7UQ,_B7'$GZCY1YG,Q(([<5"#T<#3; +MO-'L$"8BM^3?TC$XRFK4X6)VB'NDGWTL^8A3CW/KC*9M([0?'I=L['OZ*[M+ +MK#-YZ.^).4R3Q0>P(.'0M-AJ@=KWBRIKB'OF=\BL>\Y(.EDAM9`"1/_P"']; +MDH-H&@'F\+4.I2N=,39MC8L'&XVHU$Q^*[9WX<9B^<^UZI+V2 +M(=`(^&*]=BI8"OEH"I;;&HI2^CK^%QF\Y(9VU,+S=B`P+8? +M\$D)_KO"S"589EO2NQ415] +M"4V%!AG)502-F"]H&V2?E4G:MBS6VAG8_[,9S[PY71%/ +M*?*>[FF?L?'B,>8L>CD%(O5D;BY[C42HLJ^F&3N./RH-R&6,LL\IR)H?9TZ[ +MD]9!KOU>#VTN1P'\IO?4Y^^WE)?Q&?<2/A?]Q+TN(A>`M0RM!.?#+_L>A62>% +MOR_%_72NHP8IOK(MZ8SO>BROJR`4IQZ`FY0J7X!-97M#,`/W9"A>XUQ9,8XR +M30QF(,)&C1_.JW`7+(L>H'>RX!(N?9-::%\V7]O&UT5"I^"\7SB_4;2`C)N/ +MZ<%N%W..;)UR"'=74_Z**TSF7W=I)A9LA(><5>$TXR)AB;1^T(1+%&\,I!?C +M6GF,64`PE=L=@?H8.$\\<">1Y,SHXS%6JU([U=1-,/H%$QK#?2>.5HP;NL+[ +MV=HYAE=^$0=5PMIVZ"/J>""0.^L(DGU$T[["CV[&CL-\+PO%#B(&+@X26H\W +MLNY`YH%P"R*EL_+4:RVGC/QE52%I!N47&@F$/@I?JQI.UB&I,FXKEA?4X@YCCMN$1V"G`5 +M[[U3$AI,8V2B(I!+,LT)NE/@23;/LCS^!T..SX;?`*?,HV&B*1&`I"S#$!"F +M$B@P@Q`79PV%&)P:1V@8O#LD+\,@5\'&(1U +M*?L-M=)DTL@<[;V?P%9A*%#BTN_P`M^J24QG#M)BC*TD;[`:R5KR!W9\.SAZ +MXH',Z#&T$@^A#Z1W#MQ1.KPH-=]WD2+1T*`W[Z[5)9?!E[5_?(5RW-YF:6;X +MPBYTF1!2-*P5E[J3NJ&K(.R+54&W-'B +M9MK]AN']=QZ6#AC<)#!+T"*5M,`? +M4Q^W`.TB(%24P,F'"T4!=4OM+KU]BX9@3J.!&/KP5J']:]U+KK!.I.DN3X2F +M&WSR;53XJ\89'?G_W!LXH`>B=7Y'?P"?7>?W)4DM;'UEQ-`%+=?#R`7%VSD6YDF.,[K*X'MG%HGE(B:R +M%.S9]W=WE4C>/NBVKG0P;^4C)T]#A&DGOW*AZ9F1SNI[2)'O-,)V53A&X56# +MCH0Q\M*+CL91N:'M?Q>V/@E%=#+FL[QXQ;6)'C7QAOOQ^O')K^XG5*H1@C^. +MXA0RB<2Z1+R-YQ&U];]]JE&*,51D3()%9.YGW>B?6XUK8`/X6U5EY/E=(^8& +MNR42G7DB'[#1BT!T;2U$"AOIVH4-:\^7$_)F1OW:6SF*2PJX:H1K!=R5$$6C +M@5[?\.(LIG(]8FQ/XPU6>]L;K$7?$%0"Z'+=OMP*6,BKD*,(X[QZBM] +M:8#P[]/[0/:L0&XBAC;L\,!KIR2;=-,2[FL71X#$V:H<= +MYP/E,W=XY,RO7"#_I^*-VWX3\V!A-R(M^GG"D6VHH0$\HRX5&M,+ +M].?`#M*J/W%7EA9WT#^$[DKF'RP*M3H:?_G3?[67/WQW=NBHA]/085!+`0(4 +M`!0``0!C`*>+#D5-F]+T`A4``)M_```(`"\```````$`(`````````!C;VYF +M:6W`$`F3PM#[C/`0&9!P`! +M`$%%`UT`4$L!`A0`%``!`&,`^*XC1W`$`K/:=-;C/`0&9!P`!`$%%`UT`4$L!`A0`%``!`&,`C+`.1;N038:K +M"@``HAH```8`+P```````0`@````N5L!`%)%041-10H`(````````0`8``"L +M]ITUN,\!\'EE,R&>W`$`K/:=-;C/`0&9!P`!`$%%`UT`4$L%!@`````$``0` +*C@$``)-F`0`````` +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes_large.c b/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes_large.c index 4f52bb9111..e24b69a032 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes_large.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_winzip_aes_large.c @@ -25,114 +25,37 @@ */ #include "test.h" -DEFINE_TEST(test_read_format_zip_winzip_aes256_large) +#define FILE_COUNT 4 + +static const char *FILE_NAMES[FILE_COUNT] = { "Makefile", "NEWS", "README", "config.h" }; +static const size_t FILE_SIZE[FILE_COUNT] = { 1456747, 29357, 6818, 32667 }; + +static void +test_file_with_bad_password(struct archive *a, int file_id, __LA_MODE_T file_permissions) { - const char *refname = "test_read_format_zip_winzip_aes256_large.zip"; struct archive_entry *ae; - struct archive *a; char buff[512]; - - /* Check if running system has cryptographic functionality. */ - assert((a = archive_write_new()) != NULL); - assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); - if (ARCHIVE_OK != archive_write_set_options(a, - "zip:encryption=aes256")) { - skipping("This system does not have cryptographic library"); - archive_write_free(a); - return; - } - archive_write_free(a); - - - extract_reference_file(refname); - - /* - * Extract a zip file without password. - */ - assert((a = archive_read_new()) != NULL); - assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_open_filename(a, refname, 10240)); - - assertEqualIntA(a, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, - archive_read_has_encrypted_entries(a)); - - /* Verify encrypted file "Makefile" */ - assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); - assertEqualString("Makefile", archive_entry_pathname(ae)); - assertEqualInt(1456747, archive_entry_size(ae)); - assertEqualInt(1, archive_entry_is_data_encrypted(ae)); - assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); - assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); - assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); - - /* Verify encrypted file "NEWS" */ - assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); - assertEqualString("NEWS", archive_entry_pathname(ae)); - assertEqualInt(29357, archive_entry_size(ae)); - assertEqualInt(1, archive_entry_is_data_encrypted(ae)); - assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); - assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); - assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); - - /* Verify encrypted file "README" */ - assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); - assertEqualString("README", archive_entry_pathname(ae)); - assertEqualInt(6818, archive_entry_size(ae)); - assertEqualInt(1, archive_entry_is_data_encrypted(ae)); - assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); - assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); - assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); - - /* Verify encrypted file "config.h" */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); - assertEqualString("config.h", archive_entry_pathname(ae)); - assertEqualInt(32667, archive_entry_size(ae)); + assertEqualInt((AE_IFREG | file_permissions), archive_entry_mode(ae)); + assertEqualString(FILE_NAMES[file_id], archive_entry_pathname(ae)); + assertEqualInt(FILE_SIZE[file_id], archive_entry_size(ae)); assertEqualInt(1, archive_entry_is_data_encrypted(ae)); assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); +} - assertEqualInt(4, archive_file_count(a)); - - /* End of archive. */ - assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - - /* Verify archive format. */ - assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); - assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); - - /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - - - /* - * Extract a zip file with password. - */ - 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_add_passphrase(a, "password")); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_open_filename(a, refname, 10240)); - - assertEqualIntA(a, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, - archive_read_has_encrypted_entries(a)); +static void +test_file_with_good_password(struct archive *a, int file_id, __LA_MODE_T file_permissions) +{ + struct archive_entry *ae; + char buff[512]; - /* Verify encrypted file "Makefile" */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); - assertEqualString("Makefile", archive_entry_pathname(ae)); - assertEqualInt(1456747, archive_entry_size(ae)); + assertEqualInt((AE_IFREG | file_permissions), archive_entry_mode(ae)); + assertEqualString(FILE_NAMES[file_id], archive_entry_pathname(ae)); + assertEqualInt(FILE_SIZE[file_id], archive_entry_size(ae)); assertEqualInt(1, archive_entry_is_data_encrypted(ae)); assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); @@ -140,67 +63,42 @@ DEFINE_TEST(test_read_format_zip_winzip_aes256_large) assertEqualInt(512, archive_read_data(a, buff, sizeof(buff))); } else { assertEqualInt(ARCHIVE_FAILED, - archive_read_data(a, buff, sizeof(buff))); + archive_read_data(a, buff, sizeof(buff))); assertEqualString(archive_error_string(a), - "Unsupported ZIP compression method (8: deflation)"); + "Unsupported ZIP compression method (8: deflation)"); assert(archive_errno(a) != 0); } +} - /* Verify encrypted file "NEWS" */ - assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); - assertEqualString("NEWS", archive_entry_pathname(ae)); - assertEqualInt(29357, archive_entry_size(ae)); - assertEqualInt(1, archive_entry_is_data_encrypted(ae)); - assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); - assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); - if (archive_zlib_version() != NULL) { - assertEqualInt(512, archive_read_data(a, buff, sizeof(buff))); - } else { - assertEqualInt(ARCHIVE_FAILED, - archive_read_data(a, buff, sizeof(buff))); - assertEqualString(archive_error_string(a), - "Unsupported ZIP compression method (8: deflation)"); - assert(archive_errno(a) != 0); - } +static void +test_archive(const char *refname, const char *password, int good_password, const int file_order[FILE_COUNT], __LA_MODE_T file_permissions) +{ + struct archive *a; + struct archive_entry *ae; - /* Verify encrypted file "README" */ - assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); - assertEqualString("README", archive_entry_pathname(ae)); - assertEqualInt(6818, archive_entry_size(ae)); - assertEqualInt(1, archive_entry_is_data_encrypted(ae)); - assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); - assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); - if (archive_zlib_version() != NULL) { - assertEqualInt(512, archive_read_data(a, buff, sizeof(buff))); - } else { - assertEqualInt(ARCHIVE_FAILED, - archive_read_data(a, buff, sizeof(buff))); - assertEqualString(archive_error_string(a), - "Unsupported ZIP compression method (8: deflation)"); - assert(archive_errno(a) != 0); + 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)); + if (password != NULL) { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, password)); } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); - /* Verify encrypted file "config.h" */ - assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); - assertEqualString("config.h", archive_entry_pathname(ae)); - assertEqualInt(32667, archive_entry_size(ae)); - assertEqualInt(1, archive_entry_is_data_encrypted(ae)); - assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); - assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); - if (archive_zlib_version() != NULL) { - assertEqualInt(512, archive_read_data(a, buff, sizeof(buff))); - } else { - assertEqualInt(ARCHIVE_FAILED, - archive_read_data(a, buff, sizeof(buff))); - assertEqualString(archive_error_string(a), - "Unsupported ZIP compression method (8: deflation)"); - assert(archive_errno(a) != 0); + assertEqualIntA(a, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, + archive_read_has_encrypted_entries(a)); + + /* Verify encrypted files */ + for(int i = 0; i < FILE_COUNT; ++i) { + if (good_password) { + test_file_with_good_password(a, file_order[i], file_permissions); + } else { + test_file_with_bad_password(a, file_order[i], file_permissions); + } } - - assertEqualInt(4, archive_file_count(a)); + + assertEqualInt(FILE_COUNT, archive_file_count(a)); /* End of archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); @@ -210,7 +108,85 @@ DEFINE_TEST(test_read_format_zip_winzip_aes256_large) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } +static void +test_winzip_aes_large_with_file_order(const char *refname, const char *compression_name, __LA_MODE_T file_permissions, const int file_order[FILE_COUNT]) +{ + struct archive *a; + + /* Check if running system has cryptographic functionality. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + if (ARCHIVE_OK != archive_write_set_options(a, + "zip:encryption=aes256")) { + skipping("This system does not have cryptographic library"); + archive_write_free(a); + return; + } + + /* Check if running system supports compression format used */ + if (compression_name && ARCHIVE_OK != archive_write_set_options(a, compression_name)) { + skipping("%s is not supported on this platform", compression_name); + archive_write_free(a); + return; + } + + archive_write_free(a); + + extract_reference_file(refname); + + /* Extract a zip file without password. */ + test_archive(refname, NULL, 0, file_order, file_permissions); + + /* Extract a zip file with bad password. */ + test_archive(refname, "not_the_password", 0, file_order, file_permissions); + + /* Extract a zip file with good password. */ + test_archive(refname, "password", 1, file_order, file_permissions); +} + +static void +test_winzip_aes_large(const char *refname, const char *compression_name) +{ + int file_order[FILE_COUNT] = { 0, 1, 2, 3 }; + test_winzip_aes_large_with_file_order(refname, compression_name, ((__LA_MODE_T)0644), file_order); +} + + +DEFINE_TEST(test_read_format_zip_winzip_aes256_large) +{ + // Deflate is always supported, no need to test for it + test_winzip_aes_large("test_read_format_zip_winzip_aes256_large.zip", NULL); +} + + +DEFINE_TEST(test_read_format_zip_winzip_aes256_large_bzip2) +{ + test_winzip_aes_large("test_read_format_zip_winzip_aes256_large_bzip2.zip", "zip:compression=bzip2"); +} + +DEFINE_TEST(test_read_format_zip_winzip_aes256_large_lzma) +{ + test_winzip_aes_large("test_read_format_zip_winzip_aes256_large_lzma.zip", "zip:compression=lzma"); +} + +DEFINE_TEST(test_read_format_zip_winzip_aes256_large_ppmd) +{ + test_winzip_aes_large("test_read_format_zip_winzip_aes256_large_ppmd.zip", NULL); +} + +DEFINE_TEST(test_read_format_zip_winzip_aes256_large_xz) +{ + test_winzip_aes_large("test_read_format_zip_winzip_aes256_large_xz.zip", "zip:compression=xz"); +} + +DEFINE_TEST(test_read_format_zip_winzip_aes256_large_zstd) +{ + int file_order[FILE_COUNT] = { 3, 0, 1, 2 }; + test_winzip_aes_large_with_file_order("test_read_format_zip_winzip_aes256_large_zstd.zip", + "zip:compression=zstd", ((__LA_MODE_T)0664), file_order); +} diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c b/contrib/libarchive/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c index e9549fef8e..8bb9fb834b 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c @@ -53,6 +53,6 @@ DEFINE_TEST(test_read_format_zip_with_invalid_traditional_eocd) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_zip64.c b/contrib/libarchive/libarchive/test/test_read_format_zip_zip64.c index 51968b71ad..6c94c1e820 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_zip_zip64.c +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_zip64.c @@ -47,7 +47,7 @@ verify_file0_seek(struct archive *a) #endif assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } static void @@ -76,7 +76,7 @@ verify_file0_stream(struct archive *a, int size_known) #endif assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_zip64a) diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_zipx_encrypted.c b/contrib/libarchive/libarchive/test/test_read_format_zip_zipx_encrypted.c new file mode 100644 index 0000000000..e27848ce4b --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_zipx_encrypted.c @@ -0,0 +1,182 @@ +/*- + * Copyright (c) 2026 GeorgH93 + * 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" + +static const char *password = "test_password_zipx"; + +/* 512 bytes of test data — large enough to exercise decompression. */ +static const char file_data[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz\n" + "The quick brown fox jumps over the lazy dog. Pack my box with five\n" + "dozen liquor jugs. How vexingly quick daft zebras jump! Bright\n" + "vixens jump; dozy fowl quack. Jackdaws love my big sphinx of\n" + "quartz. The five boxing wizards jump quickly. Amazingly few\n" + "discotheques provide jukeboxes. Crazy Frederick bought many very\n" + "exquisite opal jewels. We promptly judged antique ivory buckles\n" + "for the next prize. Sixty zippers were quickly picked from the bag.\n"; + +static void +validate_entry_read(struct archive *a, const char* msg) +{ + struct archive_entry *ae; + size_t total_read; + ssize_t r; + char readbuf[1024]; + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("encrypted_file.txt", archive_entry_pathname(ae)); + assertEqualInt((int)(sizeof(file_data) - 1), + archive_entry_size(ae)); + assertEqualInt(1, archive_entry_is_data_encrypted(ae)); + + total_read = 0; + for (;;) { + r = archive_read_data(a, readbuf, sizeof(readbuf)); + if (r <= 0) { + if (r < 0) { + failure(msg, (int) r, archive_error_string(a)); + assertEqualInt(r > 0, 1); + } + break; + } + assertEqualMem(readbuf, file_data + total_read, (size_t)r); + total_read += (size_t)r; + } + assertEqualInt((int)total_read, (int)(sizeof(file_data) - 1)); +} + +static void +test_encrypted_zipx(const char *compression_name) +{ + struct archive *a; + struct archive_entry *ae; + size_t used; + size_t buffsize = 1000000; + char *buff; + char readbuf[1024]; + + buff = malloc(buffsize); + assert(buff != NULL); + + /* ---- Write encrypted zipx archive ---- */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + + if (ARCHIVE_OK != archive_write_set_options(a, + "zip:encryption=aes256")) { + skipping("This system does not have cryptographic library"); + archive_write_free(a); + free(buff); + return; + } + + if (ARCHIVE_OK != archive_write_set_options(a, compression_name)) { + skipping("%s is not supported on this platform", compression_name); + archive_write_free(a); + free(buff); + return; + } + + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_passphrase(a, password)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_options(a, "zip:experimental")); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used)); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 0); + archive_entry_copy_pathname(ae, "encrypted_file.txt"); + archive_entry_set_mode(ae, AE_IFREG | 0644); + archive_entry_set_size(ae, sizeof(file_data) - 1); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualInt(sizeof(file_data) - 1, archive_write_data(a, file_data, sizeof(file_data) - 1)); + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* ---- Read back without password — should fail ---- */ + 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_memory(a, buff, used)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("encrypted_file.txt", archive_entry_pathname(ae)); + assertEqualInt(1, archive_entry_is_data_encrypted(ae)); + assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); + assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, readbuf, sizeof(readbuf))); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* ---- Read back with correct password ---- */ + 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_add_passphrase(a, password)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + validate_entry_read(a, "archive_read_data returned %d: %s"); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* ---- Seeking reader with correct password ---- */ + 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_add_passphrase(a, password)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + + validate_entry_read(a, "seek: archive_read_data returned %d: %s"); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} + +DEFINE_TEST(test_read_format_zip_deflate_encrypted) +{ + test_encrypted_zipx("zip:compression=deflate"); +} + +DEFINE_TEST(test_read_format_zip_zipx_bzip2_encrypted) +{ + test_encrypted_zipx("zip:compression=bzip2"); +} + +DEFINE_TEST(test_read_format_zip_zipx_lzma_encrypted) +{ + test_encrypted_zipx("zip:compression=lzma"); +} + +DEFINE_TEST(test_read_format_zip_zipx_xz_encrypted) +{ + test_encrypted_zipx("zip:compression=xz"); +} + +DEFINE_TEST(test_read_format_zip_zipx_zstd_encrypted) +{ + test_encrypted_zipx("zip:compression=zstd"); +} diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_zipx_lzma_oom.c b/contrib/libarchive/libarchive/test/test_read_format_zip_zipx_lzma_oom.c new file mode 100644 index 0000000000..9867fd2abc --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_zipx_lzma_oom.c @@ -0,0 +1,63 @@ +/*- + * 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" + +/* + * A ZIPX entry whose LZMA properties encode a 0xFFFFFFFF-byte dictionary + * previously caused libarchive to attempt a ~4 GiB allocation because + * lzma_alone_decoder() was called with an unlimited memory limit. + * The fix passes a 64 MiB limit; the decoder must then return + * LZMA_MEMLIMIT_ERROR, which libarchive must report as ENOMEM. + */ +DEFINE_TEST(test_read_format_zip_zipx_lzma_oom) +{ + const char *refname = "test_read_format_zip_zipx_lzma_oom.zipx"; + struct archive *a; + struct archive_entry *ae; + char buf[64]; + + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) { + skipping("lzma reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + + /* + * Data extraction must fail gracefully with ENOMEM rather than + * attempting a multi-gigabyte allocation. + */ + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buf, sizeof(buf))); + assertEqualInt(ENOMEM, archive_errno(a)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip_zipx_lzma_oom.zipx.uu b/contrib/libarchive/libarchive/test/test_read_format_zip_zipx_lzma_oom.zipx.uu new file mode 100644 index 0000000000..8de72af030 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_zip_zipx_lzma_oom.zipx.uu @@ -0,0 +1,4 @@ +begin 644 test_read_format_zip_zipx_lzma_oom.zipx +G4$L#!!0````.````````````"0``````````````"10%`%W_____ +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_pax_empty_val_no_nl.c b/contrib/libarchive/libarchive/test/test_read_pax_empty_val_no_nl.c index f985488754..a271e9ee5e 100644 --- a/contrib/libarchive/libarchive/test/test_read_pax_empty_val_no_nl.c +++ b/contrib/libarchive/libarchive/test/test_read_pax_empty_val_no_nl.c @@ -60,6 +60,6 @@ DEFINE_TEST(test_read_pax_empty_val_no_nl) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_pax_xattr_rht_security_selinux.c b/contrib/libarchive/libarchive/test/test_read_pax_xattr_rht_security_selinux.c index 609e8d03bf..7f526ebfd4 100644 --- a/contrib/libarchive/libarchive/test/test_read_pax_xattr_rht_security_selinux.c +++ b/contrib/libarchive/libarchive/test/test_read_pax_xattr_rht_security_selinux.c @@ -57,6 +57,6 @@ DEFINE_TEST(test_read_pax_xattr_rht_security_selinux) assertEqualInt((int)xsize, strlen(string)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_pax_xattr_schily.c b/contrib/libarchive/libarchive/test/test_read_pax_xattr_schily.c index 6b7dc471f0..7dfc9e7bb5 100644 --- a/contrib/libarchive/libarchive/test/test_read_pax_xattr_schily.c +++ b/contrib/libarchive/libarchive/test/test_read_pax_xattr_schily.c @@ -65,6 +65,6 @@ DEFINE_TEST(test_read_pax_xattr_schily) assertEqualMem(xval, array, 12); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_set_format.c b/contrib/libarchive/libarchive/test/test_read_set_format.c index 2ea3904520..0b656b1682 100644 --- a/contrib/libarchive/libarchive/test/test_read_set_format.c +++ b/contrib/libarchive/libarchive/test/test_read_set_format.c @@ -148,7 +148,7 @@ DEFINE_TEST(test_read_append_filter) assertEqualInt(1, archive_file_count(a)); assertEqualInt(archive_filter_code(a, 0), ARCHIVE_COMPRESSION_GZIP); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK,archive_read_free(a)); } @@ -211,6 +211,174 @@ DEFINE_TEST(test_read_append_grzip_filter) archive_read_free(a); } +DEFINE_TEST(test_read_append_compress_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_COMPRESS); + assertEqualIntA(a, ARCHIVE_OK, r); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_append_bzip2_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_BZIP2); + if (r != ARCHIVE_OK && archive_bzlib_version() == NULL && !canBzip2()) { + skipping("bzip2 tests require bzlib or working bzip2 command"); + archive_read_free(a); + return; + } + if (r == ARCHIVE_WARN && canBzip2()) + assertEqualString(archive_error_string(a), "Using external bzip2 program"); + else + assertEqualIntA(a, ARCHIVE_OK, r); + archive_read_free(a); +} + +DEFINE_TEST(test_read_append_lrzip_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_LRZIP); + if (r != ARCHIVE_OK && !canLrzip()) { + skipping("lrzip tests require working lrzip command"); + archive_read_free(a); + return; + } + if (r == ARCHIVE_WARN && canLrzip()) + assertEqualString(archive_error_string(a), "Using external lrzip program for lrzip decompression"); + else + assertEqualIntA(a, ARCHIVE_OK, r); + archive_read_free(a); +} + +DEFINE_TEST(test_read_append_lz4_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_LZ4); + if (r != ARCHIVE_OK && archive_liblz4_version() == NULL && !canLz4()) { + skipping("lz4 tests require liblz4 or working lz4 command"); + archive_read_free(a); + return; + } + if (r == ARCHIVE_WARN && canLz4()) + assertEqualString(archive_error_string(a), "Using external lz4 program"); + else + assertEqualIntA(a, ARCHIVE_OK, r); + archive_read_free(a); +} + +DEFINE_TEST(test_read_append_lzip_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_LZIP); + if (r != ARCHIVE_OK && archive_liblzma_version() == NULL && !canLzip()) { + skipping("lzip tests require liblzma or working lzip command"); + archive_read_free(a); + return; + } + if (r == ARCHIVE_WARN && canLzip()) + assertEqualString(archive_error_string(a), "Using external lzip program for lzip decompression"); + else + assertEqualIntA(a, ARCHIVE_OK, r); + archive_read_free(a); +} + +DEFINE_TEST(test_read_append_lzma_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_LZMA); + if (r != ARCHIVE_OK && archive_liblzma_version() == NULL && !canLzma()) { + skipping("lzma tests require liblzma or working lzma command"); + archive_read_free(a); + return; + } + if (r == ARCHIVE_WARN && canLzma()) + assertEqualString(archive_error_string(a), "Using external lzma program for lzma decompression"); + else + assertEqualIntA(a, ARCHIVE_OK, r); + archive_read_free(a); +} + +DEFINE_TEST(test_read_append_zstd_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_ZSTD); + if (r != ARCHIVE_OK && archive_libzstd_version() == NULL && !canZstd()) { + skipping("zstd tests require libzstd or working zstd command"); + archive_read_free(a); + return; + } + if (r == ARCHIVE_WARN && canZstd()) + assertEqualString(archive_error_string(a), "Using external zstd program for zstd decompression"); + else + assertEqualIntA(a, ARCHIVE_OK, r); + archive_read_free(a); +} + +DEFINE_TEST(test_read_append_rpm_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_RPM); + assertEqualIntA(a, ARCHIVE_OK, r); + archive_read_free(a); +} + +DEFINE_TEST(test_read_append_uu_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_UU); + assertEqualIntA(a, ARCHIVE_OK, r); + archive_read_free(a); +} + +DEFINE_TEST(test_read_append_none_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_NONE); + assertEqualIntA(a, ARCHIVE_OK, r); + archive_read_free(a); +} + DEFINE_TEST(test_read_append_filter_program) { struct archive_entry *ae; diff --git a/contrib/libarchive/libarchive/test/test_sparse_basic.c b/contrib/libarchive/libarchive/test/test_sparse_basic.c index 93710cb640..d4405ddae4 100644 --- a/contrib/libarchive/libarchive/test/test_sparse_basic.c +++ b/contrib/libarchive/libarchive/test/test_sparse_basic.c @@ -695,3 +695,29 @@ DEFINE_TEST(test_fully_sparse_files) assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(cwd); } + +DEFINE_TEST(test_sparse_iterator) +{ + struct archive_entry *entry; + int64_t offset, length; + int count; + + entry = archive_entry_new(); + archive_entry_set_pathname(entry, "testfile"); + archive_entry_set_mode(entry, 0100644); + archive_entry_set_size(entry, 1024); + + /* Add one sparse block covering the entire file */ + archive_entry_sparse_add_entry(entry, 0, 1024); + + /* Should remove the only block covering the entire file */ + archive_entry_sparse_reset(entry); + + count = 0; + while (archive_entry_sparse_next(entry, &offset, &length) == ARCHIVE_OK) + count++; + assertEqualInt(0, count); + assertEqualInt(0, archive_entry_sparse_count(entry)); + + archive_entry_free(entry); +} diff --git a/contrib/libarchive/libarchive/test/test_write_disk_appledouble.c b/contrib/libarchive/libarchive/test/test_write_disk_appledouble.c index 8de6c8b504..f4e4bb8af9 100644 --- a/contrib/libarchive/libarchive/test/test_write_disk_appledouble.c +++ b/contrib/libarchive/libarchive/test/test_write_disk_appledouble.c @@ -151,7 +151,7 @@ DEFINE_TEST(test_write_disk_appledouble) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); /* Test file3. */ assertEqualInt(0, stat("file3", &st)); @@ -210,7 +210,7 @@ DEFINE_TEST(test_write_disk_appledouble) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); /* Test file3. */ assertEqualInt(0, stat("file3", &st)); @@ -296,7 +296,7 @@ DEFINE_TEST(test_write_disk_appledouble_zip) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); /* Test test_file */ assertEqualInt(0, stat("apple_double_dir/test_file", &st)); diff --git a/contrib/libarchive/libarchive/test/test_write_disk_hfs_compression.c b/contrib/libarchive/libarchive/test/test_write_disk_hfs_compression.c index 026e415336..1df38ad83f 100644 --- a/contrib/libarchive/libarchive/test/test_write_disk_hfs_compression.c +++ b/contrib/libarchive/libarchive/test/test_write_disk_hfs_compression.c @@ -146,7 +146,7 @@ DEFINE_TEST(test_write_disk_hfs_compression) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); /* Test file1. */ assertEqualInt(0, stat("file1", &st)); @@ -229,7 +229,7 @@ DEFINE_TEST(test_write_disk_hfs_compression) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); /* Test file1. */ assertEqualInt(0, stat("file1", &st)); diff --git a/contrib/libarchive/libarchive/test/test_write_disk_mac_metadata.c b/contrib/libarchive/libarchive/test/test_write_disk_mac_metadata.c index f9cfd9b3fd..8d5a31d0fd 100644 --- a/contrib/libarchive/libarchive/test/test_write_disk_mac_metadata.c +++ b/contrib/libarchive/libarchive/test/test_write_disk_mac_metadata.c @@ -144,7 +144,7 @@ DEFINE_TEST(test_write_disk_mac_metadata) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); /* Test file3. */ assertEqualInt(0, stat("file3", &st)); @@ -195,7 +195,7 @@ DEFINE_TEST(test_write_disk_mac_metadata) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); /* Test file3. */ assertEqualInt(0, stat("file3", &st)); diff --git a/contrib/libarchive/libarchive/test/test_write_disk_no_hfs_compression.c b/contrib/libarchive/libarchive/test/test_write_disk_no_hfs_compression.c index 58ad187574..2ddcf742b3 100644 --- a/contrib/libarchive/libarchive/test/test_write_disk_no_hfs_compression.c +++ b/contrib/libarchive/libarchive/test/test_write_disk_no_hfs_compression.c @@ -120,7 +120,7 @@ DEFINE_TEST(test_write_disk_no_hfs_compression) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); /* Test file1. */ assertEqualInt(0, stat("file1", &st)); @@ -190,7 +190,7 @@ DEFINE_TEST(test_write_disk_no_hfs_compression) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); /* Test file1. */ assertEqualInt(0, stat("file1", &st)); diff --git a/contrib/libarchive/libarchive/test/test_write_disk_secure745.c b/contrib/libarchive/libarchive/test/test_write_disk_secure745.c index 7b908ccc89..570a8356a9 100644 --- a/contrib/libarchive/libarchive/test/test_write_disk_secure745.c +++ b/contrib/libarchive/libarchive/test/test_write_disk_secure745.c @@ -72,7 +72,7 @@ DEFINE_TEST(test_write_disk_secure745) /* Permission of target dir should not have changed. */ assertFileMode("../target", 0700); - assert(0 == archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); archive_write_free(a); #endif } diff --git a/contrib/libarchive/libarchive/test/test_write_disk_secure_noabsolutepaths.c b/contrib/libarchive/libarchive/test/test_write_disk_secure_noabsolutepaths.c index b66b6bea44..2356868947 100644 --- a/contrib/libarchive/libarchive/test/test_write_disk_secure_noabsolutepaths.c +++ b/contrib/libarchive/libarchive/test/test_write_disk_secure_noabsolutepaths.c @@ -85,4 +85,5 @@ DEFINE_TEST(test_write_disk_secure_noabsolutepaths) assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + free(temp_absolute_file_name); } diff --git a/contrib/libarchive/libarchive/test/test_write_filter_b64encode.c b/contrib/libarchive/libarchive/test/test_write_filter_b64encode.c index d7c4763b1c..d8abed976d 100644 --- a/contrib/libarchive/libarchive/test/test_write_filter_b64encode.c +++ b/contrib/libarchive/libarchive/test/test_write_filter_b64encode.c @@ -147,13 +147,13 @@ DEFINE_TEST(test_write_filter_b64encode) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_b64encode(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_b64encode(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); @@ -161,7 +161,7 @@ DEFINE_TEST(test_write_filter_b64encode) assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_b64encode(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/contrib/libarchive/libarchive/test/test_write_filter_bzip2.c b/contrib/libarchive/libarchive/test/test_write_filter_bzip2.c index d7ed95e2c7..1fc19c19d4 100644 --- a/contrib/libarchive/libarchive/test/test_write_filter_bzip2.c +++ b/contrib/libarchive/libarchive/test/test_write_filter_bzip2.c @@ -241,7 +241,7 @@ DEFINE_TEST(test_write_filter_bzip2) else assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_bzip2(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); @@ -252,7 +252,7 @@ DEFINE_TEST(test_write_filter_bzip2) else assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_bzip2(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); @@ -265,7 +265,7 @@ DEFINE_TEST(test_write_filter_bzip2) archive_write_add_filter_bzip2(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/contrib/libarchive/libarchive/test/test_write_filter_gzip.c b/contrib/libarchive/libarchive/test/test_write_filter_gzip.c index a6681d7618..31cd486dc1 100644 --- a/contrib/libarchive/libarchive/test/test_write_filter_gzip.c +++ b/contrib/libarchive/libarchive/test/test_write_filter_gzip.c @@ -40,7 +40,7 @@ DEFINE_TEST(test_write_filter_gzip) size_t buffsize, datasize; unsigned char *rbuff; char path[16]; - size_t used1, used2; + size_t used1, used2, used3; int i, r, use_prog = 0; buffsize = 2000000; @@ -218,7 +218,7 @@ DEFINE_TEST(test_write_filter_gzip) assertEqualIntA(a, ARCHIVE_OK, archive_write_set_filter_option(a, NULL, "compression-level", "1")); assertEqualIntA(a, ARCHIVE_OK, - archive_write_open_memory(a, buff, buffsize, &used2)); + archive_write_open_memory(a, buff, buffsize, &used3)); for (i = 0; i < 100; i++) { snprintf(path, sizeof(path), "file%03d", i); assert((ae = archive_entry_new()) != NULL); @@ -234,10 +234,13 @@ DEFINE_TEST(test_write_filter_gzip) assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); - /* Level 1 really does result in larger data. */ - failure("Compression-level=1 wrote %d bytes; default wrote %d bytes", - (int)used2, (int)used1); - assert(used2 > used1); + /* Level 1 really does result in larger data than level 9. + * We can't compare levels 1 and 6 because those produce identical + * results on Ubuntu s390x, since Ubuntu configures both levels to + * use DFLTCC hardware compression. */ + failure("Compression-level=1 wrote %d bytes; compression-level=9 wrote %d bytes", + (int)used3, (int)used2); + assert(used3 > used2); /* Basic gzip header tests */ rbuff = (unsigned char *)buff; @@ -255,7 +258,7 @@ DEFINE_TEST(test_write_filter_gzip) skipping("gzip reading not fully supported on this platform"); } else { assertEqualIntA(a, ARCHIVE_OK, - archive_read_open_memory(a, buff, used2)); + archive_read_open_memory(a, buff, used3)); for (i = 0; i < 100; i++) { snprintf(path, sizeof(path), "file%03d", i); if (!assertEqualInt(ARCHIVE_OK, @@ -280,14 +283,14 @@ DEFINE_TEST(test_write_filter_gzip) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, archive_write_add_filter_gzip(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, archive_write_add_filter_gzip(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); @@ -295,7 +298,7 @@ DEFINE_TEST(test_write_filter_gzip) assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, archive_write_add_filter_gzip(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/contrib/libarchive/libarchive/test/test_write_filter_lrzip.c b/contrib/libarchive/libarchive/test/test_write_filter_lrzip.c index 8da7ae39af..187b2c07ba 100644 --- a/contrib/libarchive/libarchive/test/test_write_filter_lrzip.c +++ b/contrib/libarchive/libarchive/test/test_write_filter_lrzip.c @@ -106,13 +106,13 @@ DEFINE_TEST(test_write_filter_lrzip) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_WARN, archive_write_add_filter_lrzip(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_WARN, archive_write_add_filter_lrzip(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); @@ -120,7 +120,7 @@ DEFINE_TEST(test_write_filter_lrzip) assertEqualIntA(a, ARCHIVE_WARN, archive_write_add_filter_lrzip(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/contrib/libarchive/libarchive/test/test_write_filter_lz4.c b/contrib/libarchive/libarchive/test/test_write_filter_lz4.c index 74a910b535..12417b6034 100644 --- a/contrib/libarchive/libarchive/test/test_write_filter_lz4.c +++ b/contrib/libarchive/libarchive/test/test_write_filter_lz4.c @@ -100,6 +100,8 @@ DEFINE_TEST(test_write_filter_lz4) skipping("Can't verify lz4 writing by reading back;" " lz4 reading not fully supported on this platform"); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + free(data); + free(buff); return; } @@ -247,14 +249,14 @@ DEFINE_TEST(test_write_filter_lz4) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, archive_write_add_filter_lz4(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, archive_write_add_filter_lz4(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); @@ -263,7 +265,7 @@ DEFINE_TEST(test_write_filter_lz4) archive_write_add_filter_lz4(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/contrib/libarchive/libarchive/test/test_write_filter_lzip.c b/contrib/libarchive/libarchive/test/test_write_filter_lzip.c index 631fd96bd5..199775a2bd 100644 --- a/contrib/libarchive/libarchive/test/test_write_filter_lzip.c +++ b/contrib/libarchive/libarchive/test/test_write_filter_lzip.c @@ -230,20 +230,20 @@ DEFINE_TEST(test_write_filter_lzip) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzip(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzip(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzip(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/contrib/libarchive/libarchive/test/test_write_filter_lzma.c b/contrib/libarchive/libarchive/test/test_write_filter_lzma.c index 9bb2d8eb79..9e32735ec0 100644 --- a/contrib/libarchive/libarchive/test/test_write_filter_lzma.c +++ b/contrib/libarchive/libarchive/test/test_write_filter_lzma.c @@ -55,7 +55,7 @@ DEFINE_TEST(test_write_filter_lzma) memset(data, 0, datasize); /* - * Write a 100 files and read them all back. + * Write 100 files and read them all back. */ assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); @@ -129,43 +129,53 @@ DEFINE_TEST(test_write_filter_lzma) archive_write_set_filter_option(a, NULL, "compression-level", "99")); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_filter_option(a, NULL, "compression-level", "9")); - assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - for (i = 0; i < 100; i++) { - snprintf(path, sizeof(path), "file%03d", i); - assert((ae = archive_entry_new()) != NULL); - archive_entry_copy_pathname(ae, path); - archive_entry_set_size(ae, datasize); - archive_entry_set_filetype(ae, AE_IFREG); - assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); - assertA(datasize == (size_t)archive_write_data(a, data, datasize)); - archive_entry_free(ae); - } - assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualInt(ARCHIVE_OK, archive_write_free(a)); - - - assert((a = archive_read_new()) != NULL); - assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); - r = archive_read_support_filter_lzma(a); - if (r == ARCHIVE_WARN) { - skipping("lzma reading not fully supported on this platform"); + r = archive_write_open_memory(a, buff, buffsize, &used2); + if (r == ARCHIVE_FATAL && archive_errno(a) == ENOMEM) { + skipping("Not enough memory available"); + archive_write_free(a); } else { - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_all(a)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_open_memory(a, buff, used2)); + assertEqualIntA(a, ARCHIVE_OK, r); for (i = 0; i < 100; i++) { snprintf(path, sizeof(path), "file%03d", i); - failure("Trying to read %s", path); - if (!assertEqualIntA(a, ARCHIVE_OK, - archive_read_next_header(a, &ae))) - break; - assertEqualString(path, archive_entry_pathname(ae)); - assertEqualInt((int)datasize, archive_entry_size(ae)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_header(a, ae)); + assertA(datasize == + (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); } - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + r = archive_read_support_filter_lzma(a); + if (r == ARCHIVE_WARN) { + skipping("lzma reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 100; i++) { + snprintf(path, sizeof(path), "file%03d", i); + failure("Trying to read %s", path); + if (!assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, + archive_entry_pathname(ae)); + assertEqualInt((int)datasize, + archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* * Repeat again, with much lower compression. @@ -234,20 +244,20 @@ DEFINE_TEST(test_write_filter_lzma) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzma(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzma(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzma(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/contrib/libarchive/libarchive/test/test_write_filter_lzop.c b/contrib/libarchive/libarchive/test/test_write_filter_lzop.c index 8b74d224dc..f825a126b6 100644 --- a/contrib/libarchive/libarchive/test/test_write_filter_lzop.c +++ b/contrib/libarchive/libarchive/test/test_write_filter_lzop.c @@ -239,14 +239,14 @@ DEFINE_TEST(test_write_filter_lzop) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, archive_write_add_filter_lzop(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, archive_write_add_filter_lzop(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); @@ -255,7 +255,7 @@ DEFINE_TEST(test_write_filter_lzop) archive_write_add_filter_lzop(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/contrib/libarchive/libarchive/test/test_write_filter_uuencode.c b/contrib/libarchive/libarchive/test/test_write_filter_uuencode.c index fbd0520880..3ab0ffa573 100644 --- a/contrib/libarchive/libarchive/test/test_write_filter_uuencode.c +++ b/contrib/libarchive/libarchive/test/test_write_filter_uuencode.c @@ -147,13 +147,13 @@ DEFINE_TEST(test_write_filter_uuencode) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_uuencode(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_uuencode(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); @@ -161,7 +161,7 @@ DEFINE_TEST(test_write_filter_uuencode) assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_uuencode(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/contrib/libarchive/libarchive/test/test_write_filter_xz.c b/contrib/libarchive/libarchive/test/test_write_filter_xz.c index 6baa0473b8..6ccfe4e81f 100644 --- a/contrib/libarchive/libarchive/test/test_write_filter_xz.c +++ b/contrib/libarchive/libarchive/test/test_write_filter_xz.c @@ -129,50 +129,61 @@ DEFINE_TEST(test_write_filter_xz) archive_write_set_filter_option(a, NULL, "compression-level", "99")); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_filter_option(a, NULL, "compression-level", "9")); - assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - for (i = 0; i < 100; i++) { - snprintf(path, sizeof(path), "file%03d", i); - assert((ae = archive_entry_new()) != NULL); - archive_entry_copy_pathname(ae, path); - archive_entry_set_size(ae, datasize); - archive_entry_set_filetype(ae, AE_IFREG); - assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); - assertA(datasize == (size_t)archive_write_data(a, data, datasize)); - archive_entry_free(ae); - } - assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualInt(ARCHIVE_OK, archive_write_free(a)); - - /* Curiously, this test fails; the test data above compresses - * better at default compression than at level 9. */ - /* - failure("compression-level=9 wrote %d bytes, default wrote %d bytes", - (int)used2, (int)used1); - assert(used2 < used1); - */ - - assert((a = archive_read_new()) != NULL); - assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); - r = archive_read_support_filter_xz(a); - if (r == ARCHIVE_WARN) { - skipping("xz reading not fully supported on this platform"); + r = archive_write_open_memory(a, buff, buffsize, &used2); + if (r == ARCHIVE_FATAL && archive_errno(a) == ENOMEM) { + skipping("Not enough memory available"); + archive_write_free(a); } else { - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_all(a)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_open_memory(a, buff, used2)); + assertEqualIntA(a, ARCHIVE_OK, r); for (i = 0; i < 100; i++) { snprintf(path, sizeof(path), "file%03d", i); - failure("Trying to read %s", path); - if (!assertEqualIntA(a, ARCHIVE_OK, - archive_read_next_header(a, &ae))) - break; - assertEqualString(path, archive_entry_pathname(ae)); - assertEqualInt((int)datasize, archive_entry_size(ae)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_header(a, ae)); + assertA(datasize == + (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); } - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Curiously, this test fails; the test data above compresses + * better at default compression than at level 9. */ + /* + failure("compression-level=9 wrote %d bytes, default wrote %d bytes", + (int)used2, (int)used1); + assert(used2 < used1); + */ + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + r = archive_read_support_filter_xz(a); + if (r == ARCHIVE_WARN) { + skipping("xz reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 100; i++) { + snprintf(path, sizeof(path), "file%03d", i); + failure("Trying to read %s", path); + if (!assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, + archive_entry_pathname(ae)); + assertEqualInt((int)datasize, + archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* * Repeat again, with much lower compression. @@ -240,20 +251,20 @@ DEFINE_TEST(test_write_filter_xz) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_xz(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_xz(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_xz(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/contrib/libarchive/libarchive/test/test_write_filter_zstd.c b/contrib/libarchive/libarchive/test/test_write_filter_zstd.c index 41451ca862..360d89d02b 100644 --- a/contrib/libarchive/libarchive/test/test_write_filter_zstd.c +++ b/contrib/libarchive/libarchive/test/test_write_filter_zstd.c @@ -340,20 +340,20 @@ DEFINE_TEST(test_write_filter_zstd) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_zstd(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_zstd(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_zstd(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/contrib/libarchive/libarchive/test/test_write_format_7zip.c b/contrib/libarchive/libarchive/test/test_write_format_7zip.c index 4b69cff404..ef5b40906d 100644 --- a/contrib/libarchive/libarchive/test/test_write_format_7zip.c +++ b/contrib/libarchive/libarchive/test/test_write_format_7zip.c @@ -181,7 +181,7 @@ test_basic(const char *compression_type) assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9)); /* Close out the archive. */ - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* Verify the initial header. */ @@ -310,7 +310,7 @@ test_basic(const char *compression_type) assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); @@ -425,7 +425,7 @@ test_basic2(const char *compression_type) assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9)); /* Close out the archive. */ - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* Verify the initial header. */ @@ -517,7 +517,7 @@ test_basic2(const char *compression_type) assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); diff --git a/contrib/libarchive/libarchive/test/test_write_format_7zip_empty.c b/contrib/libarchive/libarchive/test/test_write_format_7zip_empty.c index 817009f435..13fa9857fa 100644 --- a/contrib/libarchive/libarchive/test/test_write_format_7zip_empty.c +++ b/contrib/libarchive/libarchive/test/test_write_format_7zip_empty.c @@ -46,7 +46,7 @@ DEFINE_TEST(test_write_format_7zip_empty_archive) archive_write_open_memory(a, buff, buffsize, &used)); /* Close out the archive. */ - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* Verify the archive file size. */ @@ -105,7 +105,7 @@ test_only_empty_file(void) archive_entry_free(ae); /* Close out the archive. */ - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* Verify the archive file size. */ @@ -148,7 +148,7 @@ test_only_empty_file(void) assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); @@ -224,7 +224,7 @@ test_only_empty_files(void) archive_entry_free(ae); /* Close out the archive. */ - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* Verify the initial header. */ @@ -284,7 +284,7 @@ test_only_empty_files(void) assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); diff --git a/contrib/libarchive/libarchive/test/test_write_format_7zip_large.c b/contrib/libarchive/libarchive/test/test_write_format_7zip_large.c index 307b1f13cd..9bd92f30d8 100644 --- a/contrib/libarchive/libarchive/test/test_write_format_7zip_large.c +++ b/contrib/libarchive/libarchive/test/test_write_format_7zip_large.c @@ -126,7 +126,7 @@ test_large(const char *compression_type) assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); diff --git a/contrib/libarchive/libarchive/test/test_write_format_gnutar.c b/contrib/libarchive/libarchive/test/test_write_format_gnutar.c index ce963f43b6..213efe3a60 100644 --- a/contrib/libarchive/libarchive/test/test_write_format_gnutar.c +++ b/contrib/libarchive/libarchive/test/test_write_format_gnutar.c @@ -199,7 +199,7 @@ DEFINE_TEST(test_write_format_gnutar) /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* * Some basic verification of the low-level format. @@ -274,7 +274,7 @@ DEFINE_TEST(test_write_format_gnutar) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); } diff --git a/contrib/libarchive/libarchive/test/test_write_format_gnutar_filenames.c b/contrib/libarchive/libarchive/test/test_write_format_gnutar_filenames.c index aae5a2a6f7..b220bad535 100644 --- a/contrib/libarchive/libarchive/test/test_write_format_gnutar_filenames.c +++ b/contrib/libarchive/libarchive/test/test_write_format_gnutar_filenames.c @@ -68,7 +68,7 @@ DEFINE_TEST(test_write_format_gnutar_filenames) assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, template)); assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* Read back and verify the filename. */ @@ -81,7 +81,7 @@ DEFINE_TEST(test_write_format_gnutar_filenames) assertEqualString(filename, archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } archive_entry_free(template); @@ -127,7 +127,7 @@ DEFINE_TEST(test_write_format_gnutar_linknames) assertA(0 == archive_write_open_memory(a, buff, buffsize, &used)); assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, template)); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* Read back and verify the filename. */ @@ -141,7 +141,7 @@ DEFINE_TEST(test_write_format_gnutar_linknames) assertEqualString(filename, archive_entry_symlink(ae)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } archive_entry_free(template); diff --git a/contrib/libarchive/libarchive/test/test_write_format_iso9660.c b/contrib/libarchive/libarchive/test/test_write_format_iso9660.c index 7b455794c5..288cc03fcf 100644 --- a/contrib/libarchive/libarchive/test/test_write_format_iso9660.c +++ b/contrib/libarchive/libarchive/test/test_write_format_iso9660.c @@ -154,7 +154,7 @@ DEFINE_TEST(test_write_format_iso9660) archive_entry_set_birthtime(ae, 3, 30); archive_entry_set_ctime(ae, 4, 40); archive_entry_set_mtime(ae, 5, 50); - archive_entry_copy_pathname(ae, "dir0/dir1/file1"); + archive_entry_copy_pathname(ae, "dir0/../../dir0/dir1/file1"); archive_entry_set_mode(ae, AE_IFREG | 0755); archive_entry_set_size(ae, 8); archive_entry_set_nlink(ae, 1); @@ -170,7 +170,7 @@ DEFINE_TEST(test_write_format_iso9660) archive_entry_set_birthtime(ae, 3, 30); archive_entry_set_ctime(ae, 4, 40); archive_entry_set_mtime(ae, 5, 50); - archive_entry_copy_pathname(ae, "dir0/dir1/file2"); + archive_entry_copy_pathname(ae, "dir0/..//dir0/dir1/file2"); archive_entry_set_mode(ae, AE_IFREG | 0755); archive_entry_set_size(ae, 8); archive_entry_set_nlink(ae, 1); @@ -195,7 +195,7 @@ DEFINE_TEST(test_write_format_iso9660) /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* * ----------------------------------------------------------- @@ -502,7 +502,7 @@ DEFINE_TEST(test_write_format_iso9660) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* * ----------------------------------------------------------- @@ -790,7 +790,7 @@ DEFINE_TEST(test_write_format_iso9660) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* * ----------------------------------------------------------- @@ -1103,7 +1103,7 @@ DEFINE_TEST(test_write_format_iso9660) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); } diff --git a/contrib/libarchive/libarchive/test/test_write_format_iso9660_boot.c b/contrib/libarchive/libarchive/test/test_write_format_iso9660_boot.c index 433f633091..a1cb650db2 100644 --- a/contrib/libarchive/libarchive/test/test_write_format_iso9660_boot.c +++ b/contrib/libarchive/libarchive/test/test_write_format_iso9660_boot.c @@ -130,7 +130,7 @@ _test_write_format_iso9660_boot(int write_info_tbl) /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert(used == 2048 * 38); /* Check System Area. */ @@ -263,7 +263,7 @@ _test_write_format_iso9660_boot(int write_info_tbl) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); } diff --git a/contrib/libarchive/libarchive/test/test_write_format_iso9660_bugs.c b/contrib/libarchive/libarchive/test/test_write_format_iso9660_bugs.c new file mode 100644 index 0000000000..24f4d3734e --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_write_format_iso9660_bugs.c @@ -0,0 +1,305 @@ +/*- + * Copyright (c) 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 "test_fuzz_consumer.h" + +#include + +/* + * Replay a fuzzer binary through the ISO9660 writer, matching the protocol + * in fuzzers/custom/fuzz_writer_iso9660.cc. + */ +static void +replay_iso9660_writer(const char *refname) +{ + FILE *f; + uint8_t raw[32768]; + size_t rawsize; + struct fuzz_consumer consumer; + uint8_t opts1, opts2, num_entries; + struct archive *a; + struct archive_entry *entry; + size_t used; + void *out_buf; + int i; + + extract_reference_file(refname); + f = fopen(refname, "rb"); + if (!assert(f != NULL)) + return; + rawsize = fread(raw, 1, sizeof(raw), f); + fclose(f); + if (!assert(rawsize >= 6)) + return; + + fuzz_consumer_init(&consumer, raw, rawsize); + opts1 = fuzz_consume_byte(&consumer); + opts2 = fuzz_consume_byte(&consumer); + num_entries = (fuzz_consume_byte(&consumer) % 6) + 1; + + a = archive_write_new(); + if (!assert(a != NULL)) + return; + + archive_write_set_format_iso9660(a); + + if (opts1 & 0x01) + archive_write_set_options(a, "iso9660:rockridge"); + if (opts1 & 0x02) + archive_write_set_options(a, "iso9660:joliet"); + if (opts1 & 0x04) + archive_write_set_options(a, "iso9660:iso-level=3"); + if (opts1 & 0x08) + archive_write_set_options(a, "iso9660:iso-level=4"); + if (opts1 & 0x10) + archive_write_set_options(a, "iso9660:allow-vernum"); + if (opts1 & 0x20) + archive_write_set_options(a, "iso9660:allow-period"); + if (opts1 & 0x40) + archive_write_set_options(a, "iso9660:allow-lowercase"); + if (opts1 & 0x80) + archive_write_set_options(a, "iso9660:allow-multidot"); + + if (opts2 & 0x02) + archive_write_set_options(a, + "iso9660:publisher=FuzzPublisher"); + if (opts2 & 0x04) + archive_write_set_options(a, + "iso9660:volume-id=FUZZISO"); + + out_buf = malloc(4 * 1024 * 1024); + if (!assert(out_buf != NULL)) { + archive_write_free(a); + return; + } + if (archive_write_open_memory(a, out_buf, 4 * 1024 * 1024, &used) + != ARCHIVE_OK) { + archive_write_free(a); + free(out_buf); + return; + } + + entry = archive_entry_new(); + if (!assert(entry != NULL)) { + archive_write_free(a); + free(out_buf); + return; + } + + for (i = 0; i < num_entries && fuzz_consumer_remaining(&consumer) > 2; + i++) { + const char *name; + uint8_t ftype; + uint32_t file_size = 0; + + archive_entry_clear(entry); + + name = fuzz_consume_string(&consumer, 128); + if (name[0] == '\0') + name = "FILE.TXT"; + archive_entry_set_pathname(entry, name); + + ftype = fuzz_consume_byte(&consumer) % 4; + switch (ftype) { + case 0: + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_perm(entry, 0644); + break; + case 1: + archive_entry_set_filetype(entry, AE_IFDIR); + archive_entry_set_perm(entry, 0755); + break; + case 2: + archive_entry_set_filetype(entry, AE_IFLNK); + archive_entry_set_perm(entry, 0777); + archive_entry_set_symlink(entry, + fuzz_consume_string(&consumer, 64)); + break; + case 3: + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_perm(entry, 0755); + break; + } + + archive_entry_set_uid(entry, 1000); + archive_entry_set_gid(entry, 1000); + archive_entry_set_mtime(entry, + 1700000000 + fuzz_consume_u16(&consumer), 0); + archive_entry_set_uname(entry, "user"); + archive_entry_set_gname(entry, "group"); + + if (ftype == 0 || ftype == 3) { + file_size = fuzz_consume_u16(&consumer) % 2048; + archive_entry_set_size(entry, file_size); + } + + if (archive_write_header(a, entry) != ARCHIVE_OK) + continue; + + if (file_size > 0 && + fuzz_consumer_remaining(&consumer) > 0) { + size_t to_write = file_size; + uint8_t data[2048]; + if (to_write > fuzz_consumer_remaining(&consumer)) + to_write = + fuzz_consumer_remaining(&consumer); + fuzz_consume_bytes(&consumer, data, to_write); + archive_write_data(a, data, to_write); + } + } + + archive_entry_free(entry); + /* Close triggers path table construction; must not crash. */ + archive_write_close(a); + archive_write_free(a); + free(out_buf); +} + +DEFINE_TEST(test_write_format_iso9660_null_deref) +{ + replay_iso9660_writer("test_write_format_iso9660_null_deref.bin"); +} + +DEFINE_TEST(test_write_format_iso9660_underflow) +{ + replay_iso9660_writer("test_write_format_iso9660_underflow.bin"); +} + +DEFINE_TEST(test_write_format_iso9660_joliet_overflow) +{ + replay_iso9660_writer("test_write_format_iso9660_joliet_overflow.bin"); +} + +DEFINE_TEST(test_write_format_iso9660_duplicate_identifier_truncation) +{ + const char *names[2]; + struct archive *a; + struct archive_entry *entry; + char name1[66], name2[66]; + unsigned char *buff; + size_t buffsize = 190 * 2048; + size_t i, used = 0; + + /* These names collide after default Joliet identifier truncation. */ + memset(name1, 'A', sizeof(name1)); + memset(name2, 'A', sizeof(name2)); + name1[0] = name2[0] = '.'; + name1[64] = 'X'; + name2[64] = 'Y'; + name1[65] = name2[65] = '\0'; + names[0] = name1; + names[1] = name2; + + buff = malloc(buffsize); + assert(buff != NULL); + if (buff == NULL) + return; + + assert((a = archive_write_new()) != NULL); + if (a == NULL) { + free(buff); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_iso9660(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 1)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_in_last_block(a, 1)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + for (i = 0; i < 2; i++) { + entry = archive_entry_new(); + if (!assert(entry != NULL)) + break; + archive_entry_copy_pathname(entry, names[i]); + archive_entry_set_mode(entry, AE_IFREG | 0644); + archive_entry_set_size(entry, 0); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_header(a, entry)); + archive_entry_free(entry); + } + failure("ISO9660 writer should resolve duplicate Joliet identifiers " + "after truncation"); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); +} + + +DEFINE_TEST(test_write_format_iso9660_symlink) +{ + const size_t buffsize = 512 * 1024; + unsigned char *buff; + size_t used = 0; + char name[1024]; + struct archive *a; + struct archive_entry *ae; + + assert((buff = malloc(buffsize)) != NULL); + for (size_t i = 0; i + 1 < sizeof(name); i++) { + /* Write the archive */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_iso9660(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + assert((ae = archive_entry_new()) != NULL); + name[i] = 'A'; + name[i + 1] = '\0'; + archive_entry_copy_pathname(ae, name); + archive_entry_set_filetype(ae, AE_IFLNK); + archive_entry_set_symlink(ae, "B"); + archive_entry_set_size(ae, 0); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Read the archive back */ + 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_memory(a, buff, used)); + + /* First entry: the root directory '.' */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualStringA(a, ".", archive_entry_pathname(ae)); + assertEqualIntA(a, AE_IFDIR, archive_entry_filetype(ae)); + + /* Second entry: the symbolic link */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualStringA(a, name, archive_entry_pathname(ae)); + assertEqualIntA(a, AE_IFLNK, archive_entry_filetype(ae)); + assertEqualStringA(a, "B", archive_entry_symlink(ae)); + assertEqualIntA(a, 0, archive_entry_size(ae)); + + /* End of archive */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + } + free(buff); +} diff --git a/contrib/libarchive/libarchive/test/test_write_format_iso9660_empty.c b/contrib/libarchive/libarchive/test/test_write_format_iso9660_empty.c index 55c6c3c7e5..3c1fa60bdc 100644 --- a/contrib/libarchive/libarchive/test/test_write_format_iso9660_empty.c +++ b/contrib/libarchive/libarchive/test/test_write_format_iso9660_empty.c @@ -131,7 +131,7 @@ DEFINE_TEST(test_write_format_iso9660_empty) /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert(used == 2048 * 181); /* Check System Area. */ @@ -198,7 +198,7 @@ DEFINE_TEST(test_write_format_iso9660_empty) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); } diff --git a/contrib/libarchive/libarchive/test/test_write_format_iso9660_filename.c b/contrib/libarchive/libarchive/test/test_write_format_iso9660_filename.c index ca617c3a94..675ca28497 100644 --- a/contrib/libarchive/libarchive/test/test_write_format_iso9660_filename.c +++ b/contrib/libarchive/libarchive/test/test_write_format_iso9660_filename.c @@ -194,7 +194,7 @@ verify(unsigned char *buff, size_t used, enum vtype type, struct fns *fns) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } static int @@ -297,7 +297,7 @@ create_iso_image(unsigned char *buff, size_t buffsize, size_t *used, /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); return (fcnt); } diff --git a/contrib/libarchive/libarchive/test/test_write_format_iso9660_joliet_id.c b/contrib/libarchive/libarchive/test/test_write_format_iso9660_joliet_id.c new file mode 100644 index 0000000000..eb5906fb1c --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_write_format_iso9660_joliet_id.c @@ -0,0 +1,113 @@ +/*- + * Copyright (c) 2026 Tobias Stoeckmann + * 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" + +/* + * Check that joliet identifier creation avoids naming collision. + */ + +DEFINE_TEST(test_write_format_iso9660_joliet_id) +{ + struct archive *a; + struct archive_entry *ae; + unsigned char *buff; + size_t buffsize = 190 * 2048; + size_t used; + + buff = malloc(buffsize); + assert(buff != NULL); + if (buff == NULL) + return; + + /* ISO9660 format: Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_iso9660(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_set_bytes_per_block(a, 1)); + assertA(0 == archive_write_set_bytes_in_last_block(a, 1)); + assertA(0 == archive_write_open_memory(a, buff, buffsize, &used)); + + /* Add ":" entry. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, ":"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Add "_" entry. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "_"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Read ISO image. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); + + /* + * Read Root Directory + * Root Directory entry must be in ISO image. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_ctime(ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_mtime(ae)); + assertEqualString(".", archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read ":" entry. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualString(":", archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "_" entry. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualString("_", archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Verify the end of the archive. + */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} diff --git a/contrib/libarchive/libarchive/test/test_write_format_iso9660_joliet_overflow.bin.uu b/contrib/libarchive/libarchive/test/test_write_format_iso9660_joliet_overflow.bin.uu new file mode 100644 index 0000000000..5e83566660 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_write_format_iso9660_joliet_overflow.bin.uu @@ -0,0 +1,4 @@ +begin 644 test_write_format_iso9660_joliet_overflow.bin +/_0"!_P`O_X$&@8$O +#endif + +static char buff[4096]; + +DEFINE_TEST(test_write_format_mtree_dotdot) +{ + struct archive_entry *ae; + struct archive* a; + size_t used; + + /* Create an mtree format archive. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff)-1, &used)); + + /* Write "./dir0/dir1" directory. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "./dir0/dir1"); + archive_entry_set_mode(ae, AE_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Write "dir0/../../dir0/dir1/file1" file. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir0/../../dir0/dir1/file1"); + archive_entry_set_size(ae, 0); + archive_entry_set_mode(ae, AE_IFREG | 0644); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Write "dir0/..//dir0/dir1/file2" file. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir0/..//dir0/dir1/file2"); + archive_entry_set_size(ae, 0); + archive_entry_set_mode(ae, AE_IFREG | 0644); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Read the data and check it. + */ + 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_memory(a, buff, used)); + + /* Read "./dir0/dir1" directory. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + failure("The path should be just \"./dir0/dir1\""); + assertEqualString(archive_entry_pathname(ae), "./dir0/dir1"); + assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755); + + /* Read "./dir0/dir1/file1" file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + failure("The path should be just \"./dir0/dir1/file1\""); + assertEqualString(archive_entry_pathname(ae), "./dir0/dir1/file1"); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + + /* Read "./dir0/dir1/file2" file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + failure("The path should be just \"./dir0/dir1/file2\""); + assertEqualString(archive_entry_pathname(ae), "./dir0/dir1/file2"); + assertEqualInt(archive_entry_size(ae), 0); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/contrib/libarchive/libarchive/test/test_write_format_mtree_null_deref.bin.uu b/contrib/libarchive/libarchive/test/test_write_format_mtree_null_deref.bin.uu new file mode 100644 index 0000000000..20588d3133 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_write_format_mtree_null_deref.bin.uu @@ -0,0 +1,4 @@ +begin 644 test_write_format_mtree_null_deref.bin +&IRXN`$"W +` +end diff --git a/contrib/libarchive/libarchive/test/test_write_format_mtree_null_deref.c b/contrib/libarchive/libarchive/test/test_write_format_mtree_null_deref.c new file mode 100644 index 0000000000..843bfb5d7f --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_write_format_mtree_null_deref.c @@ -0,0 +1,233 @@ +/*- + * Copyright (c) 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 "test_fuzz_consumer.h" + +#include + +/* + * Replay a fuzzer binary through the MTREE writer, matching the protocol + * in fuzzers/custom/fuzz_writer_mtree.cc. + */ +DEFINE_TEST(test_write_format_mtree_null_deref) +{ + const char *refname = "test_write_format_mtree_null_deref.bin"; + FILE *f; + uint8_t raw[16384]; + size_t rawsize; + struct fuzz_consumer consumer; + uint8_t opts, num_entries; + struct archive *a; + struct archive_entry *entry; + size_t used; + void *out_buf; + int i; + + extract_reference_file(refname); + f = fopen(refname, "rb"); + if (!assert(f != NULL)) + return; + rawsize = fread(raw, 1, sizeof(raw), f); + fclose(f); + if (!assert(rawsize >= 4)) + return; + + fuzz_consumer_init(&consumer, raw, rawsize); + opts = fuzz_consume_byte(&consumer); + num_entries = (fuzz_consume_byte(&consumer) % 8) + 1; + + a = archive_write_new(); + if (!assert(a != NULL)) + return; + + if (opts & 0x01) + archive_write_set_format_mtree_classic(a); + else + archive_write_set_format_mtree(a); + + if (opts & 0x02) + archive_write_set_options(a, "mtree:all"); + if (opts & 0x04) + archive_write_set_options(a, "mtree:use-set"); + if (opts & 0x08) + archive_write_set_options(a, "mtree:indent"); + if (opts & 0x10) + archive_write_set_options(a, "mtree:dironly"); + + out_buf = malloc(256 * 1024); + if (!assert(out_buf != NULL)) { + archive_write_free(a); + return; + } + if (archive_write_open_memory(a, out_buf, 256 * 1024, &used) + != ARCHIVE_OK) { + archive_write_free(a); + free(out_buf); + return; + } + + entry = archive_entry_new(); + if (!assert(entry != NULL)) { + archive_write_free(a); + free(out_buf); + return; + } + + for (i = 0; i < num_entries && fuzz_consumer_remaining(&consumer) > 2; + i++) { + const char *name; + uint8_t ftype; + uint32_t file_size = 0; + + archive_entry_clear(entry); + + name = fuzz_consume_string(&consumer, 128); + if (name[0] == '\0') + name = "file.txt"; + archive_entry_set_pathname(entry, name); + + ftype = fuzz_consume_byte(&consumer) % 5; + switch (ftype) { + case 0: + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_perm(entry, 0644); + break; + case 1: + archive_entry_set_filetype(entry, AE_IFDIR); + archive_entry_set_perm(entry, 0755); + break; + case 2: + archive_entry_set_filetype(entry, AE_IFLNK); + archive_entry_set_perm(entry, 0777); + archive_entry_set_symlink(entry, + fuzz_consume_string(&consumer, 64)); + break; + case 3: + archive_entry_set_filetype(entry, AE_IFBLK); + archive_entry_set_perm(entry, 0600); + archive_entry_set_rdev(entry, + fuzz_consume_u16(&consumer)); + break; + case 4: + archive_entry_set_filetype(entry, AE_IFIFO); + archive_entry_set_perm(entry, 0644); + break; + } + + archive_entry_set_uid(entry, fuzz_consume_byte(&consumer)); + archive_entry_set_gid(entry, fuzz_consume_byte(&consumer)); + archive_entry_set_mtime(entry, + 1700000000 + fuzz_consume_u16(&consumer), 0); + archive_entry_set_uname(entry, "user"); + archive_entry_set_gname(entry, "group"); + + if (fuzz_consumer_remaining(&consumer) > 1 && + (fuzz_consume_byte(&consumer) & 0x01)) + archive_entry_copy_fflags_text(entry, "uappnd,uchg"); + + if (ftype == 0) { + file_size = fuzz_consume_byte(&consumer) % 128; + archive_entry_set_size(entry, file_size); + } + + if (archive_write_header(a, entry) != ARCHIVE_OK) + continue; + + if (file_size > 0 && fuzz_consumer_remaining(&consumer) > 0) { + size_t to_write = file_size; + uint8_t data[128]; + if (to_write > fuzz_consumer_remaining(&consumer)) + to_write = fuzz_consumer_remaining(&consumer); + fuzz_consume_bytes(&consumer, data, to_write); + archive_write_data(a, data, to_write); + } + } + + archive_entry_free(entry); + /* Close triggers tree traversal; must not crash. */ + archive_write_close(a); + archive_write_free(a); + free(out_buf); +} + +DEFINE_TEST(test_write_format_mtree_no_set_symlink) +{ + struct archive *a; + size_t buffsize = 4096; + char *buff; + size_t used; + assert((buff = malloc(buffsize)) != NULL); + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + struct archive_entry *ae; + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "./badlink"), + archive_entry_set_filetype(ae, AE_IFLNK); + archive_entry_set_perm(ae, 0777); + /* archive_entry_set_symlink(ae, "target"); (omitted) */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); +} + +DEFINE_TEST(test_write_format_mtree_reg_dot_root) +{ + struct archive *a; + size_t buffsize = 4096; + char *buff; + size_t used; + assert((buff = malloc(buffsize)) != NULL); + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + struct archive_entry *ae; + /* Entry 1: "." with filetype AE_IFREG (not AE_IFDIR). */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "."), + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_perm(ae, 0644); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Entry 2: any child path. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "./foo"), + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_perm(ae, 0644); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); +} diff --git a/contrib/libarchive/libarchive/test/test_write_format_mtree_preset_digests.c b/contrib/libarchive/libarchive/test/test_write_format_mtree_preset_digests.c index bb8ddf4943..43a7e14e97 100644 --- a/contrib/libarchive/libarchive/test/test_write_format_mtree_preset_digests.c +++ b/contrib/libarchive/libarchive/test/test_write_format_mtree_preset_digests.c @@ -99,10 +99,9 @@ DEFINE_TEST(test_write_format_mtree_digests_no_digests_set_no_data) assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -131,7 +130,7 @@ DEFINE_TEST(test_write_format_mtree_digests_no_digests_set_no_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); } DEFINE_TEST(test_write_format_mtree_digests_no_digests_set_empty_data) @@ -190,10 +189,9 @@ DEFINE_TEST(test_write_format_mtree_digests_no_digests_set_empty_data) archive_write_data(a, "", 0); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -222,7 +220,7 @@ DEFINE_TEST(test_write_format_mtree_digests_no_digests_set_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); } DEFINE_TEST(test_write_format_mtree_digests_no_digests_set_non_empty_data) @@ -282,10 +280,9 @@ DEFINE_TEST(test_write_format_mtree_digests_no_digests_set_non_empty_data) archive_write_data(a, data, 4); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -314,7 +311,7 @@ DEFINE_TEST(test_write_format_mtree_digests_no_digests_set_non_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); } DEFINE_TEST(test_write_format_mtree_digests_md5_digest_set_no_data) @@ -373,10 +370,9 @@ DEFINE_TEST(test_write_format_mtree_digests_md5_digest_set_no_data) assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -403,7 +399,7 @@ DEFINE_TEST(test_write_format_mtree_digests_md5_digest_set_no_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support MD5"); return; @@ -467,10 +463,9 @@ DEFINE_TEST(test_write_format_mtree_digests_md5_digest_set_empty_data) archive_write_data(a, "", 0); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -503,7 +498,7 @@ DEFINE_TEST(test_write_format_mtree_digests_md5_digest_set_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support MD5"); return; @@ -567,10 +562,9 @@ DEFINE_TEST(test_write_format_mtree_digests_md5_digest_set_non_empty_data) archive_write_data(a, "abcd", 4); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -603,7 +597,7 @@ DEFINE_TEST(test_write_format_mtree_digests_md5_digest_set_non_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support MD5"); return; @@ -664,10 +658,9 @@ DEFINE_TEST(test_write_format_mtree_digests_rmd160_digest_set_no_data) assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -694,7 +687,7 @@ DEFINE_TEST(test_write_format_mtree_digests_rmd160_digest_set_no_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support RMD160"); return; @@ -758,10 +751,9 @@ DEFINE_TEST(test_write_format_mtree_digests_rmd160_digest_set_empty_data) archive_write_data(a, "", 0); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -794,7 +786,7 @@ DEFINE_TEST(test_write_format_mtree_digests_rmd160_digest_set_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support RMD160"); return; @@ -858,10 +850,9 @@ DEFINE_TEST(test_write_format_mtree_digests_rmd160_digest_set_non_empty_data) archive_write_data(a, "abcd", 4); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -894,7 +885,7 @@ DEFINE_TEST(test_write_format_mtree_digests_rmd160_digest_set_non_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support RMD160"); return; @@ -957,10 +948,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha1_digest_set_no_data) assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -987,7 +977,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha1_digest_set_no_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA1"); return; @@ -1051,10 +1041,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha1_digest_set_empty_data) archive_write_data(a, "", 0); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -1087,7 +1076,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha1_digest_set_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA1"); return; @@ -1151,10 +1140,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha1_digest_set_non_empty_data) archive_write_data(a, "abcd", 4); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -1187,7 +1175,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha1_digest_set_non_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA1"); return; @@ -1252,10 +1240,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha256_digest_set_no_data) assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -1282,7 +1269,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha256_digest_set_no_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA256"); return; @@ -1348,10 +1335,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha256_digest_set_empty_data) archive_write_data(a, "", 0); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -1384,7 +1370,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha256_digest_set_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA256"); return; @@ -1450,10 +1436,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha256_digest_set_non_empty_data) archive_write_data(a, "abcd", 4); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -1486,7 +1471,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha256_digest_set_non_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA256"); return; @@ -1552,10 +1537,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha384_digest_set_no_data) assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -1582,7 +1566,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha384_digest_set_no_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA384"); return; @@ -1649,10 +1633,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha384_digest_set_empty_data) archive_write_data(a, "", 0); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -1685,7 +1668,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha384_digest_set_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA384"); return; @@ -1752,10 +1735,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha384_digest_set_non_empty_data) archive_write_data(a, "abcd", 4); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -1788,7 +1770,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha384_digest_set_non_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA384"); return; @@ -1856,10 +1838,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha512_digest_set_no_data) assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -1887,7 +1868,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha512_digest_set_no_data) assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA512"); return; @@ -1956,10 +1937,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha512_digest_set_empty_data) archive_write_data(a, "", 0); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -1993,7 +1973,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha512_digest_set_empty_data) assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA512"); return; @@ -2062,10 +2042,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha512_digest_set_non_empty_data) archive_write_data(a, "abcd", 4); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_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_memory(a, buff, used)); @@ -2099,7 +2078,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha512_digest_set_non_empty_data) assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA512"); return; diff --git a/contrib/libarchive/libarchive/test/test_write_format_pax.c b/contrib/libarchive/libarchive/test/test_write_format_pax.c index 625a3742c0..a84fb82505 100644 --- a/contrib/libarchive/libarchive/test/test_write_format_pax.c +++ b/contrib/libarchive/libarchive/test/test_write_format_pax.c @@ -133,7 +133,7 @@ DEFINE_TEST(test_write_format_pax) /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* * @@ -248,7 +248,7 @@ DEFINE_TEST(test_write_format_pax) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); } diff --git a/contrib/libarchive/libarchive/test/test_write_format_tar_empty_dirname.c b/contrib/libarchive/libarchive/test/test_write_format_tar_empty_dirname.c new file mode 100644 index 0000000000..7536078799 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_write_format_tar_empty_dirname.c @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2026 Tobias Stoeckmann + * 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" + +static void +test_format(int (*set_format)(struct archive *)) +{ + struct archive *a; + struct archive_entry *entry; + char buff[2048]; + size_t used; + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == set_format(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_set_bytes_per_block(a, 512)); + assertA(0 == archive_write_set_bytes_in_last_block(a, 512)); + assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* Write directory with empty wide character name */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_copy_pathname_w(entry, L""); + archive_entry_set_mode(entry, S_IFDIR | 0755); + archive_entry_set_uid(entry, 0); + archive_entry_set_gid(entry, 0); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); + + /* Close out the archive. */ + archive_entry_free(entry); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Now, read the data back. + */ + 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_memory(a, buff, used)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &entry)); + assertEqualString("", archive_entry_pathname(entry)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_next_header(a, &entry)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + +} + +DEFINE_TEST(test_write_format_tar_empty_dirname) +{ + test_format(archive_write_set_format_gnutar); + test_format(archive_write_set_format_pax); + test_format(archive_write_set_format_ustar); + test_format(archive_write_set_format_v7tar); +} diff --git a/contrib/libarchive/libarchive/test/test_write_format_xar.c b/contrib/libarchive/libarchive/test/test_write_format_xar.c index a3e2577de9..495400a34f 100644 --- a/contrib/libarchive/libarchive/test/test_write_format_xar.c +++ b/contrib/libarchive/libarchive/test/test_write_format_xar.c @@ -44,14 +44,14 @@ test_xar(const char *option) assert((a = archive_write_new()) != NULL); if (archive_write_set_format_xar(a) != ARCHIVE_OK) { skipping("xar is not supported on this platform"); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); return; } assertA(0 == archive_write_add_filter_none(a)); if (option != NULL && archive_write_set_options(a, option) != ARCHIVE_OK) { skipping("option `%s` is not supported on this platform", option); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); return; } @@ -93,13 +93,13 @@ test_xar(const char *option) archive_entry_free(ae); /* - * "dir/file3" has a bunch of attributes and 8 bytes of data. + * "dir/file" has a bunch of attributes and 8 bytes of data. */ assert((ae = archive_entry_new()) != NULL); archive_entry_set_atime(ae, 2, 20); archive_entry_set_ctime(ae, 4, 40); archive_entry_set_mtime(ae, 5, 50); - archive_entry_copy_pathname(ae, "dir/file"); + archive_entry_copy_pathname(ae, "dir/../../dir/file"); archive_entry_set_mode(ae, AE_IFREG | 0755); archive_entry_set_size(ae, 8); assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); @@ -113,7 +113,7 @@ test_xar(const char *option) archive_entry_set_atime(ae, 2, 20); archive_entry_set_ctime(ae, 4, 40); archive_entry_set_mtime(ae, 5, 50); - archive_entry_copy_pathname(ae, "dir/dir2/file4"); + archive_entry_copy_pathname(ae, "dir/..//dir/dir2/file4"); archive_entry_copy_hardlink(ae, "file"); archive_entry_set_mode(ae, AE_IFREG | 0755); archive_entry_set_nlink(ae, 2); @@ -170,7 +170,7 @@ test_xar(const char *option) /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* * @@ -298,7 +298,7 @@ test_xar(const char *option) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); } @@ -351,3 +351,32 @@ DEFINE_TEST(test_write_format_xar) test_xar("compression=xz,compression-level=1"); test_xar("compression=xz,compression-level=9"); } + +DEFINE_TEST(test_write_format_xar_entry_trunc) +{ + struct archive *a; + struct archive_entry *ae; + unsigned char buff[1024]; + size_t used = 0; + + assert((a = archive_write_new()) != NULL); + if (archive_write_set_format_xar(a) != ARCHIVE_OK) { + skipping("xar is not supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "foo"); + archive_entry_set_mode(ae, S_IFREG | 0644); + archive_entry_set_size(ae, 1028); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 3, archive_write_data(a, "foo", 3)); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +} diff --git a/contrib/libarchive/libarchive/test/test_write_format_xar_bugs.c b/contrib/libarchive/libarchive/test/test_write_format_xar_bugs.c new file mode 100644 index 0000000000..2b446b6790 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_write_format_xar_bugs.c @@ -0,0 +1,170 @@ +/*- + * Copyright (c) 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 "test_fuzz_consumer.h" + +#include + +/* + * Replay a fuzzer binary through the XAR writer, matching the protocol + * in fuzzers/custom/fuzz_writer_xar.cc. + */ +static void +replay_xar_writer(const char *refname) +{ + FILE *f; + uint8_t raw[16384]; + size_t rawsize; + struct fuzz_consumer consumer; + uint8_t opts, num_entries; + struct archive *a; + struct archive_entry *entry; + size_t used; + char *out_buf; + int i; + + extract_reference_file(refname); + f = fopen(refname, "rb"); + if (!assert(f != NULL)) + return; + rawsize = fread(raw, 1, sizeof(raw), f); + fclose(f); + if (!assert(rawsize >= 6)) + return; + + fuzz_consumer_init(&consumer, raw, rawsize); + opts = fuzz_consume_byte(&consumer); + num_entries = (fuzz_consume_byte(&consumer) % 5) + 1; + + a = archive_write_new(); + if (!assert(a != NULL)) + return; + + archive_write_set_format_xar(a); + archive_write_add_filter_none(a); + + if (opts & 0x01) + archive_write_set_options(a, "xar:compression=gzip"); + if (opts & 0x02) + archive_write_set_options(a, "xar:compression=bzip2"); + if (opts & 0x04) + archive_write_set_options(a, "xar:checksum=sha1"); + if (opts & 0x08) + archive_write_set_options(a, "xar:checksum=md5"); + + out_buf = (char *)malloc(512 * 1024); + if (!assert(out_buf != NULL)) { + archive_write_free(a); + return; + } + if (archive_write_open_memory(a, out_buf, 512 * 1024, &used) + != ARCHIVE_OK) { + archive_write_free(a); + free(out_buf); + return; + } + + entry = archive_entry_new(); + if (!assert(entry != NULL)) { + archive_write_free(a); + free(out_buf); + return; + } + + for (i = 0; i < num_entries && fuzz_consumer_remaining(&consumer) > 4; + i++) { + const char *path; + uint8_t ftype; + uint16_t raw_mode; + int64_t file_size = 0; + + archive_entry_clear(entry); + + path = fuzz_consume_string(&consumer, 200); + if (path[0] == '\0') + path = "file.txt"; + archive_entry_set_pathname(entry, path); + + ftype = fuzz_consume_byte(&consumer) % 4; + raw_mode = fuzz_consume_u16(&consumer) & 07777; + switch (ftype) { + case 0: archive_entry_set_filetype(entry, AE_IFREG); break; + case 1: archive_entry_set_filetype(entry, AE_IFDIR); break; + case 2: archive_entry_set_filetype(entry, AE_IFLNK); break; + default: archive_entry_set_filetype(entry, AE_IFCHR); break; + } + archive_entry_set_perm(entry, raw_mode); + + archive_entry_set_uname(entry, + fuzz_consume_string(&consumer, 32)); + archive_entry_set_gname(entry, + fuzz_consume_string(&consumer, 32)); + archive_entry_set_uid(entry, fuzz_consume_u32(&consumer)); + archive_entry_set_gid(entry, fuzz_consume_u32(&consumer)); + archive_entry_set_mtime(entry, + fuzz_consume_i64(&consumer), fuzz_consume_u32(&consumer)); + archive_entry_set_atime(entry, + fuzz_consume_i64(&consumer), 0); + archive_entry_set_ctime(entry, + fuzz_consume_i64(&consumer), 0); + + if (ftype == 0) { + file_size = fuzz_consume_byte(&consumer) % 200; + archive_entry_set_size(entry, file_size); + } + + if (ftype == 2) + archive_entry_set_symlink(entry, + fuzz_consume_string(&consumer, 64)); + + if (archive_write_header(a, entry) == ARCHIVE_OK + && file_size > 0) { + size_t write_len = (size_t)file_size; + if (write_len > fuzz_consumer_remaining(&consumer)) + write_len = fuzz_consumer_remaining(&consumer); + if (write_len > 0) { + uint8_t file_data[200]; + fuzz_consume_bytes(&consumer, file_data, + write_len); + archive_write_data(a, file_data, write_len); + } + } + } + + archive_entry_free(entry); + archive_write_close(a); + archive_write_free(a); + free(out_buf); +} + +DEFINE_TEST(test_write_format_xar_strcpy_overlap) +{ + replay_xar_writer("test_write_format_xar_strcpy_overlap.bin"); +} + +DEFINE_TEST(test_write_format_xar_underflow) +{ + replay_xar_writer("test_write_format_xar_underflow.bin"); +} diff --git a/contrib/libarchive/libarchive/test/test_write_format_xar_empty.c b/contrib/libarchive/libarchive/test/test_write_format_xar_empty.c index b3ba6994e9..c774c8d4c9 100644 --- a/contrib/libarchive/libarchive/test/test_write_format_xar_empty.c +++ b/contrib/libarchive/libarchive/test/test_write_format_xar_empty.c @@ -41,7 +41,7 @@ DEFINE_TEST(test_write_format_xar_empty) assert((a = archive_write_new()) != NULL); if (archive_write_set_format_xar(a) != ARCHIVE_OK) { skipping("xar is not supported on this platform"); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); return; } assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); diff --git a/contrib/libarchive/libarchive/test/test_write_format_xar_fflags.c b/contrib/libarchive/libarchive/test/test_write_format_xar_fflags.c new file mode 100644 index 0000000000..e176f379e5 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_write_format_xar_fflags.c @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 2026 Tobias Stoeckmann + * 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_write_format_xar_fflags) +{ + struct archive *a; + struct archive_entry *ae; + char buff[4096]; + size_t used; + + /* Xar format: Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + if (archive_write_set_format_xar(a) != ARCHIVE_OK) { + skipping("xar is not supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 1)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_in_last_block(a, 1)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* Add "file" entry. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFREG | 0644); + archive_entry_set_size(ae, 0); + archive_entry_copy_fflags_text(ae, "sappnd,sappnd,sappnd,very_long_name_but_unknown"); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Now, read the data back. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); + + /* Read "file". */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assert((AE_IFREG | 0644) == archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/contrib/libarchive/libarchive/test/test_write_format_xar_strcpy_overlap.bin.uu b/contrib/libarchive/libarchive/test/test_write_format_xar_strcpy_overlap.bin.uu new file mode 100644 index 0000000000..59850557ce --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_write_format_xar_strcpy_overlap.bin.uu @@ -0,0 +1,6 @@ +begin 644 test_write_format_xar_strcpy_overlap.bin +M=&EI9/____\L261I+&1I+"\N+B\L9"UF+&8L+(0M:2YT9C8L+RXN+R\N+B]T +M+(0M9C8L+RXN+R\N+F8L9BPLA"UF9$G_-BPO+B[__XLN+R\N+B]T+(0M9C8L +.+RXN+R\N:2XO/2]T=/\` +` +end diff --git a/contrib/libarchive/libarchive/test/test_write_format_xar_underflow.bin.uu b/contrib/libarchive/libarchive/test/test_write_format_xar_underflow.bin.uu new file mode 100644 index 0000000000..4f15b55054 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_write_format_xar_underflow.bin.uu @@ -0,0 +1,6 @@ +begin 644 test_write_format_xar_underflow.bin +M=&EI9/____\L261I+&1I+"\N+B\L9"UF+&8L+(0M:2YT9C8L+RXN+R\N+B]T +M+(0M9C8L+RXN+R\N+F8L9BPLA"UF9$G_-BPO+B[__XLN+R\N+B]T+(0M9C8L +.+RXN+R\N:2XO/2]T=/\` +` +end diff --git a/contrib/libarchive/libarchive/test/test_write_format_zip.c b/contrib/libarchive/libarchive/test/test_write_format_zip.c index 583c78c3ac..569b54da5e 100644 --- a/contrib/libarchive/libarchive/test/test_write_format_zip.c +++ b/contrib/libarchive/libarchive/test/test_write_format_zip.c @@ -262,7 +262,7 @@ write_contents(struct archive *a) /* Close out the archive. */ - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); } @@ -550,7 +550,7 @@ verify_contents(struct archive *a, int seeking, int content) /* Verify the end of the archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_write_format_zip_compression_lzmaxz.c b/contrib/libarchive/libarchive/test/test_write_format_zip_compression_lzmaxz.c index c5bb2d659a..f627b1930a 100644 --- a/contrib/libarchive/libarchive/test/test_write_format_zip_compression_lzmaxz.c +++ b/contrib/libarchive/libarchive/test/test_write_format_zip_compression_lzmaxz.c @@ -23,9 +23,10 @@ static const short folder_gid = 40; static time_t now; -static void verify_write_lzma(struct archive *a) +static int verify_write_lzma(struct archive *a) { struct archive_entry *entry; + int r; /* Write entries. */ @@ -38,7 +39,13 @@ static void verify_write_lzma(struct archive *a) archive_entry_set_gid(entry, file_gid); archive_entry_set_mtime(entry, now, 0); archive_entry_set_atime(entry, now + 3, 0); - assertEqualIntA(a, 0, archive_write_header(a, entry)); + r = archive_write_header(a, entry); + if (r == ARCHIVE_FATAL && archive_errno(a) == ENOMEM) { + archive_entry_free(entry); + archive_free(a); + return -1; + } + assertEqualIntA(a, ARCHIVE_OK, r); assertEqualIntA(a, sizeof(file_data1), archive_write_data(a, file_data1, sizeof(file_data1))); assertEqualIntA(a, sizeof(file_data2), archive_write_data(a, file_data2, sizeof(file_data2))); archive_entry_free(entry); @@ -54,6 +61,8 @@ static void verify_write_lzma(struct archive *a) archive_entry_set_ctime(entry, now + 5, 0); assertEqualIntA(a, 0, archive_write_header(a, entry)); archive_entry_free(entry); + + return 0; } static void verify_xz_lzma(const char *buff, size_t used, uint16_t id, @@ -361,7 +370,10 @@ DEFINE_TEST(test_write_format_zip_compression_lzmaxz) assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_in_last_block(a, 1)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); - verify_write_lzma(a); + if (verify_write_lzma(a) < 0) { + skipping("Not enough memory available"); + return; + } /* Close the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); diff --git a/contrib/libarchive/libarchive/test/test_write_format_zip_empty_pathname.c b/contrib/libarchive/libarchive/test/test_write_format_zip_empty_pathname.c new file mode 100644 index 0000000000..423616f4e9 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_write_format_zip_empty_pathname.c @@ -0,0 +1,75 @@ +/*- + * 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" + +/* + * An empty pathname must be rejected (ARCHIVE_FAILED) by the ZIP writer. + * + * write_path() used bitwise & instead of logical && when checking whether + * to append a trailing slash for directory entries. Because & does not + * short-circuit, path[strlen(path)-1] was evaluated even when the entry + * was not a directory — and when the path is empty, strlen(path)-1 wraps + * to SIZE_MAX, producing a one-byte OOB read before the heap buffer. + */ +DEFINE_TEST(test_write_format_zip_empty_pathname) +{ + struct archive *a; + struct archive_entry *ae; + char buf[4096]; + size_t used; + + /* Regular file with empty pathname */ + assert((a = archive_write_new()) != NULL); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buf, sizeof(buf), &used)); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, ""); + archive_entry_set_mode(ae, AE_IFREG | 0644); + archive_entry_set_size(ae, 0); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Directory entry with empty pathname */ + assert((a = archive_write_new()) != NULL); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buf, sizeof(buf), &used)); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, ""); + archive_entry_set_mode(ae, AE_IFDIR | 0755); + archive_entry_set_size(ae, 0); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +} diff --git a/contrib/libarchive/libarchive/test/test_write_format_zip_long_pathname.c b/contrib/libarchive/libarchive/test/test_write_format_zip_long_pathname.c new file mode 100644 index 0000000000..579505decd --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_write_format_zip_long_pathname.c @@ -0,0 +1,114 @@ +/*- + * 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" + +/* + * ZIP stores the filename length in a 16-bit field, so the maximum is + * 65535 bytes. A pathname of 65536 bytes or more must be rejected + * (ARCHIVE_FAILED) rather than silently truncated in the header and + * written past the end of the central-directory segment buffer. + */ +DEFINE_TEST(test_write_format_zip_long_pathname) +{ + struct archive *a; + struct archive_entry *ae; + char *pathname; + char *buf; + size_t used; + /* Enough room for a valid ZIP with a 65535-byte filename. */ + const size_t bufsize = 256 * 1024; + + buf = malloc(bufsize); + assert(buf != NULL); + + /* 65535-byte pathname: exactly the ZIP maximum — must succeed. */ + pathname = malloc(65536); + assert(pathname != NULL); + memset(pathname, 'a', 65535); + pathname[65535] = '\0'; + + assert((a = archive_write_new()) != NULL); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buf, bufsize, &used)); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, pathname); + archive_entry_set_mode(ae, AE_IFREG | 0644); + archive_entry_set_size(ae, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(pathname); + + /* 65536-byte pathname: one byte over the ZIP limit — must be rejected. */ + pathname = malloc(65537); + assert(pathname != NULL); + memset(pathname, 'a', 65536); + pathname[65536] = '\0'; + + assert((a = archive_write_new()) != NULL); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buf, bufsize, &used)); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, pathname); + archive_entry_set_mode(ae, AE_IFREG | 0644); + archive_entry_set_size(ae, 0); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(pathname); + + /* 131072-byte pathname: the OOB-write size from the bug report. */ + pathname = malloc(131073); + assert(pathname != NULL); + memset(pathname, 'a', 131072); + pathname[131072] = '\0'; + + assert((a = archive_write_new()) != NULL); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buf, bufsize, &used)); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, pathname); + archive_entry_set_mode(ae, AE_IFREG | 0644); + archive_entry_set_size(ae, 0); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(pathname); + + free(buf); +} diff --git a/contrib/libarchive/libarchive/test/test_write_format_zip_windows_path.c b/contrib/libarchive/libarchive/test/test_write_format_zip_windows_path.c index c8be482936..ffef2a9077 100644 --- a/contrib/libarchive/libarchive/test/test_write_format_zip_windows_path.c +++ b/contrib/libarchive/libarchive/test/test_write_format_zip_windows_path.c @@ -60,7 +60,7 @@ test_with_hdrcharset(const char *charset) archive_entry_free(ae); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); dumpfile("constructed.zip", buff, used); /* @@ -88,6 +88,7 @@ test_with_hdrcharset(const char *charset) assertEqualInt(2, expected_found); failure("should not find unexpected path in anywhere (charset=%s)", charset); assertEqualInt(0, unexpected_found); + free(buff); } DEFINE_TEST(test_write_format_zip_windows_path) diff --git a/contrib/libarchive/libarchive/test/test_write_format_zip_zip64.c b/contrib/libarchive/libarchive/test/test_write_format_zip_zip64.c index 259cdc47d3..04d120651e 100644 --- a/contrib/libarchive/libarchive/test/test_write_format_zip_zip64.c +++ b/contrib/libarchive/libarchive/test/test_write_format_zip_zip64.c @@ -51,7 +51,7 @@ verify_zip_filesize(uint64_t size, int expected) archive_entry_free(ae); /* Don't actually write 4GB! ;-) */ - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); } DEFINE_TEST(test_write_format_zip_zip64_oversize) diff --git a/contrib/libarchive/libarchive/test/test_write_read_format_zip.c b/contrib/libarchive/libarchive/test/test_write_read_format_zip.c index 828b092c7b..1be282f673 100644 --- a/contrib/libarchive/libarchive/test/test_write_read_format_zip.c +++ b/contrib/libarchive/libarchive/test/test_write_read_format_zip.c @@ -259,7 +259,7 @@ write_contents(struct archive *a) /* Close out the archive. */ - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); } @@ -568,7 +568,7 @@ verify_contents(struct archive *a, int seeking, int improved_streaming) /* Verify the end of the archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/xxhash.c b/contrib/libarchive/libarchive/xxhash.c index beacd23912..37dc6ffd67 100644 --- a/contrib/libarchive/libarchive/xxhash.c +++ b/contrib/libarchive/libarchive/xxhash.c @@ -361,6 +361,8 @@ static void* XXH32_init (U32 seed) { void* state = XXH_malloc (sizeof(struct XXH_state32_t)); + if (state == NULL) + return NULL; XXH32_resetState(state, seed); return state; } diff --git a/contrib/libarchive/libarchive_fe/lafe_fnmatch.c b/contrib/libarchive/libarchive_fe/lafe_fnmatch.c new file mode 100644 index 0000000000..be10fa5b82 --- /dev/null +++ b/contrib/libarchive/libarchive_fe/lafe_fnmatch.c @@ -0,0 +1,317 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * Copyright (c) 2011 The FreeBSD Foundation + * + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 "lafe_platform.h" + +#ifndef HAVE_FNMATCH +/* + * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. + * Compares a filename or pathname to a pattern. + */ + +/* + * Some notes on multibyte character support: + * 1. Patterns with illegal byte sequences match nothing. + * 2. Illegal byte sequences in the "string" argument are handled by treating + * them as single-byte characters with a value of the first byte of the + * sequence cast to wchar_t. + * 3. Multibyte conversion state objects (mbstate_t) are passed around and + * used for most, but not all, conversions. Further work will be required + * to support state-dependent encodings. + */ + +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_WCHAR_H +#include +#endif +#ifdef HAVE_WCTYPE_H +#include +#endif + +#include "lafe_fnmatch.h" + +#define EOS '\0' + +#define RANGE_MATCH 1 +#define RANGE_NOMATCH 0 +#define RANGE_ERROR (-1) + +static int rangematch(const char *, wchar_t, int, const char **, mbstate_t *); +static int fnmatch1(const char *, const char *, const char *, int, mbstate_t, + mbstate_t); + +int +fnmatch(const char *pattern, const char *string, int flags) +{ + static const mbstate_t initial; + + return (fnmatch1(pattern, string, string, flags, initial, initial)); +} + +static int +fnmatch1(const char *pattern, const char *string, const char *stringstart, + int flags, mbstate_t patmbs, mbstate_t strmbs) +{ + const char *bt_pattern, *bt_string; + mbstate_t bt_patmbs, bt_strmbs; + const char *newp; + char c; + wchar_t pc, sc; + size_t pclen, sclen; + + bt_pattern = bt_string = NULL; + for (;;) { + pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, &patmbs); + if (pclen == (size_t)-1 || pclen == (size_t)-2) + return (FNM_NOMATCH); + pattern += pclen; + sclen = mbrtowc(&sc, string, MB_LEN_MAX, &strmbs); + if (sclen == (size_t)-1 || sclen == (size_t)-2) { + sc = (unsigned char)*string; + sclen = 1; + memset(&strmbs, 0, sizeof(strmbs)); + } + switch (pc) { + case EOS: + if ((flags & FNM_LEADING_DIR) && sc == '/') + return (0); + if (sc == EOS) + return (0); + goto backtrack; + case '?': + if (sc == EOS) + return (FNM_NOMATCH); + if (sc == '/' && (flags & FNM_PATHNAME)) + goto backtrack; + if (sc == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + goto backtrack; + string += sclen; + break; + case '*': + c = *pattern; + /* Collapse multiple stars. */ + while (c == '*') + c = *++pattern; + + if (sc == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + goto backtrack; + + /* Optimize for pattern with * at end or before /. */ + if (c == EOS) + if (flags & FNM_PATHNAME) + return ((flags & FNM_LEADING_DIR) || + strchr(string, '/') == NULL ? + 0 : FNM_NOMATCH); + else + return (0); + else if (c == '/' && flags & FNM_PATHNAME) { + if ((string = strchr(string, '/')) == NULL) + return (FNM_NOMATCH); + break; + } + + /* + * First try the shortest match for the '*' that + * could work. We can forget any earlier '*' since + * there is no way having it match more characters + * can help us, given that we are already here. + */ + bt_pattern = pattern, bt_patmbs = patmbs; + bt_string = string, bt_strmbs = strmbs; + break; + case '[': + if (sc == EOS) + return (FNM_NOMATCH); + if (sc == '/' && (flags & FNM_PATHNAME)) + goto backtrack; + if (sc == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + goto backtrack; + + switch (rangematch(pattern, sc, flags, &newp, + &patmbs)) { + case RANGE_ERROR: + goto norm; + case RANGE_MATCH: + pattern = newp; + break; + case RANGE_NOMATCH: + goto backtrack; + } + string += sclen; + break; + case '\\': + if (!(flags & FNM_NOESCAPE)) { + pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, + &patmbs); + if (pclen == 0 || pclen == (size_t)-1 || + pclen == (size_t)-2) + return (FNM_NOMATCH); + pattern += pclen; + } + /* FALLTHROUGH */ + default: + norm: + string += sclen; + if (pc == sc) + ; + else if ((flags & FNM_CASEFOLD) && + (towlower(pc) == towlower(sc))) + ; + else { + backtrack: + /* + * If we have a mismatch (other than hitting + * the end of the string), go back to the last + * '*' seen and have it match one additional + * character. + */ + if (bt_pattern == NULL) + return (FNM_NOMATCH); + sclen = mbrtowc(&sc, bt_string, MB_LEN_MAX, + &bt_strmbs); + if (sclen == (size_t)-1 || + sclen == (size_t)-2) { + sc = (unsigned char)*bt_string; + sclen = 1; + memset(&bt_strmbs, 0, + sizeof(bt_strmbs)); + } + if (sc == EOS) + return (FNM_NOMATCH); + if (sc == '/' && flags & FNM_PATHNAME) + return (FNM_NOMATCH); + bt_string += sclen; + pattern = bt_pattern, patmbs = bt_patmbs; + string = bt_string, strmbs = bt_strmbs; + } + break; + } + } + /* NOTREACHED */ +} + +static int +rangematch(const char *pattern, wchar_t test, int flags, const char **newp, + mbstate_t *patmbs) +{ + int negate, ok; + wchar_t s1[2], s2[2], t[2]; + size_t pclen; + const char *origpat; + + s1[1] = L'\0'; + s2[1] = L'\0'; + + t[0] = test; + t[1] = L'\0'; + + /* + * A bracket expression starting with an unquoted circumflex + * character produces unspecified results (IEEE 1003.2-1992, + * 3.13.2). This implementation treats it like '!', for + * consistency with the regular expression syntax. + * J.T. Conklin (conklin@ngai.kaleida.com) + */ + if ((negate = (*pattern == '!' || *pattern == '^'))) + ++pattern; + + if (flags & FNM_CASEFOLD) + t[0] = towlower(t[0]); + + /* + * A right bracket shall lose its special meaning and represent + * itself in a bracket expression if it occurs first in the list. + * -- POSIX.2 2.8.3.2 + */ + ok = 0; + origpat = pattern; + for (;;) { + if (*pattern == ']' && pattern > origpat) { + pattern++; + break; + } else if (*pattern == '\0') { + return (RANGE_ERROR); + } else if (*pattern == '/' && (flags & FNM_PATHNAME)) { + return (RANGE_NOMATCH); + } else if (*pattern == '\\' && !(flags & FNM_NOESCAPE)) + pattern++; + pclen = mbrtowc(s1, pattern, MB_LEN_MAX, patmbs); + if (pclen == (size_t)-1 || pclen == (size_t)-2) + return (RANGE_NOMATCH); + pattern += pclen; + + if (flags & FNM_CASEFOLD) + s1[0] = towlower(s1[0]); + + if (*pattern == '-' && *(pattern + 1) != EOS && + *(pattern + 1) != ']') { + if (*++pattern == '\\' && !(flags & FNM_NOESCAPE)) + if (*pattern != EOS) + pattern++; + pclen = mbrtowc(s2, pattern, MB_LEN_MAX, patmbs); + if (pclen == (size_t)-1 || pclen == (size_t)-2) + return (RANGE_NOMATCH); + pattern += pclen; + if (s2[0] == EOS) + return (RANGE_ERROR); + + if (flags & FNM_CASEFOLD) + s2[0] = towlower(s2[0]); + + if (wcscoll(s1, t) && wcscoll(t, s2) <= 0) + ok = 1; + } else if (s1[0] == t[0]) + ok = 1; + } + + *newp = pattern; + return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH); +} +#endif diff --git a/contrib/libarchive/libarchive_fe/lafe_fnmatch.h b/contrib/libarchive/libarchive_fe/lafe_fnmatch.h new file mode 100644 index 0000000000..e599056a7f --- /dev/null +++ b/contrib/libarchive/libarchive_fe/lafe_fnmatch.h @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * + * $FreeBSD$ + * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef LAFE_FNMATCH_H_INCLUDED +#define LAFE_FNMATCH_H_INCLUDED + +#include "lafe_platform.h" + +#ifndef HAVE_FNMATCH + +#define FNM_NOMATCH 1 /* Match failed. */ + +#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ +#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ +#define FNM_PERIOD 0x04 /* Period must be matched by period. */ + +#define FNM_NOSYS (-1) /* Reserved. */ + +#define FNM_LEADING_DIR 0x08 /* Ignore / after Imatch. */ +#define FNM_CASEFOLD 0x10 /* Case insensitive search. */ +#define FNM_IGNORECASE FNM_CASEFOLD +#define FNM_FILE_NAME FNM_PATHNAME + +int fnmatch(const char *pattern, const char *string, int flags); +#endif /* !HAVE_FNMATCH */ + +#endif /* !LAFE_FNMATCH_H_INCLUDED */ diff --git a/contrib/libarchive/tar/bsdtar.h b/contrib/libarchive/tar/bsdtar.h index 782d36d6f7..692b800bf8 100644 --- a/contrib/libarchive/tar/bsdtar.h +++ b/contrib/libarchive/tar/bsdtar.h @@ -67,7 +67,7 @@ struct bsdtar { /* Miscellaneous state information */ int argc; char **argv; - const char *argument; + char *argument; size_t gs_width; /* For 'list_item' in read.c */ size_t u_width; /* for 'list_item' in read.c */ uid_t user_uid; /* UID running this program */ diff --git a/contrib/libarchive/tar/read.c b/contrib/libarchive/tar/read.c index 4acbf6b2a9..57ae5200cf 100644 --- a/contrib/libarchive/tar/read.c +++ b/contrib/libarchive/tar/read.c @@ -234,9 +234,14 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer) for (;;) { /* Support --fast-read option */ const char *p; - if ((bsdtar->flags & OPTFLAG_FAST_READ) && - archive_match_path_unmatched_inclusions(bsdtar->matching) == 0) - break; + + if (bsdtar->flags & OPTFLAG_FAST_READ) { + r = archive_match_path_unmatched_inclusions(bsdtar->matching); + if (r < 0) + lafe_errc(1, 0, "%s", archive_error_string(a)); + if (!r) + break; + } r = archive_read_next_header(a, &entry); progress_data.entry = entry; @@ -282,7 +287,11 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer) * rewrite, there would be no way to exclude foo1/bar * while allowing foo2/bar.) */ - if (archive_match_excluded(bsdtar->matching, entry)) + r = archive_match_excluded(bsdtar->matching, entry); + if (r == ARCHIVE_FATAL) + lafe_errc(1, 0, "%s", + archive_error_string(bsdtar->matching)); + if (r) continue; /* Excluded by a pattern test. */ if (mode == 't') { @@ -395,7 +404,7 @@ unmatched_inclusions_warn(struct archive *matching, const char *msg) matching, &p)) == ARCHIVE_OK) lafe_warnc(0, "%s: %s", p, msg); if (r == ARCHIVE_FATAL) - lafe_errc(1, errno, "Out of memory"); + lafe_errc(1, 0, "%s", archive_error_string(matching)); return (archive_match_path_unmatched_inclusions(matching)); } diff --git a/contrib/libarchive/tar/subst.c b/contrib/libarchive/tar/subst.c index 53497ad0d1..6acf8cd15f 100644 --- a/contrib/libarchive/tar/subst.c +++ b/contrib/libarchive/tar/subst.c @@ -75,11 +75,14 @@ add_substitution(struct bsdtar *bsdtar, const char *rule_text) subst->last_rule->next = rule; subst->last_rule = rule; - if (*rule_text == '\0') + const char delim = *rule_text; + if (delim == '\0') lafe_errc(1, 0, "Empty replacement string"); - end_pattern = strchr(rule_text + 1, *rule_text); + end_pattern = strchr(rule_text + 1, delim); if (end_pattern == NULL) - lafe_errc(1, 0, "Invalid replacement string"); + lafe_errc(1, 0, "Invalid replacement string \"%s\": " + "missing closing delimiter '%c' after pattern", + rule_text, delim); pattern = malloc(end_pattern - rule_text); if (pattern == NULL) @@ -95,9 +98,11 @@ add_substitution(struct bsdtar *bsdtar, const char *rule_text) free(pattern); start_subst = end_pattern + 1; - end_pattern = strchr(start_subst, *rule_text); + end_pattern = strchr(start_subst, delim); if (end_pattern == NULL) - lafe_errc(1, 0, "Invalid replacement string"); + lafe_errc(1, 0, "Invalid replacement string \"%s\": " + "missing closing delimiter '%c' after replacement", + rule_text, delim); rule->result = malloc(end_pattern - start_subst + 1); if (rule->result == NULL) diff --git a/contrib/libarchive/tar/test/test_option_P_upper.c b/contrib/libarchive/tar/test/test_option_P_upper.c index 953d9f5899..69810a3043 100644 --- a/contrib/libarchive/tar/test/test_option_P_upper.c +++ b/contrib/libarchive/tar/test/test_option_P_upper.c @@ -79,4 +79,5 @@ DEFINE_TEST(test_extract_tar_absolute_paths) #else assertFileNotExists(temp_absolute_file_name + 1); // Skip the slash. #endif + free(temp_absolute_file_name); } diff --git a/contrib/libarchive/tar/test/test_option_mtime.c b/contrib/libarchive/tar/test/test_option_mtime.c index 75cdb8390b..8e337a46da 100644 --- a/contrib/libarchive/tar/test/test_option_mtime.c +++ b/contrib/libarchive/tar/test/test_option_mtime.c @@ -6,23 +6,6 @@ */ #include "test.h" -#if defined(_WIN32) && !defined(__CYGWIN__) -/* system() on Windows runs its arguments through CMD.EXE, which has - * notoriously unfriendly quoting rules. The current best documented way around - * them is to wrap your *entire commandline* in sacrificial quotes. - * - * See CMD.EXE /? for more information. Excerpted here: - * | Otherwise, old behavior is to see if the first character is - * | a quote character and if so, strip the leading character and - * | remove the last quote character on the command line, preserving - * | any text after the last quote character. - * - * Since this test makes heavy use of systemf() with quoted arguments inside - * the commandline, this macro is unfortunately an easier workaround. - */ -#define systemf(command, ...) systemf("\"" command "\"", __VA_ARGS__) -#endif - DEFINE_TEST(test_option_mtime) { /* Create three files with different mtimes. */ diff --git a/contrib/libarchive/tar/test/test_option_s.c b/contrib/libarchive/tar/test/test_option_s.c index 00753b99be..16e8710877 100644 --- a/contrib/libarchive/tar/test/test_option_s.c +++ b/contrib/libarchive/tar/test/test_option_s.c @@ -46,9 +46,9 @@ DEFINE_TEST(test_option_s) systemf("%s -xf test1_3.tar -C test1", testprog); assertFileContents("foo", 3, "test1/in/d1/f##"); // For the 0-length pattern check, remember that "test1/" isn't part of the string affected by the regexp - systemf("%s -cf test1_4.tar -s /f*/\\<~\\>/g in/d1/foo", testprog); + systemf("%s -cf test1_4.tar -s /f*/[~]/g in/d1/foo", testprog); systemf("%s -xf test1_4.tar -C test1", testprog); - assertFileContents("foo", 3, "test1/<>i<>n<>/<>d<>1<>/<>o<>o<>"); + assertFileContents("foo", 3, "test1/[]i[]n[]/[]d[]1[]/[f][]o[]o[]"); /* * Test 2: Basic substitution when extracting archive. */ diff --git a/contrib/libarchive/tar/util.c b/contrib/libarchive/tar/util.c index 6b21e8aeff..3fb0f9b020 100644 --- a/contrib/libarchive/tar/util.c +++ b/contrib/libarchive/tar/util.c @@ -746,12 +746,13 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry) snprintf(tmp, sizeof(tmp), "%lu,%lu", (unsigned long)archive_entry_rdevmajor(entry), (unsigned long)archive_entry_rdevminor(entry)); + p = tmp; } else { - strcpy(tmp, tar_i64toa(archive_entry_size(entry))); + p = tar_i64toa(archive_entry_size(entry)); } - if (w + strlen(tmp) >= bsdtar->gs_width) - bsdtar->gs_width = w+strlen(tmp)+1; - fprintf(out, "%*s", (int)(bsdtar->gs_width - w), tmp); + if (w + strlen(p) >= bsdtar->gs_width) + bsdtar->gs_width = w + strlen(p) + 1; + fprintf(out, "%*s", (int)(bsdtar->gs_width - w), p); /* Format the time using 'ls -l' conventions. */ tim = archive_entry_mtime(entry); @@ -772,11 +773,13 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry) #else ltime = localtime(&tim); #endif - if (ltime) + if (ltime) { sw = strftime(tmp, sizeof(tmp), fmt, ltime); + p = tmp; + } if (!ltime || !sw) - sprintf(tmp, "-- -- ----"); - fprintf(out, " %s ", tmp); + p = "-- -- ----"; + fprintf(out, " %s ", p); safe_fprintf(out, "%s", archive_entry_pathname(entry)); /* Extra information for links. */ diff --git a/contrib/libarchive/tar/write.c b/contrib/libarchive/tar/write.c index abff3831bc..302df020ad 100644 --- a/contrib/libarchive/tar/write.c +++ b/contrib/libarchive/tar/write.c @@ -699,7 +699,18 @@ append_archive(struct bsdtar *bsdtar, struct archive *a, struct archive *ina) int e; while (ARCHIVE_OK == (e = archive_read_next_header(ina, &in_entry))) { - if (archive_match_excluded(bsdtar->matching, in_entry)) + e = archive_match_excluded(bsdtar->matching, in_entry); + if (e < 0) { + if (!bsdtar->verbose) + lafe_errc(1, 0, "%s", + archive_error_string(bsdtar->matching)); + else { + fprintf(stderr, ": %s", + archive_error_string(bsdtar->matching)); + exit(1); + } + } + if (e) continue; if(edit_pathname(bsdtar, in_entry)) continue; diff --git a/contrib/libarchive/test_utils/test_main.c b/contrib/libarchive/test_utils/test_main.c index f7364c0ba4..f5de428f28 100644 --- a/contrib/libarchive/test_utils/test_main.c +++ b/contrib/libarchive/test_utils/test_main.c @@ -3056,11 +3056,41 @@ systemf(const char *fmt, ...) pid_t pid; #endif va_list ap; + size_t off = 0, avail = sizeof(buff); int r; +#if defined(_WIN32) && !defined(__CYGWIN__) + /* system() on Windows runs its arguments through CMD.EXE, which has + * notoriously unfriendly quoting rules. The current best documented way around + * them is to wrap your *entire commandline* in sacrificial quotes. + * + * See CMD.EXE /? for more information. Excerpted here: + * | Otherwise, old behavior is to see if the first character is + * | a quote character and if so, strip the leading character and + * | remove the last quote character on the command line, preserving + * | any text after the last quote character. + * + * Since these tests often make use of systemf() with quoted arguments inside + * the commandline, wrap every formatted commandline in quotes. + */ + avail -= 2; + off++; + buff[0] = '"'; +#endif + va_start(ap, fmt); - vsnprintf(buff, sizeof(buff), fmt, ap); + r = vsnprintf(buff + off, avail, fmt, ap); va_end(ap); + + if (r < 0 || (size_t)r > avail) { + return (-1); + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + buff[off + r] = '"'; + buff[off + r + 1] = '\0'; +#endif + if (verbosity > VERBOSITY_FULL) logprintf("Cmd: %s\n", buff); #if USE_POSIX_SPAWN @@ -3747,7 +3777,7 @@ usage(const char *program) printf("Usage: %s [options] ...\n", program); printf("Default is to run all tests.\n"); - printf("Otherwise, specify the numbers of the tests you wish to run.\n"); + printf("Otherwise, specify tests by name or number.\n"); printf("Options:\n"); printf(" -d Dump core after any failure, for debugging.\n"); printf(" -k Keep all temp files.\n"); diff --git a/contrib/libarchive/test_utils/test_utils.c b/contrib/libarchive/test_utils/test_utils.c index be717f4ccf..a24b0272cb 100644 --- a/contrib/libarchive/test_utils/test_utils.c +++ b/contrib/libarchive/test_utils/test_utils.c @@ -149,7 +149,7 @@ unsigned int i4le(const void* p_) { const char *p = p_; - return (i2le(p) | (i2le(p + 2) << 16)); + return (i2le(p) | ((unsigned int)i2le(p + 2) << 16)); } unsigned long long i8le(const void* p_) diff --git a/contrib/libarchive/unzip/bsdunzip.c b/contrib/libarchive/unzip/bsdunzip.c index aa849568ba..454d7f7bad 100644 --- a/contrib/libarchive/unzip/bsdunzip.c +++ b/contrib/libarchive/unzip/bsdunzip.c @@ -9,6 +9,7 @@ #include "bsdunzip_platform.h" #include "la_queue.h" +#include "lafe_fnmatch.h" #include "lafe_getline.h" #ifdef HAVE_SYS_STAT_H #include @@ -51,9 +52,6 @@ #include #endif #endif -#ifdef HAVE_GETOPT_OPTRESET -#include -#endif #include "bsdunzip.h" #include "passphrase.h" @@ -307,12 +305,8 @@ match_pattern(struct pattern_list *list, const char *str) struct pattern *entry; STAILQ_FOREACH(entry, list, link) { -#ifdef HAVE_FNMATCH if (fnmatch(entry->pattern, str, C_opt ? FNM_CASEFOLD : 0) == 0) return (1); -#else -#error "Unsupported platform: fnmatch() is required" -#endif } return (0); } diff --git a/contrib/libarchive/unzip/test/test_P_encryption.c b/contrib/libarchive/unzip/test/test_P_encryption.c index ed08a06881..ed789ec132 100644 --- a/contrib/libarchive/unzip/test/test_P_encryption.c +++ b/contrib/libarchive/unzip/test/test_P_encryption.c @@ -9,6 +9,7 @@ /* Test P arg - password protected */ DEFINE_TEST(test_P_encryption) { +#ifdef HAVE_LIBZ const char *reffile = "test_encrypted.zip"; int r; @@ -23,4 +24,7 @@ DEFINE_TEST(test_P_encryption) assertTextFileContents("plaintext\n", "encrypted/file.txt"); } +#else + skipping("zlib not available"); +#endif }