Merge pull request #2526 from fdegros/compress_support

Fix SIGSEGV in compress filter when appended before open

(cherry picked from commit 4f3cf235e3)
This commit is contained in:
Tim Kientzle authored and Martin Matuska committed 2026-06-23 10:16:15 +02:00
1 parent 0f9f5c8871
commit ba5d675183
2 files changed
+185 -3

No files matched your search

@@ -104,6 +104,7 @@ struct private_data {
void *out_block;
/* Decompression status variables. */
int initialized;
int use_reset_code;
int end_of_stream; /* EOF status. */
int maxcode; /* Largest code. */
@@ -212,7 +213,6 @@ compress_bidder_init(struct archive_read_filter *self)
struct private_data *state;
static const size_t out_block_size = 64 * 1024;
void *out_block;
int code;
self->code = ARCHIVE_FILTER_COMPRESS;
self->name = "compress (.Z)";
@@ -233,14 +233,23 @@ compress_bidder_init(struct archive_read_filter *self)
state->out_block = out_block;
self->vtable = &compress_reader_vtable;
/* XXX MOVE THE FOLLOWING OUT OF INIT() XXX */
return (ARCHIVE_OK);
}
static int
compress_filter_init(struct archive_read_filter *self)
{
struct private_data *state = (struct private_data *)self->data;
int code;
state->initialized = 1;
(void)getbits(self, 8); /* Skip first signature byte. */
(void)getbits(self, 8); /* Skip second signature byte. */
/* Get compression parameters. */
code = getbits(self, 8);
if ((code & 0x1f) > 16) {
if (code < 0 || (code & 0x1f) > 16) {
archive_set_error(&self->archive->archive, -1,
"Invalid compressed data");
return (ARCHIVE_FATAL);
@@ -278,6 +287,11 @@ compress_filter_read(struct archive_read_filter *self, const void **pblock)
int ret;
state = (struct private_data *)self->data;
if (!state->initialized) {
ret = compress_filter_init(self);
if (ret != ARCHIVE_OK)
return (ret);
}
if (state->end_of_stream) {
*pblock = NULL;
return (0);
+168
View File
@@ -211,6 +211,174 @@ DEFINE_TEST(test_read_append_grzip_filter)
archive_read_free(a);
}
DEFINE_TEST(test_read_append_compress_filter)
{
struct archive *a;
int r;
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR));
r = archive_read_append_filter(a, ARCHIVE_FILTER_COMPRESS);
assertEqualIntA(a, ARCHIVE_OK, r);
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
DEFINE_TEST(test_read_append_bzip2_filter)
{
struct archive *a;
int r;
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR));
r = archive_read_append_filter(a, ARCHIVE_FILTER_BZIP2);
if (r != ARCHIVE_OK && archive_bzlib_version() == NULL && !canBzip2()) {
skipping("bzip2 tests require bzlib or working bzip2 command");
archive_read_free(a);
return;
}
if (r == ARCHIVE_WARN && canBzip2())
assertEqualString(archive_error_string(a), "Using external bzip2 program");
else
assertEqualIntA(a, ARCHIVE_OK, r);
archive_read_free(a);
}
DEFINE_TEST(test_read_append_lrzip_filter)
{
struct archive *a;
int r;
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR));
r = archive_read_append_filter(a, ARCHIVE_FILTER_LRZIP);
if (r != ARCHIVE_OK && !canLrzip()) {
skipping("lrzip tests require working lrzip command");
archive_read_free(a);
return;
}
if (r == ARCHIVE_WARN && canLrzip())
assertEqualString(archive_error_string(a), "Using external lrzip program for lrzip decompression");
else
assertEqualIntA(a, ARCHIVE_OK, r);
archive_read_free(a);
}
DEFINE_TEST(test_read_append_lz4_filter)
{
struct archive *a;
int r;
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR));
r = archive_read_append_filter(a, ARCHIVE_FILTER_LZ4);
if (r != ARCHIVE_OK && archive_liblz4_version() == NULL && !canLz4()) {
skipping("lz4 tests require liblz4 or working lz4 command");
archive_read_free(a);
return;
}
if (r == ARCHIVE_WARN && canLz4())
assertEqualString(archive_error_string(a), "Using external lz4 program");
else
assertEqualIntA(a, ARCHIVE_OK, r);
archive_read_free(a);
}
DEFINE_TEST(test_read_append_lzip_filter)
{
struct archive *a;
int r;
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR));
r = archive_read_append_filter(a, ARCHIVE_FILTER_LZIP);
if (r != ARCHIVE_OK && archive_liblzma_version() == NULL && !canLzip()) {
skipping("lzip tests require liblzma or working lzip command");
archive_read_free(a);
return;
}
if (r == ARCHIVE_WARN && canLzip())
assertEqualString(archive_error_string(a), "Using external lzip program for lzip decompression");
else
assertEqualIntA(a, ARCHIVE_OK, r);
archive_read_free(a);
}
DEFINE_TEST(test_read_append_lzma_filter)
{
struct archive *a;
int r;
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR));
r = archive_read_append_filter(a, ARCHIVE_FILTER_LZMA);
if (r != ARCHIVE_OK && archive_liblzma_version() == NULL && !canLzma()) {
skipping("lzma tests require liblzma or working lzma command");
archive_read_free(a);
return;
}
if (r == ARCHIVE_WARN && canLzma())
assertEqualString(archive_error_string(a), "Using external lzma program for lzma decompression");
else
assertEqualIntA(a, ARCHIVE_OK, r);
archive_read_free(a);
}
DEFINE_TEST(test_read_append_zstd_filter)
{
struct archive *a;
int r;
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR));
r = archive_read_append_filter(a, ARCHIVE_FILTER_ZSTD);
if (r != ARCHIVE_OK && archive_libzstd_version() == NULL && !canZstd()) {
skipping("zstd tests require libzstd or working zstd command");
archive_read_free(a);
return;
}
if (r == ARCHIVE_WARN && canZstd())
assertEqualString(archive_error_string(a), "Using external zstd program for zstd decompression");
else
assertEqualIntA(a, ARCHIVE_OK, r);
archive_read_free(a);
}
DEFINE_TEST(test_read_append_rpm_filter)
{
struct archive *a;
int r;
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR));
r = archive_read_append_filter(a, ARCHIVE_FILTER_RPM);
assertEqualIntA(a, ARCHIVE_OK, r);
archive_read_free(a);
}
DEFINE_TEST(test_read_append_uu_filter)
{
struct archive *a;
int r;
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR));
r = archive_read_append_filter(a, ARCHIVE_FILTER_UU);
assertEqualIntA(a, ARCHIVE_OK, r);
archive_read_free(a);
}
DEFINE_TEST(test_read_append_none_filter)
{
struct archive *a;
int r;
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR));
r = archive_read_append_filter(a, ARCHIVE_FILTER_NONE);
assertEqualIntA(a, ARCHIVE_OK, r);
archive_read_free(a);
}
DEFINE_TEST(test_read_append_filter_program)
{
struct archive_entry *ae;