Bugfixes:
  OSS-Fuzz #44547 (security):
    fix heap-use-after-free in RAR (v4) filter code
  PR #1671:
    Fix 7z PPMD reading beyond boundary

Obtained from:		libarchive
Libarchive commit:	72ce1ff7c6857a7334baa05884e69b9264a2199c
This commit is contained in:
Martin Matuska 2022-02-19 00:45:12 +01:00
parent 84631082f6
commit 3c540f9694
16 changed files with 2200 additions and 26701 deletions

View File

@ -104,7 +104,7 @@ jobs:
path: libarchive-dist.tar
Windows:
runs-on: windows-latest
runs-on: windows-2022
strategy:
matrix:
be: [mingw-gcc, msvc]

View File

@ -21,7 +21,7 @@ endif()
# RelWithDebInfo : Release build with Debug Info
# MinSizeRel : Release Min Size build
IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE)
SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build Type" FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE)
# Set a value type to properly display CMAKE_BUILD_TYPE on GUI if the
# value type is "UNINITIALIZED".

View File

@ -51,7 +51,7 @@ IF "%1"=="deplibs" (
mingw32-make test || EXIT /b 1
mingw32-make install || EXIT /b 1
) ELSE IF "%BE%"=="msvc" (
cmake -G "Visual Studio 16 2019" . || EXIT /b 1
cmake -G "Visual Studio 17 2022" . || EXIT /b 1
cmake --build . --target ALL_BUILD --config Release || EXIT /b 1
cmake --build . --target RUN_TESTS --config Release || EXIT /b 1
cmake --build . --target INSTALL --config Release || EXIT /b 1
@ -65,7 +65,7 @@ IF "%1"=="deplibs" (
REM mingw32-make test || EXIT /b 1
mingw32-make install || EXIT /b 1
) ELSE IF "%BE%"=="msvc" (
cmake -G "Visual Studio 16 2019" -D CMAKE_BUILD_TYPE="Release" -D ENABLE_LIB_ONLY=ON -D ENABLE_SHARED_LIB=OFF -D ENABLE_STATIC_LIB=ON . || EXIT /b 1
cmake -G "Visual Studio 17 2022" -D CMAKE_BUILD_TYPE="Release" -D ENABLE_LIB_ONLY=ON -D ENABLE_SHARED_LIB=OFF -D ENABLE_STATIC_LIB=ON . || EXIT /b 1
cmake --build . --target ALL_BUILD --config Release || EXIT /b 1
REM cmake --build . --target RUN_TESTS --config Release || EXIT /b 1
cmake --build . --target INSTALL --config Release || EXIT /b 1
@ -78,7 +78,7 @@ IF "%1"=="deplibs" (
mingw32-make || EXIT /b 1
mingw32-make install || EXIT /b 1
) ELSE IF "%BE%"=="msvc" (
cmake -G "Visual Studio 16 2019" -D CMAKE_BUILD_TYPE="Release" . || EXIT /b 1
cmake -G "Visual Studio 17 2022" -D CMAKE_BUILD_TYPE="Release" . || EXIT /b 1
cmake --build . --target ALL_BUILD --config Release || EXIT /b 1
cmake --build . --target INSTALL --config Release || EXIT /b 1
)
@ -91,7 +91,7 @@ IF "%1"=="deplibs" (
) ELSE IF "%BE%"=="msvc" (
MKDIR build_ci\cmake
CD build_ci\cmake
cmake -G "Visual Studio 16 2019" -D CMAKE_BUILD_TYPE="Release" -D ZLIB_LIBRARY="C:/Program Files (x86)/zlib/lib/zlibstatic.lib" -D ZLIB_INCLUDE_DIR="C:/Program Files (x86)/zlib/include" -D BZIP2_LIBRARIES="C:/Program Files (x86)/bzip2/lib/bz2.lib" -D BZIP2_INCLUDE_DIR="C:/Program Files (x86)/bzip2/include" -D LIBLZMA_LIBRARY="C:/Program Files (x86)/xz/lib/liblzma.lib" -D LIBLZMA_INCLUDE_DIR="C:/Program Files (x86)/xz/include" ..\.. || EXIT /b 1
cmake -G "Visual Studio 17 2022" -D CMAKE_BUILD_TYPE="Release" -D ZLIB_LIBRARY="C:/Program Files (x86)/zlib/lib/zlibstatic.lib" -D ZLIB_INCLUDE_DIR="C:/Program Files (x86)/zlib/include" -D BZIP2_LIBRARIES="C:/Program Files (x86)/bzip2/lib/bz2.lib" -D BZIP2_INCLUDE_DIR="C:/Program Files (x86)/bzip2/include" -D LIBLZMA_LIBRARY="C:/Program Files (x86)/xz/lib/liblzma.lib" -D LIBLZMA_INCLUDE_DIR="C:/Program Files (x86)/xz/include" ..\.. || EXIT /b 1
)
) ELSE IF "%1%"=="build" (
IF "%BE%"=="mingw-gcc" (

View File

@ -1 +1 @@
3006000
3006001dev

View File

@ -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.6.0])
m4_define([LIBARCHIVE_VERSION_N],[3006000])
m4_define([LIBARCHIVE_VERSION_S],[3.6.1dev])
m4_define([LIBARCHIVE_VERSION_N],[3006001])
dnl bsdtar and bsdcpio versioning tracks libarchive
m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S())

View File

@ -36,7 +36,7 @@
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
#define ARCHIVE_VERSION_NUMBER 3006000
#define ARCHIVE_VERSION_NUMBER 3006001
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
@ -155,7 +155,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
#define ARCHIVE_VERSION_ONLY_STRING "3.6.0"
#define ARCHIVE_VERSION_ONLY_STRING "3.6.1dev"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);

View File

@ -13,11 +13,12 @@
https://blake2.net.
*/
#include "archive_platform.h"
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "archive_platform.h"
#include "archive_blake2.h"
#include "archive_blake2_impl.h"

View File

@ -13,6 +13,8 @@
https://blake2.net.
*/
#include "archive_platform.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@ -21,7 +23,6 @@
#include <omp.h>
#endif
#include "archive_platform.h"
#include "archive_blake2.h"
#include "archive_blake2_impl.h"

View File

@ -30,7 +30,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
#define ARCHIVE_VERSION_NUMBER 3006000
#define ARCHIVE_VERSION_NUMBER 3006001
/*
* Note: archive_entry.h is for use outside of libarchive; the

View File

@ -287,6 +287,7 @@ struct _7zip {
const unsigned char *next_in;
int64_t avail_in;
int64_t total_in;
int64_t stream_in;
unsigned char *next_out;
int64_t avail_out;
int64_t total_out;
@ -986,15 +987,30 @@ ppmd_read(void *p)
struct _7zip *zip = (struct _7zip *)(a->format->data);
Byte b;
if (zip->ppstream.avail_in == 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated RAR file data");
zip->ppstream.overconsumed = 1;
return (0);
if (zip->ppstream.avail_in <= 0) {
/*
* Ppmd7_DecodeSymbol might require reading multiple bytes
* and we are on boundary;
* last resort to read using __archive_read_ahead.
*/
ssize_t bytes_avail = 0;
const uint8_t* data = __archive_read_ahead(a,
zip->ppstream.stream_in+1, &bytes_avail);
if(bytes_avail < zip->ppstream.stream_in+1) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated 7z file data");
zip->ppstream.overconsumed = 1;
return (0);
}
zip->ppstream.next_in++;
b = data[zip->ppstream.stream_in];
} else {
b = *zip->ppstream.next_in++;
}
b = *zip->ppstream.next_in++;
zip->ppstream.avail_in--;
zip->ppstream.total_in++;
zip->ppstream.stream_in++;
return (b);
}
@ -1485,6 +1501,7 @@ decompress(struct archive_read *a, struct _7zip *zip,
}
zip->ppstream.next_in = t_next_in;
zip->ppstream.avail_in = t_avail_in;
zip->ppstream.stream_in = 0;
zip->ppstream.next_out = t_next_out;
zip->ppstream.avail_out = t_avail_out;
if (zip->ppmd7_stat == 0) {

View File

@ -430,7 +430,7 @@ static int new_node(struct huffman_code *);
static int make_table(struct archive_read *, struct huffman_code *);
static int make_table_recurse(struct archive_read *, struct huffman_code *, int,
struct huffman_table_entry *, int, int);
static int64_t expand(struct archive_read *, int64_t);
static int expand(struct archive_read *, int64_t *);
static int copy_from_lzss_window_to_unp(struct archive_read *, const void **,
int64_t, int);
static const void *rar_read_ahead(struct archive_read *, size_t, ssize_t *);
@ -1988,7 +1988,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
return (ARCHIVE_FATAL);
struct rar *rar;
int64_t start, end, actualend;
int64_t start, end;
size_t bs;
int ret = (ARCHIVE_OK), sym, code, lzss_offset, length, i;
@ -2179,11 +2179,12 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
end = rar->filters.filterstart;
}
if ((actualend = expand(a, end)) < 0)
return ((int)actualend);
ret = expand(a, &end);
if (ret != ARCHIVE_OK)
return (ret);
rar->bytes_uncopied = actualend - start;
rar->filters.lastend = actualend;
rar->bytes_uncopied = end - start;
rar->filters.lastend = end;
if (rar->filters.lastend != rar->filters.filterstart && rar->bytes_uncopied == 0) {
/* Broken RAR files cause this case.
* NOTE: If this case were possible on a normal RAR file
@ -2825,8 +2826,8 @@ make_table_recurse(struct archive_read *a, struct huffman_code *code, int node,
return ret;
}
static int64_t
expand(struct archive_read *a, int64_t end)
static int
expand(struct archive_read *a, int64_t *end)
{
static const unsigned char lengthbases[] =
{ 0, 1, 2, 3, 4, 5, 6,
@ -2873,16 +2874,19 @@ expand(struct archive_read *a, int64_t end)
struct rar *rar = (struct rar *)(a->format->data);
struct rar_br *br = &(rar->br);
if (rar->filters.filterstart < end)
end = rar->filters.filterstart;
if (rar->filters.filterstart < *end)
*end = rar->filters.filterstart;
while (1)
{
if(lzss_position(&rar->lzss) >= end)
return end;
if(lzss_position(&rar->lzss) >= *end) {
return (ARCHIVE_OK);
}
if(rar->is_ppmd_block)
return lzss_position(&rar->lzss);
if(rar->is_ppmd_block) {
*end = lzss_position(&rar->lzss);
return (ARCHIVE_OK);
}
if ((symbol = read_next_symbol(a, &rar->maincode)) < 0)
return (ARCHIVE_FATAL);
@ -2906,7 +2910,8 @@ expand(struct archive_read *a, int64_t end)
goto truncated_data;
rar->start_new_table = rar_br_bits(br, 1);
rar_br_consume(br, 1);
return lzss_position(&rar->lzss);
*end = lzss_position(&rar->lzss);
return (ARCHIVE_OK);
}
else
{
@ -2917,7 +2922,7 @@ expand(struct archive_read *a, int64_t end)
}
else if(symbol==257)
{
if (!read_filter(a, &end))
if (!read_filter(a, end))
return (ARCHIVE_FATAL);
continue;
}
@ -3325,12 +3330,19 @@ run_filters(struct archive_read *a)
struct rar_filter *filter = filters->stack;
size_t start = filters->filterstart;
size_t end = start + filter->blocklength;
int64_t tend;
uint32_t lastfilteraddress;
uint32_t lastfilterlength;
int ret;
filters->filterstart = INT64_MAX;
end = (size_t)expand(a, end);
tend = (int64_t)end;
ret = expand(a, &tend);
if (ret != ARCHIVE_OK)
return (ret);
if (tend < 0)
return (ARCHIVE_FATAL);
end = (size_t)tend;
if (end != start + filter->blocklength)
return 0;

View File

@ -32,9 +32,9 @@ DEFINE_TEST(test_read_format_rar_filter)
struct archive_entry *ae;
char *buff[12];
const char signature[12] = {
0xff, 0xd8, 0xff, 0xe0,
0x00, 0x10, 0x4a, 0x46,
0x49, 0x46, 0x00, 0x01,
0x4d, 0x5a, 0x90, 0x00,
0x03, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00,
};
extract_reference_file(refname);
@ -44,9 +44,9 @@ DEFINE_TEST(test_read_format_rar_filter)
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240));
assertA(0 == archive_read_next_header(a, &ae));
assertEqualString("013.jpg", archive_entry_pathname(ae));
assertEqualString("bsdcat.exe", archive_entry_pathname(ae));
assertA((int)archive_entry_mtime(ae));
assertEqualInt(1215721, archive_entry_size(ae));
assertEqualInt(204288, archive_entry_size(ae));
assertA(12 == archive_read_data(a, buff, 12));
assertEqualMem(buff, signature, 12);

File diff suppressed because it is too large Load Diff

View File

@ -1128,6 +1128,7 @@ DEFINE_TEST(test_read_format_zip_7z_deflate)
const char *refname = "test_read_format_zip_7z_deflate.zip";
struct archive_entry *ae;
struct archive *a;
int r;
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
@ -1137,15 +1138,33 @@ DEFINE_TEST(test_read_format_zip_7z_deflate)
assertEqualIntA(a, ARCHIVE_OK,
archive_read_open_filename(a, refname, 10240));
//read first symlink
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
r = archive_read_next_header(a, &ae);
if (archive_zlib_version() == NULL) {
assertEqualInt(ARCHIVE_FAILED, r);
assertEqualString(archive_error_string(a),
"Unsupported ZIP compression method during decompression "
"of link entry (8: deflation)");
assert(archive_errno(a) != 0);
} else {
assertEqualIntA(a, ARCHIVE_OK, r);
assertEqualString("libxkbcommon-x11.so.0.0.0",
archive_entry_symlink(ae));
}
assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
assertEqualString("libxkbcommon-x11.so.0.0.0",
archive_entry_symlink(ae));
//read second symlink
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
r = archive_read_next_header(a, &ae);
if (archive_zlib_version() == NULL) {
assertEqualInt(ARCHIVE_FAILED, r);
assertEqualString(archive_error_string(a),
"Unsupported ZIP compression method during decompression "
"of link entry (8: deflation)");
assert(archive_errno(a) != 0);
} else {
assertEqualIntA(a, ARCHIVE_OK, r);
assertEqualString("libxkbcommon-x11.so.0.0.0",
archive_entry_symlink(ae));
}
assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
assertEqualString("libxkbcommon-x11.so.0.0.0",
archive_entry_symlink(ae));
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
}

View File

@ -115,7 +115,7 @@ test_winzip_aes(const char *refname, int need_libz)
} else {
assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, 19));
assertEqualString(archive_error_string(a),
"Unsupported ZIP compression method (deflation)");
"Unsupported ZIP compression method (8: deflation)");
assert(archive_errno(a) != 0);
}

View File

@ -143,7 +143,7 @@ DEFINE_TEST(test_read_format_zip_winzip_aes256_large)
assertEqualInt(ARCHIVE_FAILED,
archive_read_data(a, buff, sizeof(buff)));
assertEqualString(archive_error_string(a),
"Unsupported ZIP compression method (deflation)");
"Unsupported ZIP compression method (8: deflation)");
assert(archive_errno(a) != 0);
}
@ -161,7 +161,7 @@ DEFINE_TEST(test_read_format_zip_winzip_aes256_large)
assertEqualInt(ARCHIVE_FAILED,
archive_read_data(a, buff, sizeof(buff)));
assertEqualString(archive_error_string(a),
"Unsupported ZIP compression method (deflation)");
"Unsupported ZIP compression method (8: deflation)");
assert(archive_errno(a) != 0);
}
@ -179,7 +179,7 @@ DEFINE_TEST(test_read_format_zip_winzip_aes256_large)
assertEqualInt(ARCHIVE_FAILED,
archive_read_data(a, buff, sizeof(buff)));
assertEqualString(archive_error_string(a),
"Unsupported ZIP compression method (deflation)");
"Unsupported ZIP compression method (8: deflation)");
assert(archive_errno(a) != 0);
}
@ -197,7 +197,7 @@ DEFINE_TEST(test_read_format_zip_winzip_aes256_large)
assertEqualInt(ARCHIVE_FAILED,
archive_read_data(a, buff, sizeof(buff)));
assertEqualString(archive_error_string(a),
"Unsupported ZIP compression method (deflation)");
"Unsupported ZIP compression method (8: deflation)");
assert(archive_errno(a) != 0);
}