filter: Check __archive_write_allocate_filter result

If allocation of filter fails, gracefully handle it instead of
eventually triggering a NULL pointer dereference.

Allocate the filter in last step, because it's rather difficult to
cleanly revert in case of error.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
This commit is contained in:
Tobias Stoeckmann committed 2026-07-17 19:02:35 +02:00
1 parent b2a38b8845
commit 421b6c267d
12 files changed
+222 -179

No files matched your search

@@ -83,21 +83,21 @@ static const char base64[] = {
int
archive_write_add_filter_b64encode(struct archive *a)
{
struct archive_write_filter *f = __archive_write_allocate_filter(a);
struct archive_write_filter *f;
struct private_b64encode *state;
archive_check_magic(a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_add_filter_b64encode");
state = calloc(1, sizeof(*state));
if (state == NULL) {
archive_set_error(a, ENOMEM,
"Can't allocate data for b64encode filter");
return (ARCHIVE_FATAL);
}
if (state == NULL)
goto memerr;
archive_strcpy(&state->name, "-");
state->mode = 0644;
f = __archive_write_allocate_filter(a);
if (f == NULL)
goto memerr;
f->data = state;
f->name = "b64encode";
f->code = ARCHIVE_FILTER_UU;
@@ -108,6 +108,11 @@ archive_write_add_filter_b64encode(struct archive *a)
f->free = archive_filter_b64encode_free;
return (ARCHIVE_OK);
memerr:
free_data(state);
archive_set_error(a, ENOMEM,
"Can't allocate data for b64encode filter");
return (ARCHIVE_FATAL);
}
/*
+24 -20
View File
@@ -79,19 +79,32 @@ static void free_data(struct private_data *);
int
archive_write_add_filter_bzip2(struct archive *a)
{
struct archive_write_filter *f = __archive_write_allocate_filter(a);
struct archive_write_filter *f;
struct private_data *data;
int r;
archive_check_magic(a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_add_filter_bzip2");
data = calloc(1, sizeof(*data));
if (data == NULL) {
archive_set_error(a, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
data->compression_level = 9; /* default */
if (data == NULL)
goto memerr;
#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
data->compression_level = 9;
r = ARCHIVE_OK;
#else
data->pdata = __archive_write_program_allocate("bzip2");
if (data->pdata == NULL)
goto memerr;
data->compression_level = 0;
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Using external bzip2 program");
r = ARCHIVE_WARN;
#endif
f = __archive_write_allocate_filter(a);
if (f == NULL)
goto memerr;
f->data = data;
f->options = &archive_compressor_bzip2_options;
f->close = &archive_compressor_bzip2_close;
@@ -100,20 +113,11 @@ archive_write_add_filter_bzip2(struct archive *a)
f->write = archive_compressor_bzip2_write;
f->code = ARCHIVE_FILTER_BZIP2;
f->name = "bzip2";
#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
return (ARCHIVE_OK);
#else
data->pdata = __archive_write_program_allocate("bzip2");
if (data->pdata == NULL) {
free(data);
archive_set_error(a, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
data->compression_level = 0;
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Using external bzip2 program");
return (ARCHIVE_WARN);
#endif
return (r);
memerr:
free_data(data);
archive_set_error(a, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
static int
+11 -6
View File
@@ -128,19 +128,19 @@ archive_write_set_compression_compress(struct archive *a)
int
archive_write_add_filter_compress(struct archive *a)
{
struct archive_write_filter *f = __archive_write_allocate_filter(a);
struct archive_write_filter *f;
struct private_data *state;
archive_check_magic(a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_add_filter_compress");
state = calloc(1, sizeof(*state));
if (state == NULL) {
archive_set_error(a, ENOMEM,
"Can't allocate data for compression");
return (ARCHIVE_FATAL);
}
if (state == NULL)
goto memerr;
f = __archive_write_allocate_filter(a);
if (f == NULL)
goto memerr;
f->data = state;
f->open = &archive_compressor_compress_open;
f->write = archive_compressor_compress_write;
@@ -149,6 +149,11 @@ archive_write_add_filter_compress(struct archive *a)
f->code = ARCHIVE_FILTER_COMPRESS;
f->name = "compress";
return (ARCHIVE_OK);
memerr:
free_data(state);
archive_set_error(a, ENOMEM,
"Can't allocate data for compression");
return (ARCHIVE_FATAL);
}
/*
+12 -10
View File
@@ -51,24 +51,22 @@ static void free_data(struct write_grzip *);
int
archive_write_add_filter_grzip(struct archive *a)
{
struct archive_write_filter *f = __archive_write_allocate_filter(a);
struct archive_write_filter *f;
struct write_grzip *data;
archive_check_magic(a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_add_filter_grzip");
data = calloc(1, sizeof(*data));
if (data == NULL) {
archive_set_error(a, ENOMEM, "Can't allocate memory");
return (ARCHIVE_FATAL);
}
if (data == NULL)
goto memerr;
data->pdata = __archive_write_program_allocate("grzip");
if (data->pdata == NULL) {
free(data);
archive_set_error(a, ENOMEM, "Can't allocate memory");
return (ARCHIVE_FATAL);
}
if (data->pdata == NULL)
goto memerr;
f = __archive_write_allocate_filter(a);
if (f == NULL)
goto memerr;
f->name = "grzip";
f->code = ARCHIVE_FILTER_GRZIP;
f->data = data;
@@ -83,6 +81,10 @@ archive_write_add_filter_grzip(struct archive *a)
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Using external grzip program for grzip compression");
return (ARCHIVE_WARN);
memerr:
free_data(data);
archive_set_error(a, ENOMEM, "Can't allocate memory");
return (ARCHIVE_FATAL);
}
static int
+27 -21
View File
@@ -98,16 +98,33 @@ static void free_data(struct private_data *);
int
archive_write_add_filter_gzip(struct archive *a)
{
struct archive_write_filter *f = __archive_write_allocate_filter(a);
struct archive_write_filter *f;
struct private_data *data;
int r;
archive_check_magic(a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_add_filter_gzip");
data = calloc(1, sizeof(*data));
if (data == NULL) {
archive_set_error(a, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
if (data == NULL)
goto memerr;
data->original_filename = NULL;
#ifdef HAVE_ZLIB_H
data->compression_level = Z_DEFAULT_COMPRESSION;
r = ARCHIVE_OK;
#else
data->pdata = __archive_write_program_allocate("gzip");
if (data->pdata == NULL)
goto memerr;
data->compression_level = 0;
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Using external gzip program");
r = ARCHIVE_WARN;
#endif
f = __archive_write_allocate_filter(a);
if (f == NULL)
goto memerr;
f->data = data;
f->open = &archive_compressor_gzip_open;
f->write = archive_compressor_gzip_write;
@@ -117,22 +134,11 @@ archive_write_add_filter_gzip(struct archive *a)
f->code = ARCHIVE_FILTER_GZIP;
f->name = "gzip";
data->original_filename = NULL;
#ifdef HAVE_ZLIB_H
data->compression_level = Z_DEFAULT_COMPRESSION;
return (ARCHIVE_OK);
#else
data->pdata = __archive_write_program_allocate("gzip");
if (data->pdata == NULL) {
free(data);
archive_set_error(a, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
data->compression_level = 0;
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Using external gzip program");
return (ARCHIVE_WARN);
#endif
return (r);
memerr:
free_data(data);
archive_set_error(a, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
static int
+12 -10
View File
@@ -57,24 +57,22 @@ static void free_data(struct write_lrzip *);
int
archive_write_add_filter_lrzip(struct archive *a)
{
struct archive_write_filter *f = __archive_write_allocate_filter(a);
struct archive_write_filter *f;
struct write_lrzip *data;
archive_check_magic(a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_add_filter_lrzip");
data = calloc(1, sizeof(*data));
if (data == NULL) {
archive_set_error(a, ENOMEM, "Can't allocate memory");
return (ARCHIVE_FATAL);
}
if (data == NULL)
goto memerr;
data->pdata = __archive_write_program_allocate("lrzip");
if (data->pdata == NULL) {
free(data);
archive_set_error(a, ENOMEM, "Can't allocate memory");
return (ARCHIVE_FATAL);
}
if (data->pdata == NULL)
goto memerr;
f = __archive_write_allocate_filter(a);
if (f == NULL)
goto memerr;
f->name = "lrzip";
f->code = ARCHIVE_FILTER_LRZIP;
f->data = data;
@@ -89,6 +87,10 @@ archive_write_add_filter_lrzip(struct archive *a)
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Using external lrzip program for lrzip compression");
return (ARCHIVE_WARN);
memerr:
free_data(data);
archive_set_error(a, ENOMEM, "Can't allocate memory");
return (ARCHIVE_FATAL);
}
static int
+28 -25
View File
@@ -93,22 +93,19 @@ static void free_data(struct private_data *);
int
archive_write_add_filter_lz4(struct archive *a)
{
struct archive_write_filter *f = __archive_write_allocate_filter(a);
struct archive_write_filter *f;
struct private_data *data;
int r;
archive_check_magic(a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_add_filter_lz4");
data = calloc(1, sizeof(*data));
if (data == NULL) {
archive_set_error(a, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
if (data == NULL)
goto memerr;
/*
* Setup default settings.
*/
data->compression_level = 1;
data->version_number = 0x01;
data->block_independence = 1;
data->block_checksum = 0;
@@ -116,10 +113,29 @@ archive_write_add_filter_lz4(struct archive *a)
data->stream_checksum = 1;
data->preset_dictionary = 0;
data->block_maximum_size = 7;
#if defined(HAVE_LIBLZ4) && LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 2
data->compression_level = 1;
r = ARCHIVE_OK;
#else
/*
* We don't have lz4 library, and execute external lz4 program
* instead.
*/
data->pdata = __archive_write_program_allocate("lz4");
if (data->pdata == NULL)
goto memerr;
data->compression_level = 0;
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Using external lz4 program");
r = ARCHIVE_WARN;
#endif
/*
* Setup a filter setting.
*/
f = __archive_write_allocate_filter(a);
if (f == NULL)
goto memerr;
f->data = data;
f->options = &archive_filter_lz4_options;
f->close = &archive_filter_lz4_close;
@@ -128,24 +144,11 @@ archive_write_add_filter_lz4(struct archive *a)
f->write = archive_filter_lz4_write;
f->code = ARCHIVE_FILTER_LZ4;
f->name = "lz4";
#if defined(HAVE_LIBLZ4) && LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 2
return (ARCHIVE_OK);
#else
/*
* We don't have lz4 library, and execute external lz4 program
* instead.
*/
data->pdata = __archive_write_program_allocate("lz4");
if (data->pdata == NULL) {
free(data);
archive_set_error(a, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
data->compression_level = 0;
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Using external lz4 program");
return (ARCHIVE_WARN);
#endif
return (r);
memerr:
free_data(data);
archive_set_error(a, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
static int
+37 -33
View File
@@ -136,18 +136,47 @@ static const unsigned char header[] = {
int
archive_write_add_filter_lzop(struct archive *a)
{
struct archive_write_filter *f = __archive_write_allocate_filter(a);
struct archive_write_filter *f;
struct write_lzop *data;
int r;
archive_check_magic(a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_add_filter_lzop");
data = calloc(1, sizeof(*data));
if (data == NULL) {
archive_set_error(a, ENOMEM, "Can't allocate memory");
if (data == NULL)
goto memerr;
#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
if (lzo_init() != LZO_E_OK) {
free_data(data);
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"lzo_init(type check) failed");
return (ARCHIVE_FATAL);
}
if (lzo_version() < 0x940) {
free_data(data);
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"liblzo library is too old(%s < 0.940)",
lzo_version_string());
return (ARCHIVE_FATAL);
}
data->compression_level = 5;
r = ARCHIVE_OK;
#else
data->pdata = __archive_write_program_allocate("lzop");
if (data->pdata == NULL)
goto memerr;
data->compression_level = 0;
/* Note: We return "warn" to inform of using an external lzop
* program. */
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Using external lzop program for lzop compression");
r = ARCHIVE_WARN;
#endif
f = __archive_write_allocate_filter(a);
if (f == NULL)
goto memerr;
f->name = "lzop";
f->code = ARCHIVE_FILTER_LZOP;
f->data = data;
@@ -156,36 +185,11 @@ archive_write_add_filter_lzop(struct archive *a)
f->write = archive_write_lzop_write;
f->close = archive_write_lzop_close;
f->free = archive_write_lzop_free;
#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
if (lzo_init() != LZO_E_OK) {
free(data);
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"lzo_init(type check) failed");
return (ARCHIVE_FATAL);
}
if (lzo_version() < 0x940) {
free(data);
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"liblzo library is too old(%s < 0.940)",
lzo_version_string());
return (ARCHIVE_FATAL);
}
data->compression_level = 5;
return (ARCHIVE_OK);
#else
data->pdata = __archive_write_program_allocate("lzop");
if (data->pdata == NULL) {
free(data);
archive_set_error(a, ENOMEM, "Can't allocate memory");
return (ARCHIVE_FATAL);
}
data->compression_level = 0;
/* Note: We return "warn" to inform of using an external lzop
* program. */
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Using external lzop program for lzop compression");
return (ARCHIVE_WARN);
#endif
return (r);
memerr:
free_data(data);
archive_set_error(a, ENOMEM, "Can't allocate memory");
return (ARCHIVE_FATAL);
}
static int
@@ -90,26 +90,22 @@ static void free_data(struct private_data *);
int
archive_write_add_filter_program(struct archive *a, const char *cmd)
{
struct archive_write_filter *f = __archive_write_allocate_filter(a);
struct archive_write_filter *f;
struct private_data *data;
static const char prefix[] = "Program: ";
archive_check_magic(a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_add_filter_program");
f->data = calloc(1, sizeof(*data));
if (f->data == NULL)
data = calloc(1, sizeof(*data));
if (data == NULL)
goto memerr;
data = (struct private_data *)f->data;
data->cmd = strdup(cmd);
if (data->cmd == NULL)
goto memerr;
data->pdata = __archive_write_program_allocate(cmd);
if (data->pdata == NULL)
goto memerr;
/* Make up a description string. */
if (archive_string_ensure(&data->description,
strlen(prefix) + strlen(cmd) + 1) == NULL)
@@ -117,15 +113,19 @@ archive_write_add_filter_program(struct archive *a, const char *cmd)
archive_strcpy(&data->description, prefix);
archive_strcat(&data->description, cmd);
f = __archive_write_allocate_filter(a);
if (f == NULL)
goto memerr;
f->name = data->description.s;
f->code = ARCHIVE_FILTER_PROGRAM;
f->data = data;
f->open = archive_compressor_program_open;
f->write = archive_compressor_program_write;
f->close = archive_compressor_program_close;
f->free = archive_compressor_program_free;
return (ARCHIVE_OK);
memerr:
archive_compressor_program_free(f);
free_data(data);
archive_set_error(a, ENOMEM,
"Can't allocate memory for filter program");
return (ARCHIVE_FATAL);
+11 -6
View File
@@ -72,21 +72,21 @@ static void free_data(struct private_uuencode *);
int
archive_write_add_filter_uuencode(struct archive *a)
{
struct archive_write_filter *f = __archive_write_allocate_filter(a);
struct archive_write_filter *f;
struct private_uuencode *state;
archive_check_magic(a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_add_filter_uu");
state = calloc(1, sizeof(*state));
if (state == NULL) {
archive_set_error(a, ENOMEM,
"Can't allocate data for uuencode filter");
return (ARCHIVE_FATAL);
}
if (state == NULL)
goto memerr;
archive_strcpy(&state->name, "-");
state->mode = 0644;
f = __archive_write_allocate_filter(a);
if (f == NULL)
goto memerr;
f->data = state;
f->name = "uuencode";
f->code = ARCHIVE_FILTER_UU;
@@ -97,6 +97,11 @@ archive_write_add_filter_uuencode(struct archive *a)
f->free = archive_filter_uuencode_free;
return (ARCHIVE_OK);
memerr:
free_data(state);
archive_set_error(a, ENOMEM,
"Can't allocate data for uuencode filter");
return (ARCHIVE_FATAL);
}
/*
+13 -7
View File
@@ -146,24 +146,30 @@ static int
common_setup(struct archive *a, const char *name, int code)
{
struct private_data *data;
struct archive_write_filter *f = __archive_write_allocate_filter(a);
struct archive_write_filter *f;
data = calloc(1, sizeof(*data));
if (data == NULL) {
archive_set_error(a, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
if (data == NULL)
goto memerr;
data->compression_level = LZMA_PRESET_DEFAULT;
data->threads = 1;
f = __archive_write_allocate_filter(a);
if (f == NULL)
goto memerr;
f->name = name;
f->code = code;
f->data = data;
data->compression_level = LZMA_PRESET_DEFAULT;
data->threads = 1;
f->open = &archive_compressor_xz_open;
f->write = archive_compressor_xz_write;
f->close = archive_compressor_xz_close;
f->free = archive_compressor_xz_free;
f->options = &archive_compressor_xz_options;
return (ARCHIVE_OK);
memerr:
free_data(data);
archive_set_error(a, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
/*
+28 -27
View File
@@ -114,26 +114,16 @@ static void free_data(struct private_data *);
int
archive_write_add_filter_zstd(struct archive *a)
{
struct archive_write_filter *f = __archive_write_allocate_filter(a);
struct archive_write_filter *f;
struct private_data *data;
int r;
archive_check_magic(a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_add_filter_zstd");
data = calloc(1, sizeof(*data));
if (data == NULL) {
archive_set_error(a, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
f->data = data;
f->open = &archive_compressor_zstd_open;
f->write = archive_compressor_zstd_write;
f->options = &archive_compressor_zstd_options;
f->flush = &archive_compressor_zstd_flush;
f->close = &archive_compressor_zstd_close;
f->free = &archive_compressor_zstd_free;
f->code = ARCHIVE_FILTER_ZSTD;
f->name = "zstd";
if (data == NULL)
goto memerr;
data->compression_level = CLEVEL_DEFAULT;
data->threads = 0;
data->long_distance = 0;
@@ -146,25 +136,36 @@ archive_write_add_filter_zstd(struct archive *a)
data->cur_frame_in = 0;
data->cur_frame_out = 0;
data->cstream = ZSTD_createCStream();
if (data->cstream == NULL) {
free(data);
archive_set_error(a, ENOMEM,
"Failed to allocate zstd compressor object");
return (ARCHIVE_FATAL);
}
if (data->cstream == NULL)
goto memerr;
return (ARCHIVE_OK);
r = ARCHIVE_OK;
#else
data->pdata = __archive_write_program_allocate("zstd");
if (data->pdata == NULL) {
free(data);
archive_set_error(a, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
if (data->pdata == NULL)
goto memerr;
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Using external zstd program");
return (ARCHIVE_WARN);
r = ARCHIVE_WARN;
#endif
f = __archive_write_allocate_filter(a);
if (f == NULL)
goto memerr;
f->data = data;
f->open = &archive_compressor_zstd_open;
f->write = archive_compressor_zstd_write;
f->options = &archive_compressor_zstd_options;
f->flush = &archive_compressor_zstd_flush;
f->close = &archive_compressor_zstd_close;
f->free = &archive_compressor_zstd_free;
f->code = ARCHIVE_FILTER_ZSTD;
f->name = "zstd";
return (r);
memerr:
free_data(data);
archive_set_error(a, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
static int