]>
Commit | Line | Data |
---|---|---|
84f11eda ZJS |
1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2 | ||
3 | #include "alloc-util.h" | |
4 | #include "bus-internal.h" | |
5 | #include "bus-match.h" | |
6 | #include "env-util.h" | |
7 | #include "fd-util.h" | |
8 | #include "fileio.h" | |
9 | #include "fuzz.h" | |
10 | ||
11 | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { | |
12 | _cleanup_free_ char *out = NULL; /* out should be freed after g */ | |
13 | size_t out_size; | |
14 | _cleanup_fclose_ FILE *g = NULL; | |
15 | _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; | |
16 | int r; | |
17 | ||
c4f883b7 | 18 | if (outside_size_range(size, 0, 65536)) |
7593691a YW |
19 | return 0; |
20 | ||
84f11eda ZJS |
21 | /* We don't want to fill the logs with messages about parse errors. |
22 | * Disable most logging if not running standalone */ | |
23 | if (!getenv("SYSTEMD_LOG_LEVEL")) | |
24 | log_set_max_level(LOG_CRIT); | |
25 | ||
26 | r = sd_bus_new(&bus); | |
27 | assert_se(r >= 0); | |
28 | ||
29 | struct bus_match_node root = { | |
30 | .type = BUS_MATCH_ROOT, | |
31 | }; | |
32 | ||
33 | /* Note that we use the pointer to match_callback substructure, but the code | |
34 | * uses container_of() to access outside of the passed-in type. */ | |
35 | sd_bus_slot slot = { | |
36 | .type = BUS_MATCH_CALLBACK, | |
37 | .match_callback = {}, | |
38 | }; | |
39 | ||
40 | if (getenv_bool("SYSTEMD_FUZZ_OUTPUT") <= 0) | |
41 | assert_se(g = open_memstream_unlocked(&out, &out_size)); | |
42 | ||
43 | for (size_t offset = 0; offset < size; ) { | |
44 | _cleanup_free_ char *line = NULL; | |
45 | char *end; | |
46 | ||
47 | end = memchr((char*) data + offset, '\n', size - offset); | |
48 | ||
49 | line = memdup_suffix0((char*) data + offset, | |
50 | end ? end - (char*) data - offset : size - offset); | |
51 | if (!line) | |
52 | return log_oom_debug(); | |
53 | ||
54 | offset = end ? (size_t) (end - (char*) data + 1) : size; | |
55 | ||
56 | struct bus_match_component *components; | |
8c2d0d3a | 57 | size_t n_components; |
84f11eda ZJS |
58 | r = bus_match_parse(line, &components, &n_components); |
59 | if (IN_SET(r, -EINVAL, -ENOMEM)) { | |
60 | log_debug_errno(r, "Failed to parse line: %m"); | |
61 | continue; | |
62 | } | |
63 | assert_se(r >= 0); /* We only expect EINVAL and ENOMEM errors, or success. */ | |
64 | ||
8c2d0d3a LP |
65 | CLEANUP_ARRAY(components, n_components, bus_match_parse_free); |
66 | ||
67 | log_debug("Parsed %zu components.", n_components); | |
84f11eda ZJS |
68 | |
69 | _cleanup_free_ char *again = bus_match_to_string(components, n_components); | |
70 | if (!again) { | |
84f11eda ZJS |
71 | log_oom(); |
72 | break; | |
73 | } | |
74 | ||
75 | if (g) | |
76 | fprintf(g, "%s\n", again); | |
77 | ||
78 | r = bus_match_add(&root, components, n_components, &slot.match_callback); | |
84f11eda ZJS |
79 | if (r < 0) { |
80 | log_error_errno(r, "Failed to add match: %m"); | |
81 | break; | |
82 | } | |
83 | } | |
84 | ||
85 | bus_match_dump(g ?: stdout, &root, 0); /* We do this even on failure, to check consistency after error. */ | |
86 | bus_match_free(&root); | |
87 | ||
88 | return 0; | |
89 | } |