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