diff options
-rw-r--r-- | CMakeLists.txt | 11 | ||||
-rw-r--r-- | configure.ac | 12 | ||||
-rw-r--r-- | libarchive/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libarchive/archive.h | 2 | ||||
-rw-r--r-- | libarchive/archive_entry.h | 2 | ||||
-rw-r--r-- | libarchive/archive_read_support_format_rar5.c | 7 | ||||
-rw-r--r-- | libarchive/test/test_read_format_rar5.c | 25 |
7 files changed, 59 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e1ff575..df83ed18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2024,6 +2024,17 @@ CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA512" LIBMD) CHECK_CRYPTO_WIN("MD5;SHA1;SHA256;SHA384;SHA512") +# Check visibility annotations +SET(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") +SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fvisibility=hidden -Werror") +CHECK_C_SOURCE_COMPILES("void __attribute__((visibility(\"default\"))) foo(void); +int main() { return 0; }" HAVE_VISIBILITY_ATTR) +IF (HAVE_VISIBILITY_ATTR) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") + ADD_DEFINITIONS(-D__LIBARCHIVE_ENABLE_VISIBILITY) +ENDIF(HAVE_VISIBILITY_ATTR) +SET(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}") + # Generate "config.h" from "build/cmake/config.h.in" CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) diff --git a/configure.ac b/configure.ac index b30430d2..cc51badc 100644 --- a/configure.ac +++ b/configure.ac @@ -1247,6 +1247,18 @@ case "$host_os" in ;; esac +dnl Visibility annotations... +saved_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -fvisibility=hidden -Werror" +AC_MSG_CHECKING(whether compiler supports visibility annotations) +AC_LINK_IFELSE([AC_LANG_PROGRAM([ + int foo( void ) __attribute__((visibility("default"))); + ])], + [CFLAGS="$saved_CFLAGS -fvisibility=hidden -D__LIBARCHIVE_ENABLE_VISIBILITY"; + AC_MSG_RESULT(yes)], + [CFLAGS="$saved_CFLAGS" + AC_MSG_RESULT(no)]) + # Ensure test directories are present if building out-of-tree AC_CONFIG_COMMANDS([mkdirs], [mkdir -p libarchive/test tar/test cat/test cpio/test]) diff --git a/libarchive/CMakeLists.txt b/libarchive/CMakeLists.txt index 44895ce3..ff7ade00 100644 --- a/libarchive/CMakeLists.txt +++ b/libarchive/CMakeLists.txt @@ -82,6 +82,7 @@ SET(libarchive_SOURCES archive_read_set_format.c archive_read_set_options.c archive_read_support_filter_all.c + archive_read_support_filter_by_code.c archive_read_support_filter_bzip2.c archive_read_support_filter_compress.c archive_read_support_filter_gzip.c diff --git a/libarchive/archive.h b/libarchive/archive.h index 7f58a1f2..dcb8b0df 100644 --- a/libarchive/archive.h +++ b/libarchive/archive.h @@ -120,6 +120,8 @@ typedef ssize_t la_ssize_t; # define __LA_DECL __declspec(dllimport) # endif # endif +#elif defined __LIBARCHIVE_ENABLE_VISIBILITY +# define __LA_DECL __attribute__((visibility("default"))) #else /* Static libraries or non-Windows needs no special declaration. */ # define __LA_DECL diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h index 450b3cf9..e579e9f3 100644 --- a/libarchive/archive_entry.h +++ b/libarchive/archive_entry.h @@ -122,6 +122,8 @@ typedef ssize_t la_ssize_t; # define __LA_DECL __declspec(dllimport) # endif # endif +#elif defined __LIBARCHIVE_ENABLE_VISIBILITY +# define __LA_DECL __attribute__((visibility("default"))) #else /* Static libraries on all platforms and shared libraries on non-Windows. */ # define __LA_DECL diff --git a/libarchive/archive_read_support_format_rar5.c b/libarchive/archive_read_support_format_rar5.c index a3cfa72e..cc966a51 100644 --- a/libarchive/archive_read_support_format_rar5.c +++ b/libarchive/archive_read_support_format_rar5.c @@ -3911,6 +3911,13 @@ static int do_unpack(struct archive_read* a, struct rar5* rar, case GOOD: /* fallthrough */ case BEST: + /* No data is returned here. But because a sparse-file aware + * caller (like archive_read_data_into_fd) may treat zero-size + * as a sparse file block, we need to update the offset + * accordingly. At this point the decoder doesn't have any + * pending uncompressed data blocks, so the current position in + * the output file should be last_write_ptr. */ + if (offset) *offset = rar->cstate.last_write_ptr; return uncompress_file(a); default: archive_set_error(&a->archive, diff --git a/libarchive/test/test_read_format_rar5.c b/libarchive/test/test_read_format_rar5.c index acc90510..0c302897 100644 --- a/libarchive/test/test_read_format_rar5.c +++ b/libarchive/test/test_read_format_rar5.c @@ -1346,4 +1346,27 @@ DEFINE_TEST(test_read_format_rar5_bad_window_size_in_multiarchive_file) while(0 < archive_read_data(a, buf, sizeof(buf))) {} EPILOGUE(); -}
\ No newline at end of file +} + +DEFINE_TEST(test_read_format_rar5_read_data_block_uninitialized_offset) +{ + const void *buf; + size_t size; + la_int64_t offset; + + PROLOGUE("test_read_format_rar5_compressed.rar"); + assertA(0 == archive_read_next_header(a, &ae)); + + /* A real code may pass a pointer to an uninitialized variable as an offset + * output argument. Here we want to check this situation. But because + * relying on a value of an uninitialized variable in a test is not a good + * idea, let's pretend that 0xdeadbeef is a random value of the + * uninitialized variable. */ + offset = 0xdeadbeef; + assertEqualInt(ARCHIVE_OK, archive_read_data_block(a, &buf, &size, &offset)); + /* The test archive doesn't contain a sparse file. And because of that, here + * we assume that the first returned offset should be 0. */ + assertEqualInt(0, offset); + + EPILOGUE(); +} |