diff --git a/libarchive-clib/c/archive.h b/libarchive-clib/c/archive.h index a9d34be..de472a1 100644 --- a/libarchive-clib/c/archive.h +++ b/libarchive-clib/c/archive.h @@ -34,7 +34,7 @@ * assert that ARCHIVE_VERSION_NUMBER >= 2012108. */ /* Note: Compiler will complain if this does not match archive_entry.h! */ -#define ARCHIVE_VERSION_NUMBER 3008005 +#define ARCHIVE_VERSION_NUMBER 3008006 #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.5" +#define ARCHIVE_VERSION_ONLY_STRING "3.8.6" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); diff --git a/libarchive-clib/c/archive_acl.c b/libarchive-clib/c/archive_acl.c index 362e330..ab60183 100644 --- a/libarchive-clib/c/archive_acl.c +++ b/libarchive-clib/c/archive_acl.c @@ -1256,8 +1256,12 @@ archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text, tag = 0; s = field[n].start; - st = field[n].start + 1; len = field[n].end - field[n].start; + if (len == 0) { + ret = ARCHIVE_WARN; + continue; + } + st = s + 1; switch (*s) { case L'u': diff --git a/libarchive-clib/c/archive_cryptor_private.h b/libarchive-clib/c/archive_cryptor_private.h index 272f2f8..1f9298f 100644 --- a/libarchive-clib/c/archive_cryptor_private.h +++ b/libarchive-clib/c/archive_cryptor_private.h @@ -109,6 +109,10 @@ typedef struct { #include #define ARCHIVE_CRYPTOR_USE_NETTLE 1 +#ifndef AES_MAX_KEY_SIZE +#define AES_MAX_KEY_SIZE AES256_KEY_SIZE +#endif + typedef struct { #if NETTLE_VERSION_MAJOR < 3 struct aes_ctx ctx; diff --git a/libarchive-clib/c/archive_entry.h b/libarchive-clib/c/archive_entry.h index b434356..f7f1c52 100644 --- a/libarchive-clib/c/archive_entry.h +++ b/libarchive-clib/c/archive_entry.h @@ -28,7 +28,7 @@ #define ARCHIVE_ENTRY_H_INCLUDED /* Note: Compiler will complain if this does not match archive.h! */ -#define ARCHIVE_VERSION_NUMBER 3008005 +#define ARCHIVE_VERSION_NUMBER 3008006 /* * Note: archive_entry.h is for use outside of libarchive; the diff --git a/libarchive-clib/c/archive_hmac.c b/libarchive-clib/c/archive_hmac.c index 210cca7..458092f 100644 --- a/libarchive-clib/c/archive_hmac.c +++ b/libarchive-clib/c/archive_hmac.c @@ -198,6 +198,7 @@ static void __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) } #elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H) +#include static int __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) @@ -216,7 +217,12 @@ __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, static void __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) { +#if NETTLE_VERSION_MAJOR < 4 hmac_sha1_digest(ctx, (unsigned)*out_len, out); +#else + hmac_sha1_digest(ctx, out); + *out_len = SHA1_DIGEST_SIZE; +#endif } static void diff --git a/libarchive-clib/c/archive_read_open_filename.c b/libarchive-clib/c/archive_read_open_filename.c index a910eef..9ec1e6c 100644 --- a/libarchive-clib/c/archive_read_open_filename.c +++ b/libarchive-clib/c/archive_read_open_filename.c @@ -122,13 +122,14 @@ archive_read_open_filenames(struct archive *a, const char **filenames, archive_clear_error(a); do { + size_t len; if (filename == NULL) filename = ""; - mine = calloc(1, - sizeof(*mine) + strlen(filename)); + len = strlen(filename); + mine = calloc(1, sizeof(*mine) + len); if (mine == NULL) goto no_memory; - strcpy(mine->filename.m, filename); + memcpy(mine->filename.m, filename, len + 1); mine->block_size = block_size; mine->fd = -1; mine->buffer = NULL; diff --git a/libarchive-clib/c/archive_read_support_filter_program.c b/libarchive-clib/c/archive_read_support_filter_program.c index 2c8e453..9f187f8 100644 --- a/libarchive-clib/c/archive_read_support_filter_program.c +++ b/libarchive-clib/c/archive_read_support_filter_program.c @@ -149,6 +149,8 @@ archive_read_support_filter_program_signature(struct archive *_a, if (signature != NULL && signature_len > 0) { state->signature_len = signature_len; state->signature = malloc(signature_len); + if (state->signature == NULL) + goto memerr; memcpy(state->signature, signature, signature_len); } diff --git a/libarchive-clib/c/archive_read_support_format_7zip.c b/libarchive-clib/c/archive_read_support_format_7zip.c index 330d551..67c0305 100644 --- a/libarchive-clib/c/archive_read_support_format_7zip.c +++ b/libarchive-clib/c/archive_read_support_format_7zip.c @@ -34,6 +34,9 @@ #ifdef HAVE_STDLIB_H #include #endif +#ifdef HAVE_LIMITS_H +#include +#endif #ifdef HAVE_BZLIB_H #include #endif @@ -80,7 +83,7 @@ /* * ELF format */ -#define ELF_HDR_MIN_LEN 0x3f +#define ELF_HDR_MIN_LEN 0x40 /* sizeof(Elf64_Ehdr) */ #define ELF_HDR_EI_CLASS_OFFSET 0x04 #define ELF_HDR_EI_DATA_OFFSET 0x05 @@ -855,13 +858,18 @@ find_elf_data_sec(struct archive_read *a) while (e_shnum > 0) { name_offset = (*dec32)(h + sec_tbl_offset); if (name_offset == data_sym_offset) { + uint64_t sel_offset; + if (format_64) { - min_addr = (*dec64)( + sel_offset = (*dec64)( h + sec_tbl_offset + 0x18); } else { - min_addr = (*dec32)( + sel_offset = (*dec32)( h + sec_tbl_offset + 0x10); } + if (sel_offset > SSIZE_MAX) + break; + min_addr = (ssize_t)sel_offset; break; } sec_tbl_offset += e_shentsize; diff --git a/libarchive-clib/c/archive_read_support_format_cab.c b/libarchive-clib/c/archive_read_support_format_cab.c index 63755ef..c4a67a7 100644 --- a/libarchive-clib/c/archive_read_support_format_cab.c +++ b/libarchive-clib/c/archive_read_support_format_cab.c @@ -383,8 +383,10 @@ archive_read_support_format_cab(struct archive *_a) NULL, NULL); - if (r != ARCHIVE_OK) + if (r != ARCHIVE_OK) { + archive_wstring_free(&cab->ws); free(cab); + } return (ARCHIVE_OK); } diff --git a/libarchive-clib/c/archive_read_support_format_lha.c b/libarchive-clib/c/archive_read_support_format_lha.c index cf6a147..ccdf490 100644 --- a/libarchive-clib/c/archive_read_support_format_lha.c +++ b/libarchive-clib/c/archive_read_support_format_lha.c @@ -1101,6 +1101,13 @@ lha_read_file_header_3(struct archive_read *a, struct lha *lha) header_crc = lha_crc16(0, p, H3_FIXED_SIZE); __archive_read_consume(a, H3_FIXED_SIZE); + /* Reject rediculously large header */ + if (lha->header_size > 65536) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "LHa header size too large"); + return (ARCHIVE_FATAL); + } + /* Read extended headers */ err = lha_read_file_extended_header(a, lha, &header_crc, 4, lha->header_size - H3_FIXED_SIZE, &extdsize); diff --git a/libarchive-clib/c/archive_read_support_format_mtree.c b/libarchive-clib/c/archive_read_support_format_mtree.c index 10c07b0..4a5a49c 100644 --- a/libarchive-clib/c/archive_read_support_format_mtree.c +++ b/libarchive-clib/c/archive_read_support_format_mtree.c @@ -300,7 +300,12 @@ cleanup(struct archive_read *a) struct mtree_entry *p, *q; mtree = (struct mtree *)(a->format->data); - + + /* Close any dangling file descriptor before freeing */ + if (mtree->fd >= 0) { + close(mtree->fd); + mtree->fd = -1; + } p = mtree->entries; while (p != NULL) { q = p->next; diff --git a/libarchive-clib/c/archive_read_support_format_rar5.c b/libarchive-clib/c/archive_read_support_format_rar5.c index 17e501e..778537b 100644 --- a/libarchive-clib/c/archive_read_support_format_rar5.c +++ b/libarchive-clib/c/archive_read_support_format_rar5.c @@ -375,6 +375,7 @@ static int rar5_read_data_skip(struct archive_read *a); static int push_data_ready(struct archive_read* a, struct rar5* rar, const uint8_t* buf, size_t size, int64_t offset); static void clear_data_ready_stack(struct rar5* rar); +static void rar5_deinit(struct rar5* rar); /* CDE_xxx = Circular Double Ended (Queue) return values. */ enum CDE_RETURN_VALUES { @@ -429,8 +430,7 @@ static int cdeque_front(struct cdeque* d, void** value) { return CDE_OUT_OF_BOUNDS; } -/* Pushes a new element into the end of this circular deque object. If current - * size will exceed capacity, the oldest element will be overwritten. */ +/* Pushes a new element into the end of this circular deque object. */ static int cdeque_push_back(struct cdeque* d, void* item) { if(d == NULL) return CDE_PARAM; @@ -554,7 +554,11 @@ static struct filter_info* add_new_filter(struct rar5* rar) { return NULL; } - cdeque_push_back(&rar->cstate.filters, cdeque_filter(f)); + if (CDE_OK != cdeque_push_back(&rar->cstate.filters, cdeque_filter(f))) { + free(f); + return NULL; + } + return f; } @@ -3040,7 +3044,9 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) { if(block_length < 4 || block_length > 0x400000 || filter_type > FILTER_ARM || - !is_valid_filter_block_start(rar, block_start)) + !is_valid_filter_block_start(rar, block_start) || + (rar->cstate.window_size > 0 && + (ssize_t)block_length > rar->cstate.window_size >> 1)) { archive_set_error(&ar->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid filter encountered"); @@ -4328,7 +4334,7 @@ static int rar5_cleanup(struct archive_read *a) { free(rar->vol.push_buf); free_filters(rar); - cdeque_free(&rar->cstate.filters); + rar5_deinit(rar); free(rar); a->format->data = NULL; @@ -4353,6 +4359,7 @@ static int rar5_has_encrypted_entries(struct archive_read *_a) { return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; } +/* Must match deallocations in rar5_deinit */ static int rar5_init(struct rar5* rar) { memset(rar, 0, sizeof(struct rar5)); @@ -4368,6 +4375,11 @@ static int rar5_init(struct rar5* rar) { return ARCHIVE_OK; } +/* Must match allocations in rar5_init */ +static void rar5_deinit(struct rar5* rar) { + cdeque_free(&rar->cstate.filters); +} + int archive_read_support_format_rar5(struct archive *_a) { struct archive_read* ar; int ret; @@ -4404,8 +4416,9 @@ int archive_read_support_format_rar5(struct archive *_a) { rar5_has_encrypted_entries); if(ret != ARCHIVE_OK) { - (void) rar5_cleanup(ar); + rar5_deinit(rar); + free(rar); } - return ret; + return ARCHIVE_OK; } diff --git a/libarchive-clib/c/archive_string.c b/libarchive-clib/c/archive_string.c index a776dc8..a4955d4 100644 --- a/libarchive-clib/c/archive_string.c +++ b/libarchive-clib/c/archive_string.c @@ -772,7 +772,7 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as, int r; defchar_used = 0; - if (to_cp == CP_UTF8 || sc == NULL) + if (to_cp == CP_UTF8) dp = NULL; else dp = &defchar_used; @@ -1873,6 +1873,9 @@ archive_string_conversion_free(struct archive *a) const char * archive_string_conversion_charset_name(struct archive_string_conv *sc) { + if (sc == NULL) { + return "current locale"; + } if (sc->flag & SCONV_TO_CHARSET) return (sc->to_charset); else @@ -4123,7 +4126,12 @@ archive_mstring_get_mbs_l(struct archive *a, struct archive_mstring *aes, * character-set. */ if ((aes->aes_set & AES_SET_MBS) == 0) { const char *pm; /* unused */ - archive_mstring_get_mbs(a, aes, &pm); /* ignore errors, we'll handle it later */ + if (archive_mstring_get_mbs(a, aes, &pm) != 0) { + /* We have another form, but failed to convert it to + * the native locale. Transitively, we've failed to + * convert it to the specified character set. */ + ret = -1; + } } /* If we already have an MBS form, use it to be translated to * specified character-set. */ @@ -4141,6 +4149,8 @@ archive_mstring_get_mbs_l(struct archive *a, struct archive_mstring *aes, if (length != NULL) *length = aes->aes_mbs_in_locale.length; } else { + /* Either we have no string in any form, + * or conversion failed and set 'ret != 0'. */ *p = NULL; if (length != NULL) *length = 0; diff --git a/libarchive-clib/c/archive_write_disk_posix.c b/libarchive-clib/c/archive_write_disk_posix.c index d1f043d..7e4dba3 100644 --- a/libarchive-clib/c/archive_write_disk_posix.c +++ b/libarchive-clib/c/archive_write_disk_posix.c @@ -1975,7 +1975,7 @@ archive_write_disk_gid(struct archive *_a, const char *name, la_int64_t id) return (a->lookup_gid)(a->lookup_gid_data, name, id); return (id); } - + int64_t archive_write_disk_uid(struct archive *_a, const char *name, la_int64_t id) { @@ -2406,7 +2406,7 @@ create_filesystem_object(struct archive_write_disk *a) */ mode = final_mode & 0777 & ~a->user_umask; - /* + /* * Always create writable such that [f]setxattr() works if we're not * root. */ @@ -3024,7 +3024,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, /* * We are not the last element and we want to * follow symlinks if they are a directory. - * + * * This is needed to extract hardlinks over * symlinks. */ @@ -3435,7 +3435,7 @@ create_dir(struct archive_write_disk *a, char *path) le = new_fixup(a, path); if (le == NULL) return (ARCHIVE_FATAL); - le->fixup |=TODO_MODE_BASE; + le->fixup |= TODO_MODE_BASE; le->mode = mode_final; } return (ARCHIVE_OK); @@ -3447,8 +3447,17 @@ create_dir(struct archive_write_disk *a, char *path) * don't add it to the fixup list here, as it's already been * added. */ - if (la_stat(path, &st) == 0 && S_ISDIR(st.st_mode)) - return (ARCHIVE_OK); + if (errno == EEXIST) { + if (la_stat(path, &st) == 0) { + if (S_ISDIR(st.st_mode)) + return (ARCHIVE_OK); + /* path exists but is not a directory */ + errno = ENOTDIR; + } else { + /* restore original errno */ + errno = EEXIST; + } + } archive_set_error(&a->archive, errno, "Failed to create dir '%s'", path); @@ -4767,4 +4776,3 @@ static void close_file_descriptor(struct archive_write_disk* a) #endif /* !_WIN32 || __CYGWIN__ */ - diff --git a/libarchive-clib/c/archive_write_set_format_gnutar.c b/libarchive-clib/c/archive_write_set_format_gnutar.c index 14ef4cd..b67007a 100644 --- a/libarchive-clib/c/archive_write_set_format_gnutar.c +++ b/libarchive-clib/c/archive_write_set_format_gnutar.c @@ -293,6 +293,17 @@ archive_write_gnutar_header(struct archive_write *a, } else sconv = gnutar->opt_sconv; + /* Sanity check. */ + if (archive_entry_pathname(entry) == NULL +#if defined(_WIN32) && !defined(__CYGWIN__) + && archive_entry_pathname_w(entry) == NULL +#endif + ) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't record entry in tar file without pathname"); + return ARCHIVE_FAILED; + } + /* Only regular files (not hardlinks) have data. */ if (archive_entry_hardlink(entry) != NULL || archive_entry_symlink(entry) != NULL || @@ -385,17 +396,30 @@ archive_write_gnutar_header(struct archive_write *a, r = archive_entry_pathname_l(entry, &(gnutar->pathname), &(gnutar->pathname_length), sconv); if (r != 0) { + const char* p_mbs; if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for pathname"); ret = ARCHIVE_FATAL; goto exit_write_header; } - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Can't translate pathname '%s' to %s", - archive_entry_pathname(entry), - archive_string_conversion_charset_name(sconv)); - ret2 = ARCHIVE_WARN; + p_mbs = archive_entry_pathname(entry); + if (p_mbs) { + /* We have a wrongly-encoded MBS pathname. + * Warn and use it. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname '%s' to %s", p_mbs, + archive_string_conversion_charset_name(sconv)); + ret2 = ARCHIVE_WARN; + } else { + /* We have no MBS pathname. Fail. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname to %s", + archive_string_conversion_charset_name(sconv)); + return ARCHIVE_FAILED; + } } r = archive_entry_uname_l(entry, &(gnutar->uname), &(gnutar->uname_length), sconv); diff --git a/libarchive-clib/c/archive_write_set_format_ustar.c b/libarchive-clib/c/archive_write_set_format_ustar.c index 4084eb4..97724c1 100644 --- a/libarchive-clib/c/archive_write_set_format_ustar.c +++ b/libarchive-clib/c/archive_write_set_format_ustar.c @@ -254,11 +254,11 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry) sconv = ustar->opt_sconv; /* Sanity check. */ + if (archive_entry_pathname(entry) == NULL #if defined(_WIN32) && !defined(__CYGWIN__) - if (archive_entry_pathname_w(entry) == NULL) { -#else - if (archive_entry_pathname(entry) == NULL) { + && archive_entry_pathname_w(entry) == NULL #endif + ) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Can't record entry in tar file without pathname"); return (ARCHIVE_FAILED); @@ -409,15 +409,28 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512], */ r = archive_entry_pathname_l(entry, &pp, ©_length, sconv); if (r != 0) { + const char* p_mbs; if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Pathname"); return (ARCHIVE_FATAL); } - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Can't translate pathname '%s' to %s", - pp, archive_string_conversion_charset_name(sconv)); - ret = ARCHIVE_WARN; + p_mbs = archive_entry_pathname(entry); + if (p_mbs) { + /* We have a wrongly-encoded MBS pathname. + * Warn and use it. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname '%s' to %s", p_mbs, + archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + } else { + /* We have no MBS pathname. Fail. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname to %s", + archive_string_conversion_charset_name(sconv)); + return ARCHIVE_FAILED; + } } if (copy_length <= USTAR_name_size) memcpy(h + USTAR_name_offset, pp, copy_length); diff --git a/libarchive-clib/c/archive_write_set_format_v7tar.c b/libarchive-clib/c/archive_write_set_format_v7tar.c index 2598fc0..37ba73a 100644 --- a/libarchive-clib/c/archive_write_set_format_v7tar.c +++ b/libarchive-clib/c/archive_write_set_format_v7tar.c @@ -232,7 +232,11 @@ archive_write_v7tar_header(struct archive_write *a, struct archive_entry *entry) sconv = v7tar->opt_sconv; /* Sanity check. */ - if (archive_entry_pathname(entry) == NULL) { + if (archive_entry_pathname(entry) == NULL +#if defined(_WIN32) && !defined(__CYGWIN__) + && archive_entry_pathname_w(entry) == NULL +#endif + ) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Can't record entry in tar file without pathname"); return (ARCHIVE_FAILED); @@ -382,15 +386,28 @@ format_header_v7tar(struct archive_write *a, char h[512], */ r = archive_entry_pathname_l(entry, &pp, ©_length, sconv); if (r != 0) { + const char* p_mbs; if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Pathname"); return (ARCHIVE_FATAL); } - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Can't translate pathname '%s' to %s", - pp, archive_string_conversion_charset_name(sconv)); - ret = ARCHIVE_WARN; + p_mbs = archive_entry_pathname(entry); + if (p_mbs) { + /* We have a wrongly-encoded MBS pathname. + * Warn and use it. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname '%s' to %s", p_mbs, + archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + } else { + /* We have no MBS pathname. Fail. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname to %s", + archive_string_conversion_charset_name(sconv)); + return ARCHIVE_FAILED; + } } if (strict && copy_length < V7TAR_name_size) memcpy(h + V7TAR_name_offset, pp, copy_length); diff --git a/libarchive-clib/c/archive_write_set_format_zip.c b/libarchive-clib/c/archive_write_set_format_zip.c index 19121b5..f74922a 100644 --- a/libarchive-clib/c/archive_write_set_format_zip.c +++ b/libarchive-clib/c/archive_write_set_format_zip.c @@ -802,6 +802,17 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) int version_needed = 10; #define MIN_VERSION_NEEDED(x) do { if (version_needed < x) { version_needed = x; } } while (0) + /* Sanity check. */ + if (archive_entry_pathname(entry) == NULL +#if defined(_WIN32) && !defined(__CYGWIN__) + && archive_entry_pathname_w(entry) == NULL +#endif + ) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't record entry in zip file without pathname"); + return ARCHIVE_FAILED; + } + /* Ignore types of entries that we don't support. */ type = archive_entry_filetype(entry); if (type != AE_IFREG && type != AE_IFDIR && type != AE_IFLNK) { @@ -882,22 +893,33 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) return (ARCHIVE_FATAL); } - if (sconv != NULL) { + { const char *p; size_t len; if (archive_entry_pathname_l(zip->entry, &p, &len, sconv) != 0) { + const char* p_mbs; if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Pathname"); return (ARCHIVE_FATAL); } - archive_set_error(&a->archive, - ARCHIVE_ERRNO_FILE_FORMAT, - "Can't translate Pathname '%s' to %s", - archive_entry_pathname(zip->entry), - archive_string_conversion_charset_name(sconv)); - ret2 = ARCHIVE_WARN; + p_mbs = archive_entry_pathname(zip->entry); + if (p_mbs) { + /* We have a wrongly-encoded MBS pathname. Warn and use it. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname '%s' to %s", p_mbs, + archive_string_conversion_charset_name(sconv)); + ret2 = ARCHIVE_WARN; + } else { + /* We have no MBS pathname. Fail. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname to %s", + archive_string_conversion_charset_name(sconv)); + return ARCHIVE_FAILED; + } } if (len > 0) archive_entry_set_pathname(zip->entry, p); diff --git a/libarchive-clib/libarchive-clib.cabal b/libarchive-clib/libarchive-clib.cabal index ba00f44..18eafe6 100644 --- a/libarchive-clib/libarchive-clib.cabal +++ b/libarchive-clib/libarchive-clib.cabal @@ -1,6 +1,6 @@ cabal-version: 2.0 name: libarchive-clib -version: 3.8.5 +version: 3.8.6 license: OtherLicense license-file: LICENSE copyright: Copyright: (c) 2018-2020 Vanessa McHale