Merge branch 'vu862384'
Fixes Issue 656
Fixes CVE-2016-1541
Fixes VU#862384
Fixes TALOS-CAN-155
diff --git a/CMakeLists.txt b/CMakeLists.txt
index eedcd23..4b97039 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -204,7 +204,7 @@
SET(POSIX_REGEX_LIB "AUTO" CACHE STRING "Choose what library should provide POSIX regular expression support")
SET(ENABLE_SAFESEH "AUTO" CACHE STRING "Enable use of /SAFESEH linker flag (MSVC only)")
-SET(WINDOWS_VERSION "" CACHE STRING "Set Windows version to use (Windows only)")
+SET(WINDOWS_VERSION "WIN7" CACHE STRING "Set Windows version to use (Windows only)")
IF(ENABLE_COVERAGE)
include(LibarchiveCodeCoverage)
@@ -216,22 +216,35 @@
IF(WIN32)
IF(WINDOWS_VERSION STREQUAL "WIN8")
+ SET(NTDDI_VERSION 0x06020000)
+ SET(_WIN32_WINNT 0x0602)
SET(WINVER 0x0602)
ELSEIF(WINDOWS_VERSION STREQUAL "WIN7")
+ SET(NTDDI_VERSION 0x06010000)
+ SET(_WIN32_WINNT 0x0601)
SET(WINVER 0x0601)
ELSEIF(WINDOWS_VERSION STREQUAL "WS08")
+ SET(NTDDI_VERSION 0x06000100)
+ SET(_WIN32_WINNT 0x0600)
SET(WINVER 0x0600)
ELSEIF(WINDOWS_VERSION STREQUAL "VISTA")
+ SET(NTDDI_VERSION 0x06000000)
+ SET(_WIN32_WINNT 0x0600)
SET(WINVER 0x0600)
ELSEIF(WINDOWS_VERSION STREQUAL "WS03")
+ SET(NTDDI_VERSION 0x05020000)
+ SET(_WIN32_WINNT 0x0502)
SET(WINVER 0x0502)
ELSEIF(WINDOWS_VERSION STREQUAL "WINXP")
+ SET(NTDDI_VERSION 0x05010000)
+ SET(_WIN32_WINNT 0x0501)
SET(WINVER 0x0501)
ELSE(WINDOWS_VERSION STREQUAL "WIN8")
- # The default is to use Windows 2000 API.
- SET(WINVER 0x0500)
+ # Default to Windows Server 2003 API if we don't recognize the specifier
+ SET(NTDDI_VERSION 0x05020000)
+ SET(_WIN32_WINNT 0x0502)
+ SET(WINVER 0x0502)
ENDIF(WINDOWS_VERSION STREQUAL "WIN8")
- SET(_WIN32_WINNT ${WINVER})
ENDIF(WIN32)
IF(MSVC)
diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in
index 94fbb59..64f4d4d 100644
--- a/build/cmake/config.h.in
+++ b/build/cmake/config.h.in
@@ -1171,7 +1171,11 @@
/* Define for large files, on AIX-style hosts. */
#cmakedefine _LARGE_FILES ${_LARGE_FILES}
-/* Define for Windows to use Windows 2000+ APIs. */
+/* Define to control Windows SDK version */
+#ifndef NTDDI_VERSION
+#cmakedefine NTDDI_VERSION ${NTDDI_VERSION}
+#endif // NTDDI_VERSION
+
#ifndef _WIN32_WINNT
#cmakedefine _WIN32_WINNT ${_WIN32_WINNT}
#endif // _WIN32_WINNT
diff --git a/cat/test/main.c b/cat/test/main.c
index 8c414da..319f68c 100644
--- a/cat/test/main.c
+++ b/cat/test/main.c
@@ -780,6 +780,34 @@
return (0);
}
+/* Verify that a block of memory is filled with the specified byte. */
+int
+assertion_memory_filled_with(const char *file, int line,
+ const void *_v1, const char *vd,
+ size_t l, const char *ld,
+ char b, const char *bd, void *extra)
+{
+ const char *v1 = (const char *)_v1;
+ size_t c = 0;
+ size_t i;
+ (void)ld; /* UNUSED */
+
+ assertion_count(file, line);
+
+ for (i = 0; i < l; ++i) {
+ if (v1[i] == b) {
+ ++c;
+ }
+ }
+ if (c == l)
+ return (1);
+
+ failure_start(file, line, "%s (size %d) not filled with %s", vd, (int)l, bd);
+ logprintf(" Only %d bytes were correct\n", (int)c);
+ failure_finish(extra);
+ return (0);
+}
+
/* Verify that the named file exists and is empty. */
int
assertion_empty_file(const char *filename, int line, const char *f1)
@@ -2276,7 +2304,10 @@
/* Not a lot of error checking here; the input better be right. */
out = fopen(name, "wb");
while ((rbytes = fread(buff, 1, sizeof(buff), in)) > 0) {
- fwrite(buff, 1, rbytes, out);
+ if (fwrite(buff, 1, rbytes, out) != rbytes) {
+ logprintf("Error: fwrite\n");
+ break;
+ }
}
fclose(out);
fclose(in);
diff --git a/cat/test/test_error.c b/cat/test/test_error.c
index 20d7535..918af01 100644
--- a/cat/test/test_error.c
+++ b/cat/test/test_error.c
@@ -29,7 +29,7 @@
const char *reffile = "test_expand.error";
assertFileNotExists(reffile);
- assertEqualInt(256, systemf("%s %s >test.out 2>test.err", testprog, reffile));
+ assert(0 != systemf("%s %s >test.out 2>test.err", testprog, reffile));
assertEmptyFile("test.out");
assertNonEmptyFile("test.err");
diff --git a/cat/test/test_error_mixed.c b/cat/test/test_error_mixed.c
index ac01e2e..7d94fce 100644
--- a/cat/test/test_error_mixed.c
+++ b/cat/test/test_error_mixed.c
@@ -33,7 +33,7 @@
assertFileNotExists(reffile2);
extract_reference_file(reffile1);
extract_reference_file(reffile3);
- assertEqualInt(256, systemf("%s %s %s %s >test.out 2>test.err",
+ assert(0 != systemf("%s %s %s %s >test.out 2>test.err",
testprog, reffile1, reffile2, reffile3));
assertTextFileContents(
diff --git a/configure.ac b/configure.ac
index d352991..ca8bf6b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -243,8 +243,9 @@
# Set up defines needed before including any headers
case $host in
*mingw* | *cygwin* )
- AC_DEFINE([_WIN32_WINNT], 0x0500, [Define to '0x0500' for Windows 2000 APIs.])
- AC_DEFINE([WINVER], 0x0500, [Define to '0x0500' for Windows 2000 APIs.])
+ AC_DEFINE([_WIN32_WINNT], 0x0502, [Define to '0x0502' for Windows Server 2003 APIs.])
+ AC_DEFINE([WINVER], 0x0502, [Define to '0x0502' for Windows Server 2003 APIs.])
+ AC_DEFINE([NTDDI_VERSION], 0x05020000, [Define to '0x05020000' for Windows Server 2003 APIs.])
;;
esac
@@ -365,7 +366,17 @@
if test "x$with_lzma" != "xno"; then
AC_CHECK_HEADERS([lzma.h])
AC_CHECK_LIB(lzma,lzma_stream_decoder)
- AC_CHECK_FUNCS([lzma_stream_encoder_mt])
+ # Some pre-release (but widely distributed) versions of liblzma
+ # included a disabled version of lzma_stream_encoder_mt that
+ # fools a naive AC_CHECK_LIB or AC_CHECK_FUNC, so we need
+ # to do something more complex here:
+ AC_CACHE_CHECK(
+ [whether we have multithread support in lzma],
+ ac_cv_lzma_has_mt,
+ [AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([[#include <lzma.h>]],
+ [[lzma_stream_encoder_mt(0, 0);]])],
+ [ac_cv_lzma_has_mt=yes], [ac_cv_lzma_has_mt=no])])
fi
AC_ARG_WITH([lzo2],
diff --git a/cpio/test/main.c b/cpio/test/main.c
index 5801127..fa22adf 100644
--- a/cpio/test/main.c
+++ b/cpio/test/main.c
@@ -781,6 +781,34 @@
return (0);
}
+/* Verify that a block of memory is filled with the specified byte. */
+int
+assertion_memory_filled_with(const char *file, int line,
+ const void *_v1, const char *vd,
+ size_t l, const char *ld,
+ char b, const char *bd, void *extra)
+{
+ const char *v1 = (const char *)_v1;
+ size_t c = 0;
+ size_t i;
+ (void)ld; /* UNUSED */
+
+ assertion_count(file, line);
+
+ for (i = 0; i < l; ++i) {
+ if (v1[i] == b) {
+ ++c;
+ }
+ }
+ if (c == l)
+ return (1);
+
+ failure_start(file, line, "%s (size %d) not filled with %s", vd, (int)l, bd);
+ logprintf(" Only %d bytes were correct\n", (int)c);
+ failure_finish(extra);
+ return (0);
+}
+
/* Verify that the named file exists and is empty. */
int
assertion_empty_file(const char *filename, int line, const char *f1)
@@ -2277,7 +2305,10 @@
/* Not a lot of error checking here; the input better be right. */
out = fopen(name, "wb");
while ((rbytes = fread(buff, 1, sizeof(buff), in)) > 0) {
- fwrite(buff, 1, rbytes, out);
+ if (fwrite(buff, 1, rbytes, out) != rbytes) {
+ logprintf("Error: fwrite\n");
+ break;
+ }
}
fclose(out);
fclose(in);
diff --git a/examples/minitar/Makefile b/examples/minitar/Makefile
index 1ec4593..e2cc089 100644
--- a/examples/minitar/Makefile
+++ b/examples/minitar/Makefile
@@ -8,13 +8,19 @@
-I../../libarchive \
-g
+#
+# You may need to add additional libraries or link options here
+# For example, many Linux systems require -lacl
+#
+LIBS= -lz -lbz2
+
# How to link against libarchive.
LIBARCHIVE= ../../libarchive/libarchive.a
all: minitar
minitar: minitar.o
- cc -g -o minitar minitar.o $(LIBARCHIVE) -lz -lbz2
+ cc -g -o minitar minitar.o $(LIBARCHIVE) $(LIBS)
strip minitar
ls -l minitar
diff --git a/libarchive/archive.h b/libarchive/archive.h
index 92515d8..548db21 100644
--- a/libarchive/archive.h
+++ b/libarchive/archive.h
@@ -41,6 +41,7 @@
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
#include <stdio.h> /* For FILE * */
+#include <time.h> /* For time_t */
/*
* Note: archive.h is for use outside of libarchive; the configuration
diff --git a/libarchive/archive_string.c b/libarchive/archive_string.c
index 3d4be82..282c58e 100644
--- a/libarchive/archive_string.c
+++ b/libarchive/archive_string.c
@@ -737,7 +737,8 @@
}
if (count == 0)
ret = -1;
- } while (0);
+ break;
+ } while (1);
}
as->length += count;
as->s[as->length] = '\0';
diff --git a/libarchive/test/main.c b/libarchive/test/main.c
index 8561129..e0af431 100644
--- a/libarchive/test/main.c
+++ b/libarchive/test/main.c
@@ -2303,7 +2303,10 @@
/* Not a lot of error checking here; the input better be right. */
out = fopen(name, "wb");
while ((rbytes = fread(buff, 1, sizeof(buff), in)) > 0) {
- fwrite(buff, 1, rbytes, out);
+ if (fwrite(buff, 1, rbytes, out) != rbytes) {
+ logprintf("Error: fwrite\n");
+ break;
+ }
}
fclose(out);
fclose(in);
diff --git a/libarchive/test/test_sparse_basic.c b/libarchive/test/test_sparse_basic.c
index e5dd2f7..3cea459 100644
--- a/libarchive/test/test_sparse_basic.c
+++ b/libarchive/test/test_sparse_basic.c
@@ -301,7 +301,7 @@
/* Block that overlaps beginning of data */
if (expected_offset < offset
&& expected_offset + (int64_t)sparse->size <= offset + (int64_t)bytes_read) {
- const char *end = buff + (expected_offset - offset) + (size_t)sparse->size;
+ const char *end = (const char *)buff + (expected_offset - offset) + (size_t)sparse->size;
#if DEBUG
fprintf(stderr, " overlapping hole expected_offset=%d, size=%d\n", (int)expected_offset, (int)sparse->size);
#endif
@@ -315,7 +315,7 @@
}
/* Blocks completely contained in data we just read. */
while (expected_offset + (int64_t)sparse->size <= offset + (int64_t)bytes_read) {
- const char *end = buff + (expected_offset - offset) + (size_t)sparse->size;
+ const char *end = (const char *)buff + (expected_offset - offset) + (size_t)sparse->size;
if (sparse->type == HOLE) {
#if DEBUG
fprintf(stderr, " contained hole expected_offset=%d, size=%d\n", (int)expected_offset, (int)sparse->size);
@@ -323,7 +323,7 @@
/* verify data corresponding to hole is '\0' */
if (end > (const char *)buff + bytes_read) {
- end = buff + bytes_read;
+ end = (const char *)buff + bytes_read;
}
assertMemoryFilledWith(start, end - start, '\0');
start = end;
@@ -335,7 +335,7 @@
#endif
/* verify data corresponding to hole is ' ' */
if (assert(expected_offset + sparse->size <= offset + bytes_read)) {
- assert(start == buff + (size_t)(expected_offset - offset));
+ assert(start == (const char *)buff + (size_t)(expected_offset - offset));
assertMemoryFilledWith(start, end - start, ' ');
}
start = end;
@@ -347,7 +347,7 @@
}
/* Block that overlaps end of data */
if (expected_offset < offset + (int64_t)bytes_read) {
- const char *end = buff + bytes_read;
+ const char *end = (const char *)buff + bytes_read;
#if DEBUG
fprintf(stderr, " trailing overlap expected_offset=%d, size=%d\n", (int)expected_offset, (int)sparse->size);
#endif
diff --git a/libarchive/test/test_write_format_cpio_newc.c b/libarchive/test/test_write_format_cpio_newc.c
index 3bbc173..48b0b26 100644
--- a/libarchive/test/test_write_format_cpio_newc.c
+++ b/libarchive/test/test_write_format_cpio_newc.c
@@ -30,7 +30,7 @@
is_hex(const char *p, size_t l)
{
while (l > 0) {
- if (*p >= 0 && *p <= '9') {
+ if (*p >= '0' && *p <= '9') {
/* Ascii digit */
} else if (*p >= 'a' && *p <= 'f') {
/* lowercase letter a-f */
diff --git a/tar/test/main.c b/tar/test/main.c
index 33a6364..90801a9 100644
--- a/tar/test/main.c
+++ b/tar/test/main.c
@@ -781,6 +781,34 @@
return (0);
}
+/* Verify that a block of memory is filled with the specified byte. */
+int
+assertion_memory_filled_with(const char *file, int line,
+ const void *_v1, const char *vd,
+ size_t l, const char *ld,
+ char b, const char *bd, void *extra)
+{
+ const char *v1 = (const char *)_v1;
+ size_t c = 0;
+ size_t i;
+ (void)ld; /* UNUSED */
+
+ assertion_count(file, line);
+
+ for (i = 0; i < l; ++i) {
+ if (v1[i] == b) {
+ ++c;
+ }
+ }
+ if (c == l)
+ return (1);
+
+ failure_start(file, line, "%s (size %d) not filled with %s", vd, (int)l, bd);
+ logprintf(" Only %d bytes were correct\n", (int)c);
+ failure_finish(extra);
+ return (0);
+}
+
/* Verify that the named file exists and is empty. */
int
assertion_empty_file(const char *filename, int line, const char *f1)
@@ -2277,7 +2305,10 @@
/* Not a lot of error checking here; the input better be right. */
out = fopen(name, "wb");
while ((rbytes = fread(buff, 1, sizeof(buff), in)) > 0) {
- fwrite(buff, 1, rbytes, out);
+ if (fwrite(buff, 1, rbytes, out) != rbytes) {
+ logprintf("Error: fwrite\n");
+ break;
+ }
}
fclose(out);
fclose(in);
diff --git a/tar/test/test_leading_slash.c b/tar/test/test_leading_slash.c
index 52646d0..a8921eb 100644
--- a/tar/test/test_leading_slash.c
+++ b/tar/test/test_leading_slash.c
@@ -28,6 +28,9 @@
DEFINE_TEST(test_leading_slash)
{
const char *reffile = "test_leading_slash.tar";
+ char *errfile;
+ size_t errfile_size;
+ const char *expected_errmsg = "Removing leading '/' from member names";
extract_reference_file(reffile);
assertEqualInt(0, systemf("%s -xf %s >test.out 2>test.err", testprog, reffile));
@@ -36,10 +39,11 @@
assertTextFileContents("foo\x0a", "foo/hardlink");
assertIsHardlink("foo/file", "foo/hardlink");
assertEmptyFile("test.out");
-#ifdef _WIN32
- assertTextFileContents("bsdtar.exe: Removing leading '/' from member names\x0a", "test.err");
-#else
- assertTextFileContents("bsdtar: Removing leading '/' from member names\x0a", "test.err");
-#endif
+
+ /* Verify the error output contains the expected text somewhere in it */
+ if (assertFileExists("test.err")) {
+ errfile = slurpfile(&errfile_size, "test.err");
+ assert(strstr(errfile, expected_errmsg) != NULL);
+ }
}