libarchive: merge vendor bugfixes
Bugfixes: OSS-Fuzz #44547: fix heap-use-after-free in RAR (v4) filter code PR #1671: Fix 7z PPMD reading beyond boundary X-MFC-with: 833a452e9d
This commit is contained in:
commit
47a2e541dc
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user