diff options
author | Martin Matuska <mm@FreeBSD.org> | 2025-06-01 20:04:03 +0000 |
---|---|---|
committer | Martin Matuska <mm@FreeBSD.org> | 2025-06-01 20:04:03 +0000 |
commit | 76141d3306dea42228646b9a4a5e97ccba59fe2a (patch) | |
tree | b124948fb773476d5ed33e61697e9e5bfff5d68d | |
parent | b0ea71a8555c0b726319dc2a618cc6d17a4fa4f1 (diff) |
Update vendor/libarchive to 3.8.1vendor/libarchive
Notable bugfixes:
#2634 tar: Support negative time values with pax
#2637 tar: Keep block alignment after pax error
#2642 libarchive: fix FILE_skip regression
#2643 tar: Handle extra bytes after sparse entries
#2649 compress: Prevent call stack overflow
#2651 iso9660: always check archive_string_ensure return value
Obtained from: libarchive
Vendor commit: 9525f90ca4bd14c7b335e2f8c84a4607b0af6bdf
38 files changed, 933 insertions, 293 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 042f151edb61..4c1f8770ecde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1257,7 +1257,7 @@ ELSE(LIBXML2_FOUND) # Check linkage as well; versions of mingw-w64 before v11.0.0 # do not contain an import library for xmllite. cmake_push_check_state() - SET(CMAKE_REQUIRED_LIBRARIES "xmllite") + SET(CMAKE_REQUIRED_LIBRARIES "xmllite" "uuid") check_c_source_compiles(" #include <initguid.h> #include <xmllite.h> @@ -1268,7 +1268,7 @@ ELSE(LIBXML2_FOUND) cmake_pop_check_state() IF(HAVE_XMLLITE_H) SET(XMLLITE_FOUND TRUE) - LIST(APPEND ADDITIONAL_LIBS "xmllite") + LIST(APPEND ADDITIONAL_LIBS "xmllite" "uuid") ENDIF() ENDIF() ENDIF(EXPAT_FOUND) diff --git a/Makefile.am b/Makefile.am index 74cb6e14b609..05232712a857 100644 --- a/Makefile.am +++ b/Makefile.am @@ -531,8 +531,10 @@ libarchive_test_SOURCES= \ libarchive/test/test_read_format_tar_empty_with_gnulabel.c \ libarchive/test/test_read_format_tar_filename.c \ libarchive/test/test_read_format_tar_invalid_pax_size.c \ + libarchive/test/test_read_format_tar_mac_metadata.c \ libarchive/test/test_read_format_tar_pax_g_large.c \ libarchive/test/test_read_format_tar_pax_large_attr.c \ + libarchive/test/test_read_format_tar_pax_negative_time.c \ libarchive/test/test_read_format_tbz.c \ libarchive/test/test_read_format_tgz.c \ libarchive/test/test_read_format_tlz.c \ @@ -565,6 +567,7 @@ libarchive_test_SOURCES= \ libarchive/test/test_read_format_zip_zip64.c \ libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c \ libarchive/test/test_read_large.c \ + libarchive/test/test_read_pax_empty_val_no_nl.c \ libarchive/test/test_read_pax_xattr_rht_security_selinux.c \ libarchive/test/test_read_pax_xattr_schily.c \ libarchive/test/test_read_pax_truncated.c \ @@ -975,8 +978,10 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_tar_empty_pax.tar.Z.uu \ libarchive/test/test_read_format_tar_filename_koi8r.tar.Z.uu \ libarchive/test/test_read_format_tar_invalid_pax_size.tar.uu \ + libarchive/test/test_read_format_tar_mac_metadata_1.tar.uu \ libarchive/test/test_read_format_tar_pax_g_large.tar.uu \ libarchive/test/test_read_format_tar_pax_large_attr.tar.Z.uu \ + libarchive/test/test_read_format_tar_pax_negative_time.tar.uu \ libarchive/test/test_read_format_ustar_filename_cp866.tar.Z.uu \ libarchive/test/test_read_format_ustar_filename_eucjp.tar.Z.uu \ libarchive/test/test_read_format_ustar_filename_koi8r.tar.Z.uu \ @@ -1041,6 +1046,7 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_large_splitted_rar_ac.uu \ libarchive/test/test_read_large_splitted_rar_ad.uu \ libarchive/test/test_read_large_splitted_rar_ae.uu \ + libarchive/test/test_read_pax_empty_val_no_nl.tar.uu \ libarchive/test/test_read_pax_xattr_rht_security_selinux.tar.uu \ libarchive/test/test_read_pax_xattr_schily.tar.uu \ libarchive/test/test_read_splitted_rar_aa.uu \ @@ -1,3 +1,5 @@ +Jun 01, 2026: libarchive 3.8.1 released + May 20, 2025: libarchive 3.8.0 released Mar 30, 2025: libarchive 3.7.9 released diff --git a/build/cmake/CreatePkgConfigFile.cmake b/build/cmake/CreatePkgConfigFile.cmake index bc5a43f72af1..50caa5e85097 100644 --- a/build/cmake/CreatePkgConfigFile.cmake +++ b/build/cmake/CreatePkgConfigFile.cmake @@ -29,5 +29,5 @@ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/pkgconfig/libarchive.pc.in # And install it, of course ;). IF(ENABLE_INSTALL) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/build/pkgconfig/libarchive.pc - DESTINATION "lib/pkgconfig") + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") ENDIF() diff --git a/build/version b/build/version index 7333f0e7d0cc..f08c8c42bfea 100644 --- a/build/version +++ b/build/version @@ -1 +1 @@ -3008000 +3008001 diff --git a/configure.ac b/configure.ac index 911dcf16b182..d8d85eda929f 100644 --- a/configure.ac +++ b/configure.ac @@ -4,8 +4,8 @@ dnl First, define all of the version numbers up front. dnl In particular, this allows the version macro to be used in AC_INIT dnl These first two version numbers are updated automatically on each release. -m4_define([LIBARCHIVE_VERSION_S],[3.8.0]) -m4_define([LIBARCHIVE_VERSION_N],[3008000]) +m4_define([LIBARCHIVE_VERSION_S],[3.8.1]) +m4_define([LIBARCHIVE_VERSION_N],[3008001]) dnl bsdtar and bsdcpio versioning tracks libarchive m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S()) @@ -258,7 +258,8 @@ AM_CONDITIONAL([STATIC_BSDCPIO], [ test "$static_bsdcpio" = yes ]) case $host in *mingw* | *cygwin* | *msys* ) AC_PREPROC_IFELSE([AC_LANG_PROGRAM( - [[#ifdef _WIN32_WINNT + [[#include <windows.h> + #ifdef _WIN32_WINNT # error _WIN32_WINNT already defined #endif ]],[[;]]) @@ -267,7 +268,8 @@ case $host in AC_DEFINE([NTDDI_VERSION], 0x05020000, [Define to '0x05020000' for Windows Server 2003 APIs.]) ]) AC_PREPROC_IFELSE([AC_LANG_PROGRAM( - [[#ifdef WINVER + [[#include <windows.h> + #ifdef WINVER # error WINVER already defined #endif ]],[[;]]) @@ -436,13 +438,15 @@ if test "x$with_bz2lib" != "xno"; then esac fi +PKG_PROG_PKG_CONFIG + AC_ARG_WITH([libb2], AS_HELP_STRING([--without-libb2], [Don't build support for BLAKE2 through libb2])) if test "x$with_libb2" != "xno"; then AC_CHECK_HEADERS([blake2.h]) AC_CHECK_LIB(b2,blake2sp_init) - BLAKE2_PC_VER=`pkg-config --modversion libb2` + BLAKE2_PC_VER=`$PKG_CONFIG --modversion libb2` if test "x$BLAKE2_PC_VER" != "x"; then AC_DEFINE_UNQUOTED([LIBB2_PKGCONFIG_VERSION], ["$BLAKE2_PC_VER"], [Libb2 version coming from pkg-config.]) fi @@ -925,7 +929,7 @@ if test "x$enable_xattr" != "xno"; then ]) AC_CHECK_DECLS([XATTR_NOFOLLOW], [], [], [#include <sys/xattr.h> ]) - ATTR_PC_VER=`pkg-config --modversion libattr` + ATTR_PC_VER=`$PKG_CONFIG --modversion libattr` if test "x$ATTR_PC_VER" != "x"; then AC_DEFINE_UNQUOTED([LIBATTR_PKGCONFIG_VERSION], ["$ATTR_PC_VER"], [Libattr version coming from pkg-config.]) fi @@ -1024,7 +1028,7 @@ AC_ARG_ENABLE([acl], if test "x$enable_acl" != "xno"; then # Libacl AC_CHECK_LIB([acl], [acl_get_file]) - ACL_PC_VER=`pkg-config --modversion libacl` + ACL_PC_VER=`$PKG_CONFIG --modversion libacl` if test "x$ACL_PC_VER" != "x"; then AC_DEFINE_UNQUOTED([LIBACL_PKGCONFIG_VERSION], ["$ACL_PC_VER"], [Libacl version coming from pkg-config.]) fi @@ -1038,7 +1042,7 @@ if test "x$enable_acl" != "xno"; then ]) AC_CHECK_LIB([richacl], [richacl_get_file]) - RICHACL_PC_VER=`pkg-config --modversion librichacl` + RICHACL_PC_VER=`$PKG_CONFIG --modversion librichacl` if test "x$RICHACL_PC_VER" != "x"; then AC_DEFINE_UNQUOTED([LIBRICHACL_PKGCONFIG_VERSION], ["$RICHACL_PC_VER"], [Librichacl version coming from pkg-config.]) fi diff --git a/cpio/test/test_format_newc.c b/cpio/test/test_format_newc.c index 0d59c173fa46..33aa16d07a81 100644 --- a/cpio/test/test_format_newc.c +++ b/cpio/test/test_format_newc.c @@ -219,7 +219,7 @@ DEFINE_TEST(test_format_newc) assert(is_hex(e, 110)); assertEqualMem(e + 0, "070701", 6); /* Magic */ assert(is_hex(e + 6, 8)); /* ino */ -#if defined(_WIN32) && !defined(CYGWIN) +#if defined(_WIN32) && !defined(__CYGWIN__) /* Mode: Group members bits and others bits do not work. */ assertEqualInt(0xa180, from_hex(e + 14, 8) & 0xffc0); #else diff --git a/cpio/test/test_option_a.c b/cpio/test/test_option_a.c index e6b87948c65a..28e5b73765d7 100644 --- a/cpio/test/test_option_a.c +++ b/cpio/test/test_option_a.c @@ -52,7 +52,7 @@ test_create(void) * #ifdef this section out. Most of the test below is * still valid. */ memset(×, 0, sizeof(times)); -#if defined(_WIN32) && !defined(CYGWIN) +#if defined(_WIN32) && !defined(__CYGWIN__) times.actime = 86400; times.modtime = 86400; #else diff --git a/libarchive/CMakeLists.txt b/libarchive/CMakeLists.txt index 556710ad8285..fd997db4112c 100644 --- a/libarchive/CMakeLists.txt +++ b/libarchive/CMakeLists.txt @@ -248,7 +248,7 @@ IF(BUILD_SHARED_LIBS) ADD_LIBRARY(archive SHARED ${libarchive_SOURCES} ${include_HEADERS}) TARGET_INCLUDE_DIRECTORIES(archive PUBLIC .) TARGET_LINK_LIBRARIES(archive ${ADDITIONAL_LIBS}) - SET_TARGET_PROPERTIES(archive PROPERTIES + SET_TARGET_PROPERTIES(archive PROPERTIES VERSION ${SOVERSION_FULL} SOVERSION ${SOVERSION} MACHO_COMPATIBILITY_VERSION ${MACHO_COMPATIBILITY_VERSION} @@ -266,18 +266,22 @@ IF(NOT WIN32 OR CYGWIN OR NOT BUILD_SHARED_LIBS) SET_TARGET_PROPERTIES(archive_static PROPERTIES OUTPUT_NAME archive) ENDIF(NOT WIN32 OR CYGWIN OR NOT BUILD_SHARED_LIBS) +if(NOT DEFINED CMAKE_INSTALL_LIBDIR) + set(CMAKE_INSTALL_LIBDIR "lib") +endif() + IF(ENABLE_INSTALL) # How to install the libraries IF(BUILD_SHARED_LIBS) INSTALL(TARGETS archive RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib) + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) ENDIF(BUILD_SHARED_LIBS) INSTALL(TARGETS archive_static RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib) + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) INSTALL_MAN(${libarchive_MANS}) INSTALL(FILES ${include_HEADERS} DESTINATION include) ENDIF() diff --git a/libarchive/archive.h b/libarchive/archive.h index be8381413da2..002190a24663 100644 --- a/libarchive/archive.h +++ b/libarchive/archive.h @@ -34,7 +34,7 @@ * assert that ARCHIVE_VERSION_NUMBER >= 2012108. */ /* Note: Compiler will complain if this does not match archive_entry.h! */ -#define ARCHIVE_VERSION_NUMBER 3008000 +#define ARCHIVE_VERSION_NUMBER 3008001 #include <sys/stat.h> #include <stddef.h> /* for wchar_t */ @@ -177,7 +177,7 @@ __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_ONLY_STRING "3.8.0" +#define ARCHIVE_VERSION_ONLY_STRING "3.8.1" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); @@ -1250,8 +1250,10 @@ __LA_DECL int archive_match_include_gname_w(struct archive *, const wchar_t *); /* Utility functions */ +#if ARCHIVE_VERSION_NUMBER < 4000000 /* Convenience function to sort a NULL terminated list of strings */ __LA_DECL int archive_utility_string_sort(char **); +#endif #ifdef __cplusplus } diff --git a/libarchive/archive_cryptor_private.h b/libarchive/archive_cryptor_private.h index 460d38c122a6..4b3c6c161433 100644 --- a/libarchive/archive_cryptor_private.h +++ b/libarchive/archive_cryptor_private.h @@ -144,6 +144,10 @@ typedef struct { #else +#if defined(_WIN32) && !defined(__CYGWIN__) && !(defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA) +#define ARCHIVE_CRYPTOR_USE_WINCRYPT 1 +#endif + #define AES_BLOCK_SIZE 16 #define AES_MAX_KEY_SIZE 32 typedef int archive_crypto_ctx; diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h index 84ed1b0bd93a..2b917b3fde8e 100644 --- a/libarchive/archive_entry.h +++ b/libarchive/archive_entry.h @@ -28,7 +28,7 @@ #define ARCHIVE_ENTRY_H_INCLUDED /* Note: Compiler will complain if this does not match archive.h! */ -#define ARCHIVE_VERSION_NUMBER 3008000 +#define ARCHIVE_VERSION_NUMBER 3008001 /* * Note: archive_entry.h is for use outside of libarchive; the diff --git a/libarchive/archive_match.c b/libarchive/archive_match.c index 20880d3d39af..51a0e3fd5778 100644 --- a/libarchive/archive_match.c +++ b/libarchive/archive_match.c @@ -35,6 +35,9 @@ #ifdef HAVE_STRING_H #include <string.h> #endif +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif #include "archive.h" #include "archive_private.h" @@ -53,8 +56,7 @@ struct match { struct match_list { struct match *first; struct match **last; - int count; - int unmatched_count; + size_t unmatched_count; struct match *unmatched_next; int unmatched_eof; }; @@ -73,7 +75,6 @@ struct match_file { struct entry_list { struct match_file *first; struct match_file **last; - int count; }; struct id_array { @@ -144,12 +145,15 @@ static int add_pattern_mbs(struct archive_match *, struct match_list *, const char *); static int add_pattern_wcs(struct archive_match *, struct match_list *, const wchar_t *); +#if !defined(_WIN32) || defined(__CYGWIN__) static int cmp_key_mbs(const struct archive_rb_node *, const void *); -static int cmp_key_wcs(const struct archive_rb_node *, const void *); static int cmp_node_mbs(const struct archive_rb_node *, const struct archive_rb_node *); +#else +static int cmp_key_wcs(const struct archive_rb_node *, const void *); static int cmp_node_wcs(const struct archive_rb_node *, const struct archive_rb_node *); +#endif static void entry_list_add(struct entry_list *, struct match_file *); static void entry_list_free(struct entry_list *); static void entry_list_init(struct entry_list *); @@ -189,12 +193,12 @@ static int validate_time_flag(struct archive *, int, const char *); #define get_date archive_parse_date -static const struct archive_rb_tree_ops rb_ops_mbs = { +static const struct archive_rb_tree_ops rb_ops = { +#if !defined(_WIN32) || defined(__CYGWIN__) cmp_node_mbs, cmp_key_mbs -}; - -static const struct archive_rb_tree_ops rb_ops_wcs = { +#else cmp_node_wcs, cmp_key_wcs +#endif }; /* @@ -228,7 +232,7 @@ archive_match_new(void) a->recursive_include = 1; match_list_init(&(a->inclusions)); match_list_init(&(a->exclusions)); - __archive_rb_tree_init(&(a->exclusion_tree), &rb_ops_mbs); + __archive_rb_tree_init(&(a->exclusion_tree), &rb_ops); entry_list_init(&(a->exclusion_entry_list)); match_list_init(&(a->inclusion_unames)); match_list_init(&(a->inclusion_gnames)); @@ -507,7 +511,9 @@ archive_match_path_unmatched_inclusions(struct archive *_a) ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions"); a = (struct archive_match *)_a; - return (a->inclusions.unmatched_count); + if (a->inclusions.unmatched_count > (size_t)INT_MAX) + return INT_MAX; + return (int)(a->inclusions.unmatched_count); } int @@ -650,7 +656,7 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist, break; } } else { - if (*b == 0x0d || *b == 0x0a) { + if (*b == 0x0d || *b == 0x0a) { found_separator = 1; break; } @@ -735,7 +741,7 @@ path_excluded(struct archive_match *a, int mbs, const void *pathname) } } - /* Exclusions take priority */ + /* Exclusions take priority. */ for (match = a->exclusions.first; match != NULL; match = match->next){ r = match_path_exclusion(a, match, mbs, pathname); @@ -834,7 +840,6 @@ match_list_init(struct match_list *list) { list->first = NULL; list->last = &(list->first); - list->count = 0; } static void @@ -855,7 +860,6 @@ match_list_add(struct match_list *list, struct match *m) { *list->last = m; list->last = &(m->next); - list->count++; list->unmatched_count++; } @@ -1275,6 +1279,7 @@ set_timefilter_pathname_wcs(struct archive_match *a, int timetype, /* * Call back functions for archive_rb. */ +#if !defined(_WIN32) || defined(__CYGWIN__) static int cmp_node_mbs(const struct archive_rb_node *n1, const struct archive_rb_node *n2) @@ -1291,7 +1296,7 @@ cmp_node_mbs(const struct archive_rb_node *n1, return (-1); return (strcmp(p1, p2)); } - + static int cmp_key_mbs(const struct archive_rb_node *n, const void *key) { @@ -1303,7 +1308,7 @@ cmp_key_mbs(const struct archive_rb_node *n, const void *key) return (-1); return (strcmp(p, (const char *)key)); } - +#else static int cmp_node_wcs(const struct archive_rb_node *n1, const struct archive_rb_node *n2) @@ -1320,7 +1325,7 @@ cmp_node_wcs(const struct archive_rb_node *n1, return (-1); return (wcscmp(p1, p2)); } - + static int cmp_key_wcs(const struct archive_rb_node *n, const void *key) { @@ -1332,13 +1337,13 @@ cmp_key_wcs(const struct archive_rb_node *n, const void *key) return (-1); return (wcscmp(p, (const wchar_t *)key)); } +#endif static void entry_list_init(struct entry_list *list) { list->first = NULL; list->last = &(list->first); - list->count = 0; } static void @@ -1359,7 +1364,6 @@ entry_list_add(struct entry_list *list, struct match_file *file) { *list->last = file; list->last = &(file->next); - list->count++; } static int @@ -1382,9 +1386,7 @@ add_entry(struct archive_match *a, int flag, return (ARCHIVE_FAILED); } archive_mstring_copy_wcs(&(f->pathname), pathname); - a->exclusion_tree.rbt_ops = &rb_ops_wcs; #else - (void)rb_ops_wcs; pathname = archive_entry_pathname(entry); if (pathname == NULL) { free(f); @@ -1392,7 +1394,6 @@ add_entry(struct archive_match *a, int flag, return (ARCHIVE_FAILED); } archive_mstring_copy_mbs(&(f->pathname), pathname); - a->exclusion_tree.rbt_ops = &rb_ops_mbs; #endif f->flag = flag; f->mtime_sec = archive_entry_mtime(entry); @@ -1517,16 +1518,13 @@ time_excluded(struct archive_match *a, struct archive_entry *entry) } /* If there is no exclusion list, include the file. */ - if (a->exclusion_entry_list.count == 0) + if (a->exclusion_entry_list.first == NULL) return (0); #if defined(_WIN32) && !defined(__CYGWIN__) pathname = archive_entry_pathname_w(entry); - a->exclusion_tree.rbt_ops = &rb_ops_wcs; #else - (void)rb_ops_wcs; pathname = archive_entry_pathname(entry); - a->exclusion_tree.rbt_ops = &rb_ops_mbs; #endif if (pathname == NULL) return (0); @@ -1682,7 +1680,7 @@ archive_match_owner_excluded(struct archive *_a, static int add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id) { - unsigned i; + size_t i; if (ids->count + 1 >= ids->size) { void *p; @@ -1719,10 +1717,10 @@ add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id) static int match_owner_id(struct id_array *ids, int64_t id) { - unsigned b, m, t; + size_t b, m, t; t = 0; - b = (unsigned)ids->count; + b = ids->count; while (t < b) { m = (t + b)>>1; if (ids->ids[m] == id) @@ -1817,7 +1815,7 @@ owner_excluded(struct archive_match *a, struct archive_entry *entry) return (1); } - if (a->inclusion_unames.count) { + if (a->inclusion_unames.first != NULL) { #if defined(_WIN32) && !defined(__CYGWIN__) r = match_owner_name_wcs(a, &(a->inclusion_unames), archive_entry_uname_w(entry)); @@ -1831,7 +1829,7 @@ owner_excluded(struct archive_match *a, struct archive_entry *entry) return (r); } - if (a->inclusion_gnames.count) { + if (a->inclusion_gnames.first != NULL) { #if defined(_WIN32) && !defined(__CYGWIN__) r = match_owner_name_wcs(a, &(a->inclusion_gnames), archive_entry_gname_w(entry)); diff --git a/libarchive/archive_read_disk_windows.c b/libarchive/archive_read_disk_windows.c index a774305d0cf2..689a45958c15 100644 --- a/libarchive/archive_read_disk_windows.c +++ b/libarchive/archive_read_disk_windows.c @@ -1652,7 +1652,7 @@ tree_push(struct tree *t, const wchar_t *path, const wchar_t *full_path, /* * Append a name to the current dir path. */ -static void +static int tree_append(struct tree *t, const wchar_t *name, size_t name_length) { size_t size_needed; @@ -1665,7 +1665,8 @@ tree_append(struct tree *t, const wchar_t *name, size_t name_length) /* Resize pathname buffer as needed. */ size_needed = name_length + t->dirname_length + 2; - archive_wstring_ensure(&t->path, size_needed); + if (archive_wstring_ensure(&t->path, size_needed) == NULL) + return (TREE_ERROR_FATAL); /* Add a separating '/' if it's needed. */ if (t->dirname_length > 0 && t->path.s[archive_strlen(&t->path)-1] != L'/') @@ -1677,13 +1678,15 @@ tree_append(struct tree *t, const wchar_t *name, size_t name_length) t->full_path.s[t->full_path_dir_length] = L'\0'; t->full_path.length = t->full_path_dir_length; size_needed = name_length + t->full_path_dir_length + 2; - archive_wstring_ensure(&t->full_path, size_needed); + if (archive_wstring_ensure(&t->full_path, size_needed) == NULL) + return (TREE_ERROR_FATAL); /* Add a separating '\' if it's needed. */ if (t->full_path.s[archive_strlen(&t->full_path)-1] != L'\\') archive_wstrappend_wchar(&t->full_path, L'\\'); archive_wstrncat(&t->full_path, name, name_length); t->restore_time.full_path = t->full_path.s; } + return (0); } /* @@ -1697,7 +1700,10 @@ tree_open(const wchar_t *path, int symlink_mode, int restore_time) t = calloc(1, sizeof(*t)); archive_string_init(&(t->full_path)); archive_string_init(&t->path); - archive_wstring_ensure(&t->path, 15); + if (archive_wstring_ensure(&t->path, 15) == NULL) { + free(t); + return (NULL); + } t->initial_symlink_mode = symlink_mode; return (tree_reopen(t, path, restore_time)); } @@ -1756,7 +1762,8 @@ tree_reopen(struct tree *t, const wchar_t *path, int restore_time) p = wcsrchr(base, L'/'); if (p != NULL) { *p = L'\0'; - tree_append(t, base, p - base); + if (tree_append(t, base, p - base)) + goto failed; t->dirname_length = archive_strlen(&t->path); base = p + 1; } @@ -1892,8 +1899,10 @@ tree_next(struct tree *t) } /* Top stack item needs a regular visit. */ t->current = t->stack; - tree_append(t, t->stack->name.s, + r = tree_append(t, t->stack->name.s, archive_strlen(&(t->stack->name))); + if (r != 0) + return (r); //t->dirname_length = t->path_length; //tree_pop(t); t->stack->flags &= ~needsFirstVisit; @@ -1901,8 +1910,10 @@ tree_next(struct tree *t) } else if (t->stack->flags & needsDescent) { /* Top stack item is dir to descend into. */ t->current = t->stack; - tree_append(t, t->stack->name.s, + r = tree_append(t, t->stack->name.s, archive_strlen(&(t->stack->name))); + if (r != 0) + return (r); t->stack->flags &= ~needsDescent; r = tree_descent(t); if (r != 0) { @@ -1945,9 +1956,10 @@ tree_dir_next_windows(struct tree *t, const wchar_t *pattern) struct archive_wstring pt; archive_string_init(&pt); - archive_wstring_ensure(&pt, + if (archive_wstring_ensure(&pt, archive_strlen(&(t->full_path)) - + 2 + wcslen(pattern)); + + 2 + wcslen(pattern)) == NULL) + return (TREE_ERROR_FATAL); archive_wstring_copy(&pt, &(t->full_path)); archive_wstrappend_wchar(&pt, L'\\'); archive_wstrcat(&pt, pattern); @@ -1979,7 +1991,9 @@ tree_dir_next_windows(struct tree *t, const wchar_t *pattern) continue; if (name[0] == L'.' && name[1] == L'.' && name[2] == L'\0') continue; - tree_append(t, name, namelen); + r = tree_append(t, name, namelen); + if (r != 0) + return (r); return (t->visit_type = TREE_REGULAR); } } diff --git a/libarchive/archive_read_open_file.c b/libarchive/archive_read_open_file.c index 6ed18a0c08eb..742923abbee9 100644 --- a/libarchive/archive_read_open_file.c +++ b/libarchive/archive_read_open_file.c @@ -132,7 +132,7 @@ FILE_skip(struct archive *a, void *client_data, int64_t request) #else long skip = (long)request; #endif - int64_t old_offset, new_offset; + int64_t old_offset, new_offset = -1; int skip_bits = sizeof(skip) * 8 - 1; (void)a; /* UNUSED */ @@ -170,11 +170,14 @@ FILE_skip(struct archive *a, void *client_data, int64_t request) #ifdef __ANDROID__ new_offset = lseek(fileno(mine->f), skip, SEEK_CUR); #elif HAVE__FSEEKI64 - new_offset = _fseeki64(mine->f, skip, SEEK_CUR); + if (_fseeki64(mine->f, skip, SEEK_CUR) == 0) + new_offset = _ftelli64(mine->f); #elif HAVE_FSEEKO - new_offset = fseeko(mine->f, skip, SEEK_CUR); + if (fseeko(mine->f, skip, SEEK_CUR) == 0) + new_offset = ftello(mine->f); #else - new_offset = fseek(mine->f, skip, SEEK_CUR); + if (fseek(mine->f, skip, SEEK_CUR) == 0) + new_offset = ftell(mine->f); #endif if (new_offset >= 0) return (new_offset - old_offset); diff --git a/libarchive/archive_read_support_filter_compress.c b/libarchive/archive_read_support_filter_compress.c index b6e9816dfee9..b89eaabe5259 100644 --- a/libarchive/archive_read_support_filter_compress.c +++ b/libarchive/archive_read_support_filter_compress.c @@ -328,6 +328,7 @@ next_code(struct archive_read_filter *self) static int debug_buff[1024]; static unsigned debug_index; +again: code = newcode = getbits(self, state->bits); if (code < 0) return (code); @@ -360,7 +361,7 @@ next_code(struct archive_read_filter *self) state->section_end_code = (1 << state->bits) - 1; state->free_ent = 257; state->oldcode = -1; - return (next_code(self)); + goto again; } if (code > state->free_ent diff --git a/libarchive/archive_read_support_format_cab.c b/libarchive/archive_read_support_format_cab.c index e012248a5bc2..a96f7d313951 100644 --- a/libarchive/archive_read_support_format_cab.c +++ b/libarchive/archive_read_support_format_cab.c @@ -363,7 +363,12 @@ archive_read_support_format_cab(struct archive *_a) return (ARCHIVE_FATAL); } archive_string_init(&cab->ws); - archive_wstring_ensure(&cab->ws, 256); + if (archive_wstring_ensure(&cab->ws, 256) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + free(cab); + return (ARCHIVE_FATAL); + } r = __archive_read_register_format(a, cab, diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c index e9b3312a2cbb..0c87bc6d732f 100644 --- a/libarchive/archive_read_support_format_tar.c +++ b/libarchive/archive_read_support_format_tar.c @@ -174,7 +174,7 @@ static int gnu_sparse_old_parse(struct archive_read *, struct tar *, const struct gnu_sparse *sparse, int length); static int gnu_sparse_01_parse(struct archive_read *, struct tar *, const char *, size_t); -static ssize_t gnu_sparse_10_read(struct archive_read *, struct tar *, +static int64_t gnu_sparse_10_read(struct archive_read *, struct tar *, int64_t *); static int header_Solaris_ACL(struct archive_read *, struct tar *, struct archive_entry *, const void *, int64_t *); @@ -628,7 +628,10 @@ archive_read_format_tar_read_data(struct archive_read *a, /* If we're at end of file, return EOF. */ if (tar->sparse_list == NULL || tar->entry_bytes_remaining == 0) { - if (__archive_read_consume(a, tar->entry_padding) < 0) + int64_t request = tar->entry_bytes_remaining + + tar->entry_padding; + + if (__archive_read_consume(a, request) != request) return (ARCHIVE_FATAL); tar->entry_padding = 0; *buff = NULL; @@ -666,29 +669,15 @@ archive_read_format_tar_read_data(struct archive_read *a, static int archive_read_format_tar_skip(struct archive_read *a) { - int64_t bytes_skipped; int64_t request; - struct sparse_block *p; struct tar* tar; tar = (struct tar *)(a->format->data); - /* Do not consume the hole of a sparse file. */ - request = 0; - for (p = tar->sparse_list; p != NULL; p = p->next) { - if (!p->hole) { - if (p->remaining >= INT64_MAX - request) { - return ARCHIVE_FATAL; - } - request += p->remaining; - } - } - if (request > tar->entry_bytes_remaining) - request = tar->entry_bytes_remaining; - request += tar->entry_padding + tar->entry_bytes_unconsumed; + request = tar->entry_bytes_remaining + tar->entry_padding + + tar->entry_bytes_unconsumed; - bytes_skipped = __archive_read_consume(a, request); - if (bytes_skipped < 0) + if (__archive_read_consume(a, request) != request) return (ARCHIVE_FATAL); tar->entry_bytes_remaining = 0; @@ -702,6 +691,22 @@ archive_read_format_tar_skip(struct archive_read *a) } /* + * This function resets the accumulated state while reading + * a header. + */ +static void +tar_reset_header_state(struct tar *tar) +{ + tar->pax_hdrcharset_utf8 = 1; + tar->sparse_gnu_attributes_seen = 0; + archive_string_empty(&(tar->entry_gname)); + archive_string_empty(&(tar->entry_pathname)); + archive_string_empty(&(tar->entry_pathname_override)); + archive_string_empty(&(tar->entry_uname)); + archive_string_empty(&tar->entry_linkpath); +} + +/* * This function reads and interprets all of the headers associated * with a single entry. */ @@ -726,13 +731,7 @@ tar_read_header(struct archive_read *a, struct tar *tar, static const int32_t seen_x_header = 32; /* Also X */ static const int32_t seen_mac_metadata = 512; - tar->pax_hdrcharset_utf8 = 1; - tar->sparse_gnu_attributes_seen = 0; - archive_string_empty(&(tar->entry_gname)); - archive_string_empty(&(tar->entry_pathname)); - archive_string_empty(&(tar->entry_pathname_override)); - archive_string_empty(&(tar->entry_uname)); - archive_string_empty(&tar->entry_linkpath); + tar_reset_header_state(tar); /* Ensure format is set. */ if (a->archive.archive_format_name == NULL) { @@ -936,6 +935,7 @@ tar_read_header(struct archive_read *a, struct tar *tar, err = err_combine(err, err2); /* Note: Other headers can appear again. */ seen_headers = seen_mac_metadata; + tar_reset_header_state(tar); break; } @@ -1118,8 +1118,8 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar, break; default: archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Malformed Solaris ACL attribute (unsupported type %" - PRIo64 ")", type); + "Malformed Solaris ACL attribute (unsupported type %llu)", + (unsigned long long)type); archive_string_free(&acl_text); return (ARCHIVE_WARN); } @@ -1293,18 +1293,21 @@ read_body_to_string(struct archive_read *a, struct tar *tar, (void)tar; /* UNUSED */ header = (const struct archive_entry_header_ustar *)h; size = tar_atol(header->size, sizeof(header->size)); - if (size > entry_limit) { + if (size < 0 || size > entry_limit) { + archive_set_error(&a->archive, EINVAL, + "Special header has invalid size: %lld", + (long long)size); return (ARCHIVE_FATAL); } - if ((size > (int64_t)pathname_limit) || (size < 0)) { + if (size > (int64_t)pathname_limit) { archive_string_empty(as); int64_t to_consume = ((size + 511) & ~511); if (to_consume != __archive_read_consume(a, to_consume)) { return (ARCHIVE_FATAL); } archive_set_error(&a->archive, EINVAL, - "Special header too large: %d > 1MiB", - (int)size); + "Special header too large: %lld > 1MiB", + (long long)size); return (ARCHIVE_WARN); } r = read_bytes_to_string(a, as, size, unconsumed); @@ -1743,7 +1746,10 @@ header_pax_global(struct archive_read *a, struct tar *tar, header = (const struct archive_entry_header_ustar *)h; size = tar_atol(header->size, sizeof(header->size)); - if (size > entry_limit) { + if (size < 0 || size > entry_limit) { + archive_set_error(&a->archive, EINVAL, + "Special header has invalid size: %lld", + (long long)size); return (ARCHIVE_FATAL); } to_consume = ((size + 511) & ~511); @@ -1890,8 +1896,8 @@ header_pax_extension(struct archive_read *a, struct tar *tar, return (ARCHIVE_FATAL); } archive_set_error(&a->archive, EINVAL, - "Ignoring oversized pax extensions: %d > %d", - (int)ext_size, (int)ext_size_limit); + "Ignoring oversized pax extensions: %lld > %lld", + (long long)ext_size, (long long)ext_size_limit); return (ARCHIVE_WARN); } tar_flush_unconsumed(a, unconsumed); @@ -1990,6 +1996,13 @@ header_pax_extension(struct archive_read *a, struct tar *tar, *unconsumed += p - attr_start; tar_flush_unconsumed(a, unconsumed); + if (value_length == 0) { + archive_set_error(&a->archive, EINVAL, + "Malformed pax attributes"); + *unconsumed += ext_size + ext_padding; + return (ARCHIVE_WARN); + } + /* pax_attribute will consume value_length - 1 */ r = pax_attribute(a, tar, entry, attr_name.s, archive_strlen(&attr_name), value_length - 1, unconsumed); ext_size -= value_length - 1; @@ -2199,8 +2212,9 @@ pax_attribute_SCHILY_acl(struct archive_read *a, struct tar *tar, if (value_length > acl_limit) { __archive_read_consume(a, value_length); archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Unreasonably large ACL: %d > %d", - (int)value_length, (int)acl_limit); + "Unreasonably large ACL: %llu > %llu", + (unsigned long long)value_length, + (unsigned long long)acl_limit); return (ARCHIVE_WARN); } @@ -2247,12 +2261,16 @@ pax_attribute_read_time(struct archive_read *a, size_t value_length, int64_t *ps r = read_bytes_to_string(a, &as, value_length, unconsumed); if (r < ARCHIVE_OK) { archive_string_free(&as); + *ps = 0; + *pn = 0; return (r); } pax_time(as.s, archive_strlen(&as), ps, pn); archive_string_free(&as); - if (*ps < 0 || *ps == INT64_MAX) { + if (*ps == INT64_MIN) { + *ps = 0; + *pn = 0; return (ARCHIVE_WARN); } return (ARCHIVE_OK); @@ -2386,8 +2404,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent tar->sparse_gnu_minor = 1; if (value_length > sparse_map_limit) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Unreasonably large sparse map: %d > %d", - (int)value_length, (int)sparse_map_limit); + "Unreasonably large sparse map: %llu > %llu", + (unsigned long long)value_length, + (unsigned long long)sparse_map_limit); err = ARCHIVE_FAILED; } else { p = __archive_read_ahead(a, value_length, &bytes_read); @@ -2494,8 +2513,8 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent } else { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "symlink type is very long" - "(longest recognized value is 4 bytes, this is %d)", - (int)value_length); + "(longest recognized value is 4 bytes, this is %llu)", + (unsigned long long)value_length); err = ARCHIVE_WARN; } __archive_read_consume(a, value_length); @@ -2531,8 +2550,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent if (value_length > xattr_limit) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Ignoring unreasonably large security.selinux attribute:" - " %d > %d", - (int)value_length, (int)xattr_limit); + " %llu > %llu", + (unsigned long long)value_length, + (unsigned long long)xattr_limit); /* TODO: Should this be FAILED instead? */ err = ARCHIVE_WARN; } else { @@ -2649,8 +2669,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent } } else { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Unreasonably large xattr: %d > %d", - (int)value_length, (int)xattr_limit); + "Unreasonably large xattr: %llu > %llu", + (unsigned long long)value_length, + (unsigned long long)xattr_limit); err = ARCHIVE_WARN; } __archive_read_consume(a, value_length); @@ -2680,8 +2701,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent } } else { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Unreasonably large sparse map: %d > %d", - (int)value_length, (int)sparse_map_limit); + "Unreasonably large sparse map: %llu > %llu", + (unsigned long long)value_length, + (unsigned long long)sparse_map_limit); err = ARCHIVE_FAILED; } __archive_read_consume(a, value_length); @@ -2750,8 +2772,8 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent } } else { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "hdrcharset attribute is unreasonably large (%d bytes)", - (int)value_length); + "hdrcharset attribute is unreasonably large (%llu bytes)", + (unsigned long long)value_length); err = ARCHIVE_WARN; } __archive_read_consume(a, value_length); @@ -2838,7 +2860,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent /* - * parse a decimal time value, which may include a fractional portion + * Parse a decimal time value, which may include a fractional portion + * + * Sets ps to INT64_MIN on error. */ static void pax_time(const char *p, size_t length, int64_t *ps, long *pn) @@ -2854,6 +2878,7 @@ pax_time(const char *p, size_t length, int64_t *ps, long *pn) if (length <= 0) { *ps = 0; + *pn = 0; return; } s = 0; @@ -2867,8 +2892,9 @@ pax_time(const char *p, size_t length, int64_t *ps, long *pn) digit = *p - '0'; if (s > limit || (s == limit && digit > last_digit_limit)) { - s = INT64_MAX; - break; + *ps = INT64_MIN; + *pn = 0; + return; } s = (s * 10) + digit; ++p; @@ -3229,12 +3255,10 @@ gnu_sparse_10_atol(struct archive_read *a, struct tar *tar, * Returns length (in bytes) of the sparse data description * that was read. */ -static ssize_t +static int64_t gnu_sparse_10_read(struct archive_read *a, struct tar *tar, int64_t *unconsumed) { - ssize_t bytes_read; - int entries; - int64_t offset, size, to_skip, remaining; + int64_t bytes_read, entries, offset, size, to_skip, remaining; /* Clear out the existing sparse list. */ gnu_clear_sparse_list(tar); @@ -3242,7 +3266,7 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, int64_t *unconsumed) remaining = tar->entry_bytes_remaining; /* Parse entries. */ - entries = (int)gnu_sparse_10_atol(a, tar, &remaining, unconsumed); + entries = gnu_sparse_10_atol(a, tar, &remaining, unconsumed); if (entries < 0) return (ARCHIVE_FATAL); /* Parse the individual entries. */ @@ -3260,14 +3284,14 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, int64_t *unconsumed) } /* Skip rest of block... */ tar_flush_unconsumed(a, unconsumed); - bytes_read = (ssize_t)(tar->entry_bytes_remaining - remaining); + bytes_read = tar->entry_bytes_remaining - remaining; to_skip = 0x1ff & -bytes_read; /* Fail if tar->entry_bytes_remaing would get negative */ if (to_skip > remaining) return (ARCHIVE_FATAL); if (to_skip != __archive_read_consume(a, to_skip)) return (ARCHIVE_FATAL); - return ((ssize_t)(bytes_read + to_skip)); + return (bytes_read + to_skip); } /* diff --git a/libarchive/archive_string_sprintf.c b/libarchive/archive_string_sprintf.c index c785e12bdf6d..1c5910e0b2d3 100644 --- a/libarchive/archive_string_sprintf.c +++ b/libarchive/archive_string_sprintf.c @@ -116,8 +116,14 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt, long_flag = '\0'; switch(*p) { - case 'j': case 'l': + if (p[1] == 'l') { + long_flag = 'L'; + p += 2; + break; + } + __LA_FALLTHROUGH; + case 'j': case 'z': long_flag = *p; p++; @@ -136,6 +142,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt, switch(long_flag) { case 'j': s = va_arg(ap, intmax_t); break; case 'l': s = va_arg(ap, long); break; + case 'L': s = va_arg(ap, long long); break; case 'z': s = va_arg(ap, ssize_t); break; default: s = va_arg(ap, int); break; } @@ -144,6 +151,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt, case 's': switch(long_flag) { case 'l': + case 'L': pw = va_arg(ap, wchar_t *); if (pw == NULL) pw = L"(null)"; @@ -172,6 +180,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt, switch(long_flag) { case 'j': u = va_arg(ap, uintmax_t); break; case 'l': u = va_arg(ap, unsigned long); break; + case 'L': u = va_arg(ap, unsigned long long); break; case 'z': u = va_arg(ap, size_t); break; default: u = va_arg(ap, unsigned int); break; } diff --git a/libarchive/archive_util.c b/libarchive/archive_util.c index 3a8caad5262b..900abd0c3c62 100644 --- a/libarchive/archive_util.c +++ b/libarchive/archive_util.c @@ -77,7 +77,9 @@ #define O_CLOEXEC 0 #endif -static int archive_utility_string_sort_helper(char **, unsigned int); +#if ARCHIVE_VERSION_NUMBER < 4000000 +static int __LA_LIBC_CC archive_utility_string_sort_helper(const void *, const void *); +#endif /* Generic initialization of 'struct archive' objects. */ int @@ -629,74 +631,28 @@ __archive_ensure_cloexec_flag(int fd) #endif } +#if ARCHIVE_VERSION_NUMBER < 4000000 /* - * Utility function to sort a group of strings using quicksort. + * Utility functions to sort a group of strings using quicksort. */ static int -archive_utility_string_sort_helper(char **strings, unsigned int n) +__LA_LIBC_CC +archive_utility_string_sort_helper(const void *p1, const void *p2) { - unsigned int i, lesser_count, greater_count; - char **lesser, **greater, **tmp, *pivot; - int retval1, retval2; - - /* A list of 0 or 1 elements is already sorted */ - if (n <= 1) - return (ARCHIVE_OK); - - lesser_count = greater_count = 0; - lesser = greater = NULL; - pivot = strings[0]; - for (i = 1; i < n; i++) - { - if (strcmp(strings[i], pivot) < 0) - { - lesser_count++; - tmp = realloc(lesser, lesser_count * sizeof(*tmp)); - if (!tmp) { - free(greater); - free(lesser); - return (ARCHIVE_FATAL); - } - lesser = tmp; - lesser[lesser_count - 1] = strings[i]; - } - else - { - greater_count++; - tmp = realloc(greater, greater_count * sizeof(*tmp)); - if (!tmp) { - free(greater); - free(lesser); - return (ARCHIVE_FATAL); - } - greater = tmp; - greater[greater_count - 1] = strings[i]; - } - } + const char * const * const s1 = p1; + const char * const * const s2 = p2; - /* quicksort(lesser) */ - retval1 = archive_utility_string_sort_helper(lesser, lesser_count); - for (i = 0; i < lesser_count; i++) - strings[i] = lesser[i]; - free(lesser); - - /* pivot */ - strings[lesser_count] = pivot; - - /* quicksort(greater) */ - retval2 = archive_utility_string_sort_helper(greater, greater_count); - for (i = 0; i < greater_count; i++) - strings[lesser_count + 1 + i] = greater[i]; - free(greater); - - return (retval1 < retval2) ? retval1 : retval2; + return strcmp(*s1, *s2); } int archive_utility_string_sort(char **strings) { - unsigned int size = 0; - while (strings[size] != NULL) + size_t size = 0; + while (strings[size] != NULL) size++; - return archive_utility_string_sort_helper(strings, size); + qsort(strings, size, sizeof(char *), + archive_utility_string_sort_helper); + return (ARCHIVE_OK); } +#endif diff --git a/libarchive/archive_version_details.c b/libarchive/archive_version_details.c index 186e53e50c84..0cf92db73194 100644 --- a/libarchive/archive_version_details.c +++ b/libarchive/archive_version_details.c @@ -134,31 +134,31 @@ archive_libb2_version(struct archive_string* str) static void archive_crypto_version(struct archive_string* str) { -#if defined(ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto) || defined(ARCHIVE_DIGEST_USE_Apple_CommonCrypto) +#if defined(ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto) archive_strcat(str, " CommonCrypto/"); archive_strcat(str, archive_commoncrypto_version()); #endif -#if defined(ARCHIVE_CRYPTOR_USE_CNG) || defined(ARCHIVE_DIGEST_USE_CNG) +#if defined(ARCHIVE_CRYPTOR_USE_CNG) archive_strcat(str, " cng/"); archive_strcat(str, archive_cng_version()); #endif -#if defined(ARCHIVE_CRYPTOR_USE_MBED) || defined(ARCHIVE_DIGEST_USE_MBED) +#if defined(ARCHIVE_CRYPTOR_USE_MBED) archive_strcat(str, " mbedtls/"); archive_strcat(str, archive_mbedtls_version()); #endif -#if defined(ARCHIVE_CRYPTOR_USE_NETTLE) || defined(ARCHIVE_DIGEST_USE_NETTLE) +#if defined(ARCHIVE_CRYPTOR_USE_NETTLE) archive_strcat(str, " nettle/"); archive_strcat(str, archive_nettle_version()); #endif -#if defined(ARCHIVE_CRYPTOR_USE_OPENSSL) || defined(ARCHIVE_DIGEST_USE_OPENSSL) +#if defined(ARCHIVE_CRYPTOR_USE_OPENSSL) archive_strcat(str, " openssl/"); archive_strcat(str, archive_openssl_version()); #endif -#if defined(ARCHIVE_CRYPTOR_USE_LIBMD) || defined(ARCHIVE_DIGEST_USE_LIBMD) +#if defined(ARCHIVE_CRYPTOR_USE_LIBMD) archive_strcat(str, " libmd/"); archive_strcat(str, archive_libmd_version()); #endif -#if defined(ARCHIVE_CRYPTOR_USE_WINCRYPT) || defined(ARCHIVE_DIGEST_USE_WINCRYPT) +#if defined(ARCHIVE_CRYPTOR_USE_WINCRYPT) archive_strcat(str, " WinCrypt/"); archive_strcat(str, archive_wincrypt_version()); #endif @@ -439,11 +439,11 @@ archive_wincrypt_version(void) if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) return NULL; } - DWORD length, version; - if (!CryptGetProvParam(prov, PP_VERSION, &version, &length, 0)) { + DWORD version, length = sizeof(version); + if (!CryptGetProvParam(prov, PP_VERSION, (BYTE *)&version, &length, 0)) { return NULL; } else { - char major = version >> 8; + char major = (version >> 8) & 0xFF; char minor = version & 0xFF; static char wincrypt_version[6]; snprintf(wincrypt_version, 6, "%hhd.%hhd", major, minor); diff --git a/libarchive/archive_write_disk_windows.c b/libarchive/archive_write_disk_windows.c index c9f10a8ae793..c7339c4ec1b1 100644 --- a/libarchive/archive_write_disk_windows.c +++ b/libarchive/archive_write_disk_windows.c @@ -408,7 +408,11 @@ permissive_name_w(struct archive_write_disk *a) wn = _wcsdup(wnp); if (wn == NULL) return (-1); - archive_wstring_ensure(&(a->_name_data), 4 + wcslen(wn) + 1); + if (archive_wstring_ensure(&(a->_name_data), + 4 + wcslen(wn) + 1) == NULL) { + free(wn); + return (-1); + } a->name = a->_name_data.s; /* Prepend "\\?\" */ archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4); @@ -438,8 +442,11 @@ permissive_name_w(struct archive_write_disk *a) wn = _wcsdup(wnp); if (wn == NULL) return (-1); - archive_wstring_ensure(&(a->_name_data), - 8 + wcslen(wn) + 1); + if (archive_wstring_ensure(&(a->_name_data), + 8 + wcslen(wn) + 1) == NULL) { + free(wn); + return (-1); + } a->name = a->_name_data.s; /* Prepend "\\?\UNC\" */ archive_wstrncpy(&(a->_name_data), @@ -471,10 +478,16 @@ permissive_name_w(struct archive_write_disk *a) */ if (wnp[0] == L'\\') { wn = _wcsdup(wnp); - if (wn == NULL) + if (wn == NULL) { + free(wsp); + return (-1); + } + if (archive_wstring_ensure(&(a->_name_data), + 4 + 2 + wcslen(wn) + 1) == NULL) { + free(wsp); + free(wn); return (-1); - archive_wstring_ensure(&(a->_name_data), - 4 + 2 + wcslen(wn) + 1); + } a->name = a->_name_data.s; /* Prepend "\\?\" and drive name. */ archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4); @@ -486,9 +499,16 @@ permissive_name_w(struct archive_write_disk *a) } wn = _wcsdup(wnp); - if (wn == NULL) + if (wn == NULL) { + free(wsp); return (-1); - archive_wstring_ensure(&(a->_name_data), 4 + l + 1 + wcslen(wn) + 1); + } + if (archive_wstring_ensure(&(a->_name_data), + 4 + l + 1 + wcslen(wn) + 1) == NULL) { + free(wsp); + free(wn); + return (-1); + } a->name = a->_name_data.s; /* Prepend "\\?\" and drive name if not already added. */ if (l > 3 && wsp[0] == L'\\' && wsp[1] == L'\\' && diff --git a/libarchive/archive_write_set_format_iso9660.c b/libarchive/archive_write_set_format_iso9660.c index 3c5b8899434e..c275c1ec92b9 100644 --- a/libarchive/archive_write_set_format_iso9660.c +++ b/libarchive/archive_write_set_format_iso9660.c @@ -1167,7 +1167,12 @@ archive_write_set_format_iso9660(struct archive *_a) iso9660->primary.rootent->parent = iso9660->primary.rootent; iso9660->cur_dirent = iso9660->primary.rootent; archive_string_init(&(iso9660->cur_dirstr)); - archive_string_ensure(&(iso9660->cur_dirstr), 1); + if (archive_string_ensure(&(iso9660->cur_dirstr), 1) == NULL) { + free(iso9660); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } iso9660->cur_dirstr.s[0] = 0; iso9660->sconv_to_utf16be = NULL; iso9660->sconv_from_utf16be = NULL; @@ -5666,9 +5671,15 @@ isoent_tree(struct archive_write *a, struct isoent **isoentpp) * inserted. */ iso9660->cur_dirent = dent; archive_string_empty(&(iso9660->cur_dirstr)); - archive_string_ensure(&(iso9660->cur_dirstr), + if (archive_string_ensure(&(iso9660->cur_dirstr), archive_strlen(&(dent->file->parentdir)) + - archive_strlen(&(dent->file->basename)) + 2); + archive_strlen(&(dent->file->basename)) + 2) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + _isoent_free(isoent); + *isoentpp = NULL; + return (ARCHIVE_FATAL); + } if (archive_strlen(&(dent->file->parentdir)) + archive_strlen(&(dent->file->basename)) == 0) iso9660->cur_dirstr.s[0] = 0; diff --git a/libarchive/archive_write_set_format_mtree.c b/libarchive/archive_write_set_format_mtree.c index c2ecc424675b..02fbb2d2f555 100644 --- a/libarchive/archive_write_set_format_mtree.c +++ b/libarchive/archive_write_set_format_mtree.c @@ -2209,9 +2209,13 @@ mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep) * inserted. */ mtree->cur_dirent = dent; archive_string_empty(&(mtree->cur_dirstr)); - archive_string_ensure(&(mtree->cur_dirstr), + if (archive_string_ensure(&(mtree->cur_dirstr), archive_strlen(&(dent->parentdir)) + - archive_strlen(&(dent->basename)) + 2); + archive_strlen(&(dent->basename)) + 2) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } if (archive_strlen(&(dent->parentdir)) + archive_strlen(&(dent->basename)) == 0) mtree->cur_dirstr.s[0] = 0; diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt index ffdb5b4ef7c5..b5acb468c4c9 100644 --- a/libarchive/test/CMakeLists.txt +++ b/libarchive/test/CMakeLists.txt @@ -174,8 +174,10 @@ IF(ENABLE_TEST) test_read_format_tar_empty_pax.c test_read_format_tar_filename.c test_read_format_tar_invalid_pax_size.c + test_read_format_tar_mac_metadata.c test_read_format_tar_pax_g_large.c test_read_format_tar_pax_large_attr.c + test_read_format_tar_pax_negative_time.c test_read_format_tbz.c test_read_format_tgz.c test_read_format_tlz.c @@ -208,6 +210,7 @@ IF(ENABLE_TEST) test_read_format_zip_zip64.c test_read_format_zip_with_invalid_traditional_eocd.c test_read_large.c + test_read_pax_empty_val_no_nl.c test_read_pax_xattr_rht_security_selinux.c test_read_pax_xattr_schily.c test_read_pax_truncated.c diff --git a/libarchive/test/test_entry.c b/libarchive/test/test_entry.c index 38c406e35b5a..9b21b83ecdfb 100644 --- a/libarchive/test/test_entry.c +++ b/libarchive/test/test_entry.c @@ -436,7 +436,7 @@ DEFINE_TEST(test_entry) archive_entry_fflags(e, &set, &clear); assertEqualInt(UF_HIDDEN, set); assertEqualInt(UF_NODUMP | UF_IMMUTABLE | UF_APPEND, clear); -#elif defined(_WIN32) && !defined(CYGWIN) +#elif defined(_WIN32) && !defined(__CYGWIN__) archive_entry_copy_fflags_text_w(e, L"rdonly,hidden,nosystem"); archive_entry_fflags(e, &set, &clear); assertEqualInt(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN, set); diff --git a/libarchive/test/test_read_disk_directory_traversals.c b/libarchive/test/test_read_disk_directory_traversals.c index 009c9a8db1e1..7597f4b6f6eb 100644 --- a/libarchive/test/test_read_disk_directory_traversals.c +++ b/libarchive/test/test_read_disk_directory_traversals.c @@ -39,7 +39,7 @@ atimeIsUpdated(void) { const char *fn = "fs_noatime"; struct stat st; -#if defined(_WIN32) && !defined(CYGWIN) +#if defined(_WIN32) && !defined(__CYGWIN__) char *buff = NULL; char *ptr; int r; diff --git a/libarchive/test/test_read_format_gtar_sparse_skip_entry.tar.Z.uu b/libarchive/test/test_read_format_gtar_sparse_skip_entry.tar.Z.uu index 634ac0673db7..1aff5d386bdb 100644 --- a/libarchive/test/test_read_format_gtar_sparse_skip_entry.tar.Z.uu +++ b/libarchive/test/test_read_format_gtar_sparse_skip_entry.tar.Z.uu @@ -1,15 +1,15 @@ begin 644 test_read_format_gtar_sparse_skip_entry.tar.Z M'YV04,+@05(F#)DR<EZ$`<"PH<.'$"-*G$BQHL6*,#+:L$$#!(",,6[4@.$1 MI$B2'S.JS#A#A@P0,63,L`$C!HP9-VB\K"FCAHT8`$#@N4BTJ-&C2"/6F4,G -MC)R48^J424HQZE2J$E=F+*G5(]:O8,.*'3M6!LDY:?24Z6'S!DX:,7#(H$%# -MP0R2;>BD:;,V!@T8-6)NE&'#10T<-#;>R(%CAEV28_3R9?LW\(P8-F[`<#%C -M)@T<->#6>`PBC.2^E07;J#'#Q>J-F5DJ<`GBB),J+N;`<3JGC(LV8=2\D<-V -M]DO;N'7S]MTFC9OA/6#,CE'[=N[=<GJ[<!-F<AB[-:HGQZY=3D$V:-6RA>$V -M9]RY=<G*GT^_OOW[^/.#13Z%?!DC:;!1AD+Z%6B12AMUE%)((W'%($I:U603 -M#!W%-%---^6T4PPM8184#`:&"-9233V5D57SH2A?A%RMY)6(,,8HHPP*2/=7 -M#C8HT-9;[_VE0'PR!BGDD$06:>212"9YD1EOO*&`DE!&*>645%9IY9589JGE +MC)R48^J424HQZE2J$E=F+*G5(]:O8,.*'3M6!LDY:?24Z:$U(XV?,A3,(-F& +M3IHV:V/0@%$CYD89-ES4P/'6QHT<.&;()3G&+MX>>OG&F!'#,`P7,V;2P%&# +M1HP:BT&$<9QW;U_`-FK,<)%ZH^6;"ER"..*DBHLY<)S.*>.B31@U;^1`COV2 +MMFW<NGFW2>,F.-O8,6;7OIU;SFX7;L(\#B.WAO3CU:_+*<@&K5K(,&[@](Q# +M!@T:"LC*GT^_OOW[^/.#-3XE?!DC:;!1AD+Z%6B12AMUE%)((W'%($IMK=11 +M3#/5=%-..TTF@UY!P6#@AV`MU=13&5DUGXGRM<752EZ!Z.*+,,8%@P)[Y6"# +M`C:IEU,,[>TE5WPP!BGDD$06:>212"9YD1EOO`&DDE!&*>645%9IY9589JGE MEEQVZ>678(8IYIADEFGFF6BFJ>::;+;IYIMPQBGGG'36:>>=>.:IYYY\]NGG -MGX`&*NB@A!9JJ)YB](D@1PZ>U&B#*468484RT11###7<8!8(&-)4PX=^DN@4 -B5%*E6.J*746JTHN'2LFDDZW&*NNLM-9JZZVXYJKKKKR&!0`` +MGX`&*NB@A!9J*)YB](D@1PZ>U&B#*44(PX0RT13#9S>8!8*%--70H9\B.@65 +A5">2FF)7D:K4XJ%2,NDDJ[#&*NNLM-9JZZVXYJKKKF$! ` end diff --git a/libarchive/test/test_read_format_rar5.c b/libarchive/test/test_read_format_rar5.c index 696975354565..fd233277bc1b 100644 --- a/libarchive/test/test_read_format_rar5.c +++ b/libarchive/test/test_read_format_rar5.c @@ -1126,7 +1126,7 @@ DEFINE_TEST(test_read_format_rar5_fileattr) archive_entry_fflags(ae, &set, &clear); #if defined(__FreeBSD__) flag = UF_READONLY; -#elif defined(_WIN32) && !defined(CYGWIN) +#elif defined(_WIN32) && !defined(__CYGWIN__) flag = FILE_ATTRIBUTE_READONLY; #endif assertEqualInt(flag, set & flag); @@ -1138,7 +1138,7 @@ DEFINE_TEST(test_read_format_rar5_fileattr) archive_entry_fflags(ae, &set, &clear); #if defined(__FreeBSD__) flag = UF_HIDDEN; -#elif defined(_WIN32) && !defined(CYGWIN) +#elif defined(_WIN32) && !defined(__CYGWIN__) flag = FILE_ATTRIBUTE_HIDDEN; #endif assertEqualInt(flag, set & flag); @@ -1150,7 +1150,7 @@ DEFINE_TEST(test_read_format_rar5_fileattr) archive_entry_fflags(ae, &set, &clear); #if defined(__FreeBSD__) flag = UF_SYSTEM; -#elif defined(_WIN32) && !defined(CYGWIN) +#elif defined(_WIN32) && !defined(__CYGWIN__) flag = FILE_ATTRIBUTE_SYSTEM; #endif assertEqualInt(flag, set & flag); @@ -1162,7 +1162,7 @@ DEFINE_TEST(test_read_format_rar5_fileattr) archive_entry_fflags(ae, &set, &clear); #if defined(__FreeBSD__) flag = UF_READONLY | UF_HIDDEN; -#elif defined(_WIN32) && !defined(CYGWIN) +#elif defined(_WIN32) && !defined(__CYGWIN__) flag = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN; #endif assertEqualInt(flag, set & flag); @@ -1174,7 +1174,7 @@ DEFINE_TEST(test_read_format_rar5_fileattr) archive_entry_fflags(ae, &set, &clear); #if defined(__FreeBSD__) flag = UF_READONLY; -#elif defined(_WIN32) && !defined(CYGWIN) +#elif defined(_WIN32) && !defined(__CYGWIN__) flag = FILE_ATTRIBUTE_READONLY; #endif assertEqualInt(flag, set & flag); @@ -1186,7 +1186,7 @@ DEFINE_TEST(test_read_format_rar5_fileattr) archive_entry_fflags(ae, &set, &clear); #if defined(__FreeBSD__) flag = UF_HIDDEN; -#elif defined(_WIN32) && !defined(CYGWIN) +#elif defined(_WIN32) && !defined(__CYGWIN__) flag = FILE_ATTRIBUTE_HIDDEN; #endif assertEqualInt(flag, set & flag); @@ -1198,7 +1198,7 @@ DEFINE_TEST(test_read_format_rar5_fileattr) archive_entry_fflags(ae, &set, &clear); #if defined(__FreeBSD__) flag = UF_SYSTEM; -#elif defined(_WIN32) && !defined(CYGWIN) +#elif defined(_WIN32) && !defined(__CYGWIN__) flag = FILE_ATTRIBUTE_SYSTEM; #endif assertEqualInt(flag, set & flag); @@ -1210,7 +1210,7 @@ DEFINE_TEST(test_read_format_rar5_fileattr) archive_entry_fflags(ae, &set, &clear); #if defined(__FreeBSD__) flag = UF_READONLY | UF_HIDDEN; -#elif defined(_WIN32) && !defined(CYGWIN) +#elif defined(_WIN32) && !defined(__CYGWIN__) flag = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN; #endif assertEqualInt(flag, set & flag); diff --git a/libarchive/test/test_read_format_tar_mac_metadata.c b/libarchive/test/test_read_format_tar_mac_metadata.c new file mode 100644 index 000000000000..b4745a22ee3b --- /dev/null +++ b/libarchive/test/test_read_format_tar_mac_metadata.c @@ -0,0 +1,85 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Zhaofeng Li + * All rights reserved. + */ +#include "test.h" + +DEFINE_TEST(test_read_format_tar_mac_metadata) +{ + /* + This test tar file is crafted with two files in a specific order: + + 1. A ._-prefixed file with pax header containing the path attribute. + 2. A file with a pax header but without the path attribute. + + It's designed to trigger the case encountered in: + <https://github.com/libarchive/libarchive/pull/2636> + + GNU tar is required to reproduce this tar file: + + ```sh + NAME1="._101_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + NAME2="goodname" + OUT="test_read_format_tar_mac_metadata_1.tar" + + echo "content of badname" >"${NAME1}" + echo "content of goodname" >"${NAME2}" + + rm -f "${OUT}" + gnutar \ + --mtime="@0" \ + --owner=0 --group=0 --numeric-owner \ + --pax-option=exthdr.name=%d/PaxHeaders/%f,atime:=0,ctime:=0,foo:=bar \ + --format=pax \ + -cf "${OUT}" \ + "${NAME1}" \ + "${NAME2}" + uuencode "${OUT}" "${OUT}" >"${OUT}.uu" + + sha256sum "${OUT}" + sha256sum "${OUT}.uu" + ``` + */ + const char *refname = "test_read_format_tar_mac_metadata_1.tar"; + char *p; + size_t s; + struct archive *a; + struct archive_entry *ae; + + /* + * This is not a valid AppleDouble metadata file. It is merely to test that + * the correct bytes are read. + */ + const unsigned char appledouble[] = { + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x62, + 0x61, 0x64, 0x6e, 0x61, 0x6d, 0x65, 0x0a + }; + + extract_reference_file(refname); + p = slurpfile(&s, "%s", refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_tar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_set_option(a, "tar", "mac-ext", "1")); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 1)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + + /* Correct name and metadata bytes */ + assertEqualString("goodname", archive_entry_pathname(ae)); + + const void *metadata = archive_entry_mac_metadata(ae, &s); + if (assert(metadata != NULL)) { + assertEqualMem(metadata, appledouble, + sizeof(appledouble)); + } + + /* ... and nothing else */ + 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)); + + free(p); +} diff --git a/libarchive/test/test_read_format_tar_mac_metadata_1.tar.uu b/libarchive/test/test_read_format_tar_mac_metadata_1.tar.uu new file mode 100644 index 000000000000..20b2cf5efe26 --- /dev/null +++ b/libarchive/test/test_read_format_tar_mac_metadata_1.tar.uu @@ -0,0 +1,231 @@ +begin 644 test_read_format_tar_mac_metadata_1.tar +M+B]087A(96%D97)S+RY?,3`Q7V%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A83`P,#`V-#0`,#`P,#`P,``P,#`P,#`P`#`P,#`P,#`P,C(P +M`#`P,#`P,#`P,#`P`#`S,#,Q,0`@>``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!U<W1A<@`P,``````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````Q,3$@<&%T:#TN7S$P,5]A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A80HQ,2!F;V\] +M8F%R"C$Q(&-T:6UE/3`*,3$@871I;64],`H````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````"Y?,3`Q7V%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A +M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86$P +M,#`P-C0T`#`P,#`P,#``,#`P,#`P,``P,#`P,#`P,#`R,P`P,#`P,#`P,#`P +M,``P,S`S-S8`(#`````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````=7-T87(`,#`````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````8V]N=&5N="!O9B!B861N86UE"@`````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````N+U!A>$AE861E<G,O9V]O9&YA;64` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````,#`P,#8T-``P,#`P +M,#`P`#`P,#`P,#``,#`P,#`P,#`P-#$`,#`P,#`P,#`P,#``,#$Q-S0U`"!X +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````'5S=&%R`#`P```````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````#$Q(&9O +M;SUB87(*,3$@8W1I;64],`HQ,2!A=&EM93TP"@`````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````9V]O9&YA;64````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````#`P,#`V-#0`,#`P,#`P,``P,#`P,#`P +M`#`P,#`P,#`P,#(T`#`P,#`P,#`P,#`P`#`P-S0U-0`@,``````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````````````!U +M<W1A<@`P,``````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````!C;VYT96YT(&]F(&=O;V1N +M86UE"@`````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +9```````````````````````````````````` +` +end diff --git a/libarchive/test/test_read_format_tar_pax_negative_time.c b/libarchive/test/test_read_format_tar_pax_negative_time.c new file mode 100644 index 000000000000..b4edc3c2d951 --- /dev/null +++ b/libarchive/test/test_read_format_tar_pax_negative_time.c @@ -0,0 +1,68 @@ +/*- + * Copyright (c) 2025 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" + +/* + * Read a pax formatted tar archive that has a negative modification time. + */ +DEFINE_TEST(test_read_format_tar_pax_negative_time) +{ + char name[] = "test_read_format_tar_pax_negative_time.tar"; + struct archive_entry *ae; + struct archive *a; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); + + /* Read first entry. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("empty", archive_entry_pathname(ae)); + assertEqualInt(-2146608000, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_atime_nsec(ae)); + assertEqualInt(1748089464, archive_entry_ctime(ae)); + assertEqualInt(951928467, archive_entry_ctime_nsec(ae)); + assertEqualInt(-2146608000, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_uid(ae)); + assertEqualString("root", archive_entry_uname(ae)); + assertEqualInt(0, archive_entry_gid(ae)); + assertEqualString("root", archive_entry_gname(ae)); + assertEqualInt(0100644, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + 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)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_format_tar_pax_negative_time.tar.uu b/libarchive/test/test_read_format_tar_pax_negative_time.tar.uu new file mode 100644 index 000000000000..fdf3fc304bc8 --- /dev/null +++ b/libarchive/test/test_read_format_tar_pax_negative_time.tar.uu @@ -0,0 +1,60 @@ +begin 644 test_read_format_tar_pax_negative_time.tar +M4&%X2&5A9&5R+V5M<'1Y```````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#8T-"``,#`P,#`P(``P,#`P,#`@`#`P,#`P,#`P,3$P +M(#`P,#`P,#`P,#`P(#`Q-#`Q-P`@>``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!U<W1A<@`P,')O;W0` +M````````````````````````````````````<F]O=``````````````````` +M```````````````````P,#`P,#`@`#`P,#`P,"`````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````S,"!C=&EM93TQ-S0X,#@Y-#8T+CDU,3DR.#0V +M-PHR,2!A=&EM93TM,C$T-C8P.#`P,`HR,2!M=&EM93TM,C$T-C8P.#`P,`H` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````&5M<'1Y```````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````P +M,#`V-#0@`#`P,#`P,"``,#`P,#`P(``P,#`P,#`P,#`P,"#_________@`U< +M@"`P,34Q-C8`(#`````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````=7-T87(`,#!R;V]T```````````````` +M`````````````````````')O;W0````````````````````````````````` +M````,#`P,#`P(``P,#`P,#`@```````````````````````````````````` +M```````````````````````````````````````````````````````````` +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```````````````````````````````````````````````````````` +` +end diff --git a/libarchive/test/test_read_pax_empty_val_no_nl.c b/libarchive/test/test_read_pax_empty_val_no_nl.c new file mode 100644 index 000000000000..f985488754fd --- /dev/null +++ b/libarchive/test/test_read_pax_empty_val_no_nl.c @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2025 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" + +/* + * Read a pax formatted tar archive that contains an invalid attribute, + * because it does not end in a newline. Additionally, value is empty. + * The pax reader should stop and tar reader should continue with warning. + */ +DEFINE_TEST(test_read_pax_empty_val_no_nl) +{ + char name[] = "test_read_pax_empty_val_no_nl.tar"; + struct archive_entry *ae; + struct archive *a; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); + + /* Read first entry. */ + assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae)); + assertEqualString("empty", archive_entry_pathname(ae)); + assertEqualInt(1748163748, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_uid(ae)); + assertEqualString("root", archive_entry_uname(ae)); + assertEqualInt(0, archive_entry_gid(ae)); + assertEqualString("root", archive_entry_gname(ae)); + assertEqualInt(0100600, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + 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)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_pax_empty_val_no_nl.tar.uu b/libarchive/test/test_read_pax_empty_val_no_nl.tar.uu new file mode 100644 index 000000000000..5de8b25ecccd --- /dev/null +++ b/libarchive/test/test_read_pax_empty_val_no_nl.tar.uu @@ -0,0 +1,60 @@ +begin 600 test_read_pax_empty_val_no_nl.tar +M4&%X2&5A9&5R+V5M<'1Y```````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#8P,"``,#`P,#`P(``P,#`P,#`@`#`P,#`P,#`P,#`T +M(#$U,#$T-34V,C0T(#`Q-#`U-@`@>``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!U<W1A<@`P,')O;W0` +M````````````````````````````````````<F]O=``````````````````` +M```````````````````P,#`P,#`@`#`P,#`P,"`````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````T('@]```````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````H````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````&5M<'1Y```````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````P +M,#`V,#`@`#`P,#`P,"``,#`P,#`P(``P,#`P,#`P,#`P,"`Q-3`Q-#4U-C(T +M-"`P,3(Q,#$`(#`````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````=7-T87(`,#!R;V]T```````````````` +M`````````````````````')O;W0````````````````````````````````` +M````,#`P,#`P(``P,#`P,#`@```````````````````````````````````` +M```````````````````````````````````````````````````````````` +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```````````````````````````````````````````````````````` +` +end diff --git a/tar/test/test_list_item.c b/tar/test/test_list_item.c index df64acfada40..fd131c475275 100644 --- a/tar/test/test_list_item.c +++ b/tar/test/test_list_item.c @@ -43,54 +43,8 @@ static const char *tvf_out = "-rw-r--r-- 0 1000 1000 0 Jan 1 1980 f\n"; #endif -static void -set_lc_time(const char * str) -{ - -#if defined(_WIN32) && !defined(__CYGWIN__) - if (!SetEnvironmentVariable("LC_TIME", str)) { - fprintf(stderr, "SetEnvironmentVariable failed with %d\n", - (int)GetLastError()); - } -#else - if (setenv("LC_TIME", str, 1) == -1) - fprintf(stderr, "setenv: %s\n", strerror(errno)); -#endif -} - -static int -run_tvf(void) -{ - char * orig_lc_time; - char * lc_time; - int exact_tvf_check; - - orig_lc_time = getenv("LC_TIME"); - - /* Try to set LC_TIME to known (English) dates. */ - set_lc_time("en_US.UTF-8"); - - /* Check if we've got the right LC_TIME; if not, don't check output. */ - lc_time = getenv("LC_TIME"); - if ((lc_time != NULL) && strcmp(lc_time, "en_US.UTF-8") == 0) - exact_tvf_check = 1; - else - exact_tvf_check = 0; - - assertEqualInt(0, - systemf("%s tvf test_list_item.tar >tvf.out 2>tvf.err", testprog)); - - /* Restore the original date formatting. */ - if (orig_lc_time != NULL) - set_lc_time(orig_lc_time); - - return (exact_tvf_check); -} - DEFINE_TEST(test_list_item) { - int exact_tvf_check; - extract_reference_file("test_list_item.tar"); /* Run 'tf' and check output. */ @@ -100,16 +54,10 @@ DEFINE_TEST(test_list_item) assertTextFileContents(tf_out, "tf.out"); assertEmptyFile("tf.err"); - /* Run 'tvf'. */ - exact_tvf_check = run_tvf(); - - /* Check 'tvf' output. */ + /* Run 'tvf' and check output. */ + assertEqualInt(0, + systemf("%s tvf test_list_item.tar >tvf.out 2>tvf.err", testprog)); failure("'t' mode with 'v' should write more results to stdout"); + assertTextFileContents(tvf_out, "tvf.out"); assertEmptyFile("tvf.err"); - if (exact_tvf_check) - assertTextFileContents(tvf_out, "tvf.out"); - else { - /* The 'skipping' macro requires braces. */ - skipping("Can't check exact tvf output"); - } } diff --git a/tar/test/test_option_C_mtree.c b/tar/test/test_option_C_mtree.c index b6ab159941d8..6cbac38fcac5 100644 --- a/tar/test/test_option_C_mtree.c +++ b/tar/test/test_option_C_mtree.c @@ -17,7 +17,7 @@ DEFINE_TEST(test_option_C_mtree) p0 = NULL; char *content = "./foo type=file uname=root gname=root mode=0755\n"; char *filename = "output.tar"; -#if defined(_WIN32) && !defined(CYGWIN) +#if defined(_WIN32) && !defined(__CYGWIN__) char *p; #endif @@ -32,7 +32,7 @@ DEFINE_TEST(test_option_C_mtree) assertMakeDir("bar", 0775); assertMakeFile("bar/foo", 0777, "abc"); -#if defined(_WIN32) && !defined(CYGWIN) +#if defined(_WIN32) && !defined(__CYGWIN__) p = absolute_path; while(*p != '\0') { if (*p == '/') diff --git a/test_utils/test_main.c b/test_utils/test_main.c index f4456256c1a9..afd077fc6d0b 100644 --- a/test_utils/test_main.c +++ b/test_utils/test_main.c @@ -2456,7 +2456,7 @@ void assertVersion(const char *prog, const char *base) /* Skip arbitrary third-party version numbers. */ while (s > 0 && (*q == ' ' || *q == '-' || *q == '/' || *q == '.' || - isalnum((unsigned char)*q))) { + *q == '_' || isalnum((unsigned char)*q))) { ++q; --s; } @@ -3555,6 +3555,59 @@ test_summarize(int failed, int skips_num) } /* + * Set or unset environment variable. + */ +static void +set_environment(const char *key, const char *value) +{ + +#if defined(_WIN32) && !defined(__CYGWIN__) + if (!SetEnvironmentVariable(key, value)) { + fprintf(stderr, "SetEnvironmentVariable failed with %d\n", + (int)GetLastError()); + } +#else + if (value == NULL) { + if (unsetenv(key) == -1) + fprintf(stderr, "unsetenv: %s\n", strerror(errno)); + } else { + if (setenv(key, value, 1) == -1) + fprintf(stderr, "setenv: %s\n", strerror(errno)); + } +#endif +} + +/* + * Enforce C locale for (sub)processes. + */ +static void +set_c_locale() +{ + static const char *lcs[] = { + "LC_ADDRESS", + "LC_ALL", + "LC_COLLATE", + "LC_CTYPE", + "LC_IDENTIFICATION", + "LC_MEASUREMENT", + "LC_MESSAGES", + "LC_MONETARY", + "LC_NAME", + "LC_NUMERIC", + "LC_PAPER", + "LC_TELEPHONE", + "LC_TIME", + NULL + }; + size_t i; + + setlocale(LC_ALL, "C"); + set_environment("LANG", "C"); + for (i = 0; lcs[i] != NULL; i++) + set_environment(lcs[i], NULL); +} + +/* * Actually run a single test, with appropriate setup and cleanup. */ static int @@ -3629,7 +3682,7 @@ test_run(int i, const char *tmpdir) exit(1); } /* Explicitly reset the locale before each test. */ - setlocale(LC_ALL, "C"); + set_c_locale(); /* Record the umask before we run the test. */ umask(oldumask = umask(0)); /* @@ -3643,7 +3696,7 @@ test_run(int i, const char *tmpdir) /* Restore umask */ umask(oldumask); /* Reset locale. */ - setlocale(LC_ALL, "C"); + set_c_locale(); /* Reset directory. */ if (!assertChdir(tmpdir)) { fprintf(stderr, "ERROR: Couldn't chdir to temp dir %s\n", |