/src/systemd/src/fuzz/fuzz-compress.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* SPDX-License-Identifier: LGPL-2.1+ */ |
2 | | |
3 | | #include <errno.h> |
4 | | |
5 | | #include "alloc-util.h" |
6 | | #include "compress.h" |
7 | | #include "fuzz.h" |
8 | | |
9 | | static int compress(int alg, |
10 | | const void *src, uint64_t src_size, |
11 | 45 | void *dst, size_t dst_alloc_size, size_t *dst_size) { |
12 | 45 | |
13 | 45 | if (alg == OBJECT_COMPRESSED_LZ4) |
14 | 6 | return compress_blob_lz4(src, src_size, dst, dst_alloc_size, dst_size); |
15 | 39 | if (alg == OBJECT_COMPRESSED_XZ) |
16 | 7 | return compress_blob_xz(src, src_size, dst, dst_alloc_size, dst_size); |
17 | 32 | return -EOPNOTSUPP; |
18 | 32 | } |
19 | | |
20 | | typedef struct header { |
21 | | uint32_t alg:2; /* We have only two compression algorithms so far, but we might add |
22 | | * more in the future. Let's make this a bit wider so our fuzzer |
23 | | * cases remain stable in the future. */ |
24 | | uint32_t sw_len; |
25 | | uint32_t sw_alloc; |
26 | | uint32_t reserved[3]; /* Extra space to keep fuzz cases stable in case we need to |
27 | | * add stuff in the future. */ |
28 | | uint8_t data[]; |
29 | | } header; |
30 | | |
31 | 54 | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
32 | 54 | _cleanup_free_ void *buf = NULL, *buf2 = NULL; |
33 | 54 | int r; |
34 | 54 | |
35 | 54 | if (size < offsetof(header, data) + 1) |
36 | 9 | return 0; |
37 | 45 | |
38 | 45 | const header *h = (struct header*) data; |
39 | 45 | const size_t data_len = size - offsetof(header, data); |
40 | 45 | |
41 | 45 | int alg = h->alg; |
42 | 45 | |
43 | 45 | /* We don't want to fill the logs with messages about parse errors. |
44 | 45 | * Disable most logging if not running standalone */ |
45 | 45 | if (!getenv("SYSTEMD_LOG_LEVEL")) |
46 | 45 | log_set_max_level(LOG_CRIT); |
47 | 45 | |
48 | 45 | log_info("Using compression %s, data size=%zu", |
49 | 45 | object_compressed_to_string(alg) ?: "(none)", |
50 | 45 | data_len); |
51 | 45 | |
52 | 45 | buf = malloc(MAX(size, 128u)); /* Make the buffer a bit larger for very small data */ |
53 | 45 | if (!buf) { |
54 | 0 | log_oom(); |
55 | 0 | return 0; |
56 | 0 | } |
57 | 45 | |
58 | 45 | size_t csize; |
59 | 45 | r = compress(alg, h->data, data_len, buf, size, &csize); |
60 | 45 | if (r < 0) { |
61 | 45 | log_error_errno(r, "Compression failed: %m"); |
62 | 45 | return 0; |
63 | 45 | } |
64 | 0 | |
65 | 0 | log_debug("Compressed %zu bytes to → %zu bytes", data_len, csize); |
66 | 0 |
|
67 | 0 | size_t sw_alloc = MAX(h->sw_alloc, 1u); |
68 | 0 | buf2 = malloc(sw_alloc); |
69 | 0 | if (!buf) { |
70 | 0 | log_oom(); |
71 | 0 | return 0; |
72 | 0 | } |
73 | 0 |
|
74 | 0 | size_t sw_len = MIN(data_len - 1, h->sw_len); |
75 | 0 |
|
76 | 0 | r = decompress_startswith(alg, buf, csize, &buf2, &sw_alloc, h->data, sw_len, h->data[sw_len]); |
77 | 0 | assert_se(r > 0); |
78 | 0 |
|
79 | 0 | return 0; |
80 | 0 | } |