1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include "conf-parser.h"
4 #include "fd-util.h"
5 #include "fuzz.h"
6 #include "install.h"
7 #include "load-fragment.h"
8 #include "manager-dump.h"
9 #include "string-util.h"
10 #include "unit-serialize.h"
11 #include "utf8.h"
12 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)13 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
14         _cleanup_free_ char *out = NULL; /* out should be freed after g */
15         size_t out_size;
16         _cleanup_fclose_ FILE *f = NULL, *g = NULL;
17         _cleanup_free_ char *p = NULL;
18         UnitType t;
19         _cleanup_(manager_freep) Manager *m = NULL;
20         Unit *u;
21         const char *name;
22         long offset;
23 
24         if (outside_size_range(size, 0, 65536))
25                 return 0;
26 
27         f = data_to_file(data, size);
28 
29         assert_se(f);
30 
31         if (read_line(f, LINE_MAX, &p) < 0)
32                 return 0;
33 
34         t = unit_type_from_string(p);
35         if (t < 0)
36                 return 0;
37 
38         if (!unit_vtable[t]->load)
39                 return 0;
40 
41         offset = ftell(f);
42         assert_se(offset >= 0);
43 
44         for (;;) {
45                 _cleanup_free_ char *l = NULL;
46                 const char *ll;
47 
48                 if (read_line(f, LONG_LINE_MAX, &l) <= 0)
49                         break;
50 
51                 ll = startswith(l, UTF8_BYTE_ORDER_MARK) ?: l;
52                 ll = ll + strspn(ll, WHITESPACE);
53 
54                 if (HAS_FEATURE_MEMORY_SANITIZER && startswith(ll, "ListenNetlink")) {
55                         /* ListenNetlink causes a false positive in msan,
56                          * let's skip this for now. */
57                         log_notice("Skipping test because ListenNetlink= is present");
58                         return 0;
59                 }
60         }
61 
62         assert_se(fseek(f, offset, SEEK_SET) == 0);
63 
64         /* We don't want to fill the logs with messages about parse errors.
65          * Disable most logging if not running standalone */
66         if (!getenv("SYSTEMD_LOG_LEVEL"))
67                 log_set_max_level(LOG_CRIT);
68 
69         assert_se(manager_new(LOOKUP_SCOPE_SYSTEM, MANAGER_TEST_RUN_MINIMAL, &m) >= 0);
70 
71         name = strjoina("a.", unit_type_to_string(t));
72         assert_se(unit_new_for_name(m, unit_vtable[t]->object_size, name, &u) >= 0);
73 
74         (void) config_parse(
75                         name, name, f,
76                         UNIT_VTABLE(u)->sections,
77                         config_item_perf_lookup, load_fragment_gperf_lookup,
78                         0,
79                         u,
80                         NULL);
81 
82         g = open_memstream_unlocked(&out, &out_size);
83         assert_se(g);
84 
85         unit_dump(u, g, "");
86         manager_dump(m, g, ">>>");
87 
88         return 0;
89 }
90