]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
02942704 ZJS |
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 | void *dst, size_t dst_alloc_size, size_t *dst_size) { | |
12 | ||
13 | if (alg == OBJECT_COMPRESSED_LZ4) | |
14 | return compress_blob_lz4(src, src_size, dst, dst_alloc_size, dst_size); | |
15 | if (alg == OBJECT_COMPRESSED_XZ) | |
16 | return compress_blob_xz(src, src_size, dst, dst_alloc_size, dst_size); | |
17 | return -EOPNOTSUPP; | |
18 | } | |
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 | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { | |
32 | _cleanup_free_ void *buf = NULL, *buf2 = NULL; | |
33 | int r; | |
34 | ||
35 | if (size < offsetof(header, data) + 1) | |
36 | return 0; | |
37 | ||
38 | const header *h = (struct header*) data; | |
39 | const size_t data_len = size - offsetof(header, data); | |
40 | ||
41 | int alg = h->alg; | |
42 | ||
43 | /* We don't want to fill the logs with messages about parse errors. | |
44 | * Disable most logging if not running standalone */ | |
45 | if (!getenv("SYSTEMD_LOG_LEVEL")) | |
46 | log_set_max_level(LOG_CRIT); | |
47 | ||
48 | log_info("Using compression %s, data size=%zu", | |
49 | object_compressed_to_string(alg) ?: "(none)", | |
50 | data_len); | |
51 | ||
52 | buf = malloc(MAX(size, 128u)); /* Make the buffer a bit larger for very small data */ | |
53 | if (!buf) { | |
54 | log_oom(); | |
55 | return 0; | |
56 | } | |
57 | ||
58 | size_t csize; | |
59 | r = compress(alg, h->data, data_len, buf, size, &csize); | |
60 | if (r < 0) { | |
61 | log_error_errno(r, "Compression failed: %m"); | |
62 | return 0; | |
63 | } | |
64 | ||
65 | log_debug("Compressed %zu bytes to → %zu bytes", data_len, csize); | |
66 | ||
67 | size_t sw_alloc = MAX(h->sw_alloc, 1u); | |
68 | buf2 = malloc(sw_alloc); | |
69 | if (!buf) { | |
70 | log_oom(); | |
71 | return 0; | |
72 | } | |
73 | ||
74 | size_t sw_len = MIN(data_len - 1, h->sw_len); | |
75 | ||
319a4f4b | 76 | r = decompress_startswith(alg, buf, csize, &buf2, h->data, sw_len, h->data[sw_len]); |
02942704 ZJS |
77 | assert_se(r > 0); |
78 | ||
79 | return 0; | |
80 | } |