summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt11
-rw-r--r--configure.ac12
-rw-r--r--libarchive/CMakeLists.txt1
-rw-r--r--libarchive/archive.h2
-rw-r--r--libarchive/archive_entry.h2
-rw-r--r--libarchive/archive_read_support_format_rar5.c7
-rw-r--r--libarchive/test/test_read_format_rar5.c25
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();
+}