]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/fuzz-bus-match.c
tree-wide: port various things over to CLEANUP_ARRAY()
[thirdparty/systemd.git] / src / libsystemd / sd-bus / fuzz-bus-match.c
CommitLineData
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
11int 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}