/src/systemd/src/libsystemd/sd-bus/bus-signature.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* SPDX-License-Identifier: LGPL-2.1+ */ |
2 | | |
3 | | #include <util.h> |
4 | | |
5 | | #include "sd-bus.h" |
6 | | |
7 | | #include "bus-signature.h" |
8 | | #include "bus-type.h" |
9 | | |
10 | | static int signature_element_length_internal( |
11 | | const char *s, |
12 | | bool allow_dict_entry, |
13 | | unsigned array_depth, |
14 | | unsigned struct_depth, |
15 | 59.5M | size_t *l) { |
16 | 59.5M | |
17 | 59.5M | int r; |
18 | 59.5M | |
19 | 59.5M | if (!s) |
20 | 0 | return -EINVAL; |
21 | 59.5M | |
22 | 59.5M | assert(l); |
23 | 59.5M | |
24 | 59.5M | if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) { |
25 | 48.7M | *l = 1; |
26 | 48.7M | return 0; |
27 | 48.7M | } |
28 | 10.7M | |
29 | 10.7M | if (*s == SD_BUS_TYPE_ARRAY) { |
30 | 1.58M | size_t t; |
31 | 1.58M | |
32 | 1.58M | if (array_depth >= 32) |
33 | 1 | return -EINVAL; |
34 | 1.58M | |
35 | 1.58M | r = signature_element_length_internal(s + 1, true, array_depth+1, struct_depth, &t); |
36 | 1.58M | if (r < 0) |
37 | 708 | return r; |
38 | 1.58M | |
39 | 1.58M | *l = t + 1; |
40 | 1.58M | return 0; |
41 | 1.58M | } |
42 | 9.17M | |
43 | 9.17M | if (*s == SD_BUS_TYPE_STRUCT_BEGIN) { |
44 | 9.04M | const char *p = s + 1; |
45 | 9.04M | |
46 | 9.04M | if (struct_depth >= 32) |
47 | 1 | return -EINVAL; |
48 | 9.04M | |
49 | 25.1M | while (*p != SD_BUS_TYPE_STRUCT_END) { |
50 | 16.1M | size_t t; |
51 | 16.1M | |
52 | 16.1M | r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t); |
53 | 16.1M | if (r < 0) |
54 | 345 | return r; |
55 | 16.1M | |
56 | 16.1M | p += t; |
57 | 16.1M | } |
58 | 9.04M | |
59 | 9.04M | if (p - s < 2) |
60 | 1 | /* D-Bus spec: Empty structures are not allowed; there |
61 | 1 | * must be at least one type code between the parentheses. |
62 | 1 | */ |
63 | 1 | return -EINVAL; |
64 | 9.04M | |
65 | 9.04M | *l = p - s + 1; |
66 | 9.04M | return 0; |
67 | 9.04M | } |
68 | 134k | |
69 | 134k | if (*s == SD_BUS_TYPE_DICT_ENTRY_BEGIN && allow_dict_entry) { |
70 | 134k | const char *p = s + 1; |
71 | 134k | unsigned n = 0; |
72 | 134k | |
73 | 134k | if (struct_depth >= 32) |
74 | 1 | return -EINVAL; |
75 | 134k | |
76 | 2.17M | while (*p != SD_BUS_TYPE_DICT_ENTRY_END) { |
77 | 2.03M | size_t t; |
78 | 2.03M | |
79 | 2.03M | if (n == 0 && !bus_type_is_basic(*p)) |
80 | 11 | return -EINVAL; |
81 | 2.03M | |
82 | 2.03M | r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t); |
83 | 2.03M | if (r < 0) |
84 | 94 | return r; |
85 | 2.03M | |
86 | 2.03M | p += t; |
87 | 2.03M | n++; |
88 | 2.03M | } |
89 | 134k | |
90 | 134k | if (n != 2) |
91 | 28 | return -EINVAL; |
92 | 134k | |
93 | 134k | *l = p - s + 1; |
94 | 134k | return 0; |
95 | 134k | } |
96 | 203 | |
97 | 203 | return -EINVAL; |
98 | 203 | } |
99 | | |
100 | 38.2M | int signature_element_length(const char *s, size_t *l) { |
101 | 38.2M | return signature_element_length_internal(s, true, 0, 0, l); |
102 | 38.2M | } |
103 | | |
104 | 70.8k | bool signature_is_single(const char *s, bool allow_dict_entry) { |
105 | 70.8k | int r; |
106 | 70.8k | size_t t; |
107 | 70.8k | |
108 | 70.8k | if (!s) |
109 | 0 | return false; |
110 | 70.8k | |
111 | 70.8k | r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t); |
112 | 70.8k | if (r < 0) |
113 | 11 | return false; |
114 | 70.7k | |
115 | 70.7k | return s[t] == 0; |
116 | 70.7k | } |
117 | | |
118 | 33.1k | bool signature_is_pair(const char *s) { |
119 | 33.1k | |
120 | 33.1k | if (!s) |
121 | 0 | return false; |
122 | 33.1k | |
123 | 33.1k | if (!bus_type_is_basic(*s)) |
124 | 0 | return false; |
125 | 33.1k | |
126 | 33.1k | return signature_is_single(s + 1, false); |
127 | 33.1k | } |
128 | | |
129 | 538k | bool signature_is_valid(const char *s, bool allow_dict_entry) { |
130 | 538k | const char *p; |
131 | 538k | int r; |
132 | 538k | |
133 | 538k | if (!s) |
134 | 0 | return false; |
135 | 538k | |
136 | 538k | p = s; |
137 | 1.99M | while (*p) { |
138 | 1.45M | size_t t; |
139 | 1.45M | |
140 | 1.45M | r = signature_element_length_internal(p, allow_dict_entry, 0, 0, &t); |
141 | 1.45M | if (r < 0) |
142 | 235 | return false; |
143 | 1.45M | |
144 | 1.45M | p += t; |
145 | 1.45M | } |
146 | 538k | |
147 | 538k | return p - s <= SD_BUS_MAXIMUM_SIGNATURE_LENGTH; |
148 | 538k | } |