diff --git a/src/basic/compress.c b/src/basic/compress.c index 39d00dbf67b..1e94635397c 100644 --- a/src/basic/compress.c +++ b/src/basic/compress.c @@ -58,11 +58,10 @@ static int zstd_ret_to_errno(size_t ret) { #define ALIGN_8(l) ALIGN_TO(l, sizeof(size_t)) static const char* const compression_table[_COMPRESSION_MAX] = { + [COMPRESSION_NONE] = "NONE", [COMPRESSION_XZ] = "XZ", [COMPRESSION_LZ4] = "LZ4", [COMPRESSION_ZSTD] = "ZSTD", - /* If we add too many more entries here, it's going to grow quite large (and be mostly sparse), since - * the array key is actually a bitmask, not a plain enum */ }; DEFINE_STRING_TABLE_LOOKUP(compression, Compression); diff --git a/src/basic/compress.h b/src/basic/compress.h index c384380b64b..fc817d219d7 100644 --- a/src/basic/compress.h +++ b/src/basic/compress.h @@ -4,12 +4,10 @@ #include typedef enum Compression { - /* These are defined the same way as the relevant object types in journal-def.h, - * i.e. OBJECT_COMPRESSED_XZ, … */ - COMPRESSION_NONE = 0, - COMPRESSION_XZ = 1, - COMPRESSION_LZ4 = 2, - COMPRESSION_ZSTD = 4, + COMPRESSION_NONE, + COMPRESSION_XZ, + COMPRESSION_LZ4, + COMPRESSION_ZSTD, _COMPRESSION_MAX, _COMPRESSION_INVALID = -EINVAL, } Compression; diff --git a/src/fuzz/fuzz-compress.c b/src/fuzz/fuzz-compress.c index 4c1186c83bb..712ab3ffa9e 100644 --- a/src/fuzz/fuzz-compress.c +++ b/src/fuzz/fuzz-compress.c @@ -35,7 +35,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { log_set_max_level(LOG_CRIT); log_info("Using compression %s, data size=%zu", - compression_to_string(alg) ?: "(none)", + compression_to_string(alg), data_len); buf = malloc(MAX(size, 128u)); /* Make the buffer a bit larger for very small data */ diff --git a/src/libsystemd/sd-journal/journal-def.h b/src/libsystemd/sd-journal/journal-def.h index 5d0417e874b..ffd1af005f1 100644 --- a/src/libsystemd/sd-journal/journal-def.h +++ b/src/libsystemd/sd-journal/journal-def.h @@ -48,7 +48,6 @@ enum { OBJECT_COMPRESSED_LZ4 = 1 << 1, OBJECT_COMPRESSED_ZSTD = 1 << 2, _OBJECT_COMPRESSED_MASK = OBJECT_COMPRESSED_XZ | OBJECT_COMPRESSED_LZ4 | OBJECT_COMPRESSED_ZSTD, - _OBJECT_COMPRESSED_MAX = _OBJECT_COMPRESSED_MASK, }; struct ObjectHeader { diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c index b1ff945cc24..2350220bf29 100644 --- a/src/libsystemd/sd-journal/journal-file.c +++ b/src/libsystemd/sd-journal/journal-file.c @@ -1383,6 +1383,8 @@ int journal_file_find_data_object_with_hash( goto next; c = COMPRESSION_FROM_OBJECT(o); + if (c < 0) + return -EPROTONOSUPPORT; if (c != COMPRESSION_NONE) { #if HAVE_COMPRESSION uint64_t l; @@ -1585,16 +1587,15 @@ static int journal_file_append_data( size_t rsize = 0; compression = compress_blob(data, size, o->data.payload, size - 1, &rsize); - - if (compression >= 0) { + if (compression > COMPRESSION_NONE) { o->object.size = htole64(offsetof(Object, data.payload) + rsize); - o->object.flags |= compression; + o->object.flags |= COMPRESSION_TO_MASK(compression); log_debug("Compressed data object %"PRIu64" -> %zu using %s", size, rsize, compression_to_string(compression)); } else /* Compression didn't work, we don't really care why, let's continue without compression */ - compression = 0; + compression = COMPRESSION_NONE; } #endif @@ -3716,6 +3717,8 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6 return -E2BIG; c = COMPRESSION_FROM_OBJECT(o); + if (c < 0) + return -EPROTONOSUPPORT; if (c != COMPRESSION_NONE) { #if HAVE_COMPRESSION size_t rsize = 0; diff --git a/src/libsystemd/sd-journal/journal-file.h b/src/libsystemd/sd-journal/journal-file.h index 78539f8ffac..04266958c12 100644 --- a/src/libsystemd/sd-journal/journal-file.h +++ b/src/libsystemd/sd-journal/journal-file.h @@ -270,11 +270,29 @@ const char* journal_object_type_to_string(ObjectType type) _const_; static inline Compression COMPRESSION_FROM_OBJECT(const Object *o) { assert(o); - /* These flags and enums are defined the same way. Make sure this is really the case. */ - assert_cc((Compression) 0 == COMPRESSION_NONE); - assert_cc((Compression) OBJECT_COMPRESSED_XZ == COMPRESSION_XZ); - assert_cc((Compression) OBJECT_COMPRESSED_LZ4 == COMPRESSION_LZ4); - assert_cc((Compression) OBJECT_COMPRESSED_ZSTD == COMPRESSION_ZSTD); - - return o->object.flags & _OBJECT_COMPRESSED_MASK; + switch (o->object.flags & _OBJECT_COMPRESSED_MASK) { + case 0: + return COMPRESSION_NONE; + case OBJECT_COMPRESSED_XZ: + return COMPRESSION_XZ; + case OBJECT_COMPRESSED_LZ4: + return COMPRESSION_LZ4; + case OBJECT_COMPRESSED_ZSTD: + return COMPRESSION_ZSTD; + default: + return _COMPRESSION_INVALID; + } +} + +static inline uint8_t COMPRESSION_TO_MASK(Compression c) { + switch (c) { + case COMPRESSION_XZ: + return OBJECT_COMPRESSED_XZ; + case COMPRESSION_LZ4: + return OBJECT_COMPRESSED_LZ4; + case COMPRESSION_ZSTD: + return OBJECT_COMPRESSED_ZSTD; + default: + return 0; + } } diff --git a/src/libsystemd/sd-journal/journal-verify.c b/src/libsystemd/sd-journal/journal-verify.c index d9f7c6f7e69..3b2b72f0c75 100644 --- a/src/libsystemd/sd-journal/journal-verify.c +++ b/src/libsystemd/sd-journal/journal-verify.c @@ -119,6 +119,8 @@ static int hash_payload(JournalFile *f, Object *o, uint64_t offset, const uint8_ assert(res_hash); c = COMPRESSION_FROM_OBJECT(o); + if (c < 0) + return -EBADMSG; if (c != COMPRESSION_NONE) { _cleanup_free_ void *b = NULL; size_t b_size; diff --git a/src/libsystemd/sd-journal/sd-journal.c b/src/libsystemd/sd-journal/sd-journal.c index aa2284386c4..80145c43e99 100644 --- a/src/libsystemd/sd-journal/sd-journal.c +++ b/src/libsystemd/sd-journal/sd-journal.c @@ -2312,6 +2312,8 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void ** l = le64toh(d->object.size) - offsetof(Object, data.payload); c = COMPRESSION_FROM_OBJECT(d); + if (c < 0) + return -EPROTONOSUPPORT; if (c != COMPRESSION_NONE) { #if HAVE_COMPRESSION r = decompress_startswith( @@ -2386,6 +2388,8 @@ static int return_data( return -E2BIG; c = COMPRESSION_FROM_OBJECT(o); + if (c < 0) + return -EPROTONOSUPPORT; if (c != COMPRESSION_NONE) { #if HAVE_COMPRESSION size_t rsize; diff --git a/src/test/test-tables.c b/src/test/test-tables.c index 5f8910a1a51..ed409701b93 100644 --- a/src/test/test-tables.c +++ b/src/test/test-tables.c @@ -122,8 +122,7 @@ int main(int argc, char **argv) { test_table(unit_load_state, UNIT_LOAD_STATE); test_table(unit_type, UNIT_TYPE); test_table(virtualization, VIRTUALIZATION); - - test_table_sparse(compression, COMPRESSION); + test_table(compression, COMPRESSION); assert_cc(sizeof(sd_device_action_t) == sizeof(int64_t));