Branch data Line data Source code
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 : 21358 : static int signature_element_length_internal(
11 : : const char *s,
12 : : bool allow_dict_entry,
13 : : unsigned array_depth,
14 : : unsigned struct_depth,
15 : : size_t *l) {
16 : :
17 : : int r;
18 : :
19 [ - + ]: 21358 : if (!s)
20 : 0 : return -EINVAL;
21 : :
22 [ - + ]: 21358 : assert(l);
23 : :
24 [ + + + + ]: 21358 : if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) {
25 : 16330 : *l = 1;
26 : 16330 : return 0;
27 : : }
28 : :
29 [ + + ]: 5028 : if (*s == SD_BUS_TYPE_ARRAY) {
30 : : size_t t;
31 : :
32 [ + + ]: 1284 : if (array_depth >= 32)
33 : 4 : return -EINVAL;
34 : :
35 : 1280 : r = signature_element_length_internal(s + 1, true, array_depth+1, struct_depth, &t);
36 [ + + ]: 1280 : if (r < 0)
37 : 136 : return r;
38 : :
39 : 1144 : *l = t + 1;
40 : 1144 : return 0;
41 : : }
42 : :
43 [ + + ]: 3744 : if (*s == SD_BUS_TYPE_STRUCT_BEGIN) {
44 : 2260 : const char *p = s + 1;
45 : :
46 [ + + ]: 2260 : if (struct_depth >= 32)
47 : 4 : return -EINVAL;
48 : :
49 [ + + ]: 6752 : while (*p != SD_BUS_TYPE_STRUCT_END) {
50 : : size_t t;
51 : :
52 : 4652 : r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
53 [ + + ]: 4652 : if (r < 0)
54 : 156 : return r;
55 : :
56 : 4496 : p += t;
57 : : }
58 : :
59 [ + + ]: 2100 : if (p - s < 2)
60 : : /* D-Bus spec: Empty structures are not allowed; there
61 : : * must be at least one type code between the parentheses.
62 : : */
63 : 40 : return -EINVAL;
64 : :
65 : 2060 : *l = p - s + 1;
66 : 2060 : return 0;
67 : : }
68 : :
69 [ + + + + ]: 1484 : if (*s == SD_BUS_TYPE_DICT_ENTRY_BEGIN && allow_dict_entry) {
70 : 1452 : const char *p = s + 1;
71 : 1452 : unsigned n = 0;
72 : :
73 [ - + ]: 1452 : if (struct_depth >= 32)
74 : 0 : return -EINVAL;
75 : :
76 [ + + ]: 4340 : while (*p != SD_BUS_TYPE_DICT_ENTRY_END) {
77 : : size_t t;
78 : :
79 [ + + + + ]: 2892 : if (n == 0 && !bus_type_is_basic(*p))
80 : 4 : return -EINVAL;
81 : :
82 : 2888 : r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
83 [ - + ]: 2888 : if (r < 0)
84 : 0 : return r;
85 : :
86 : 2888 : p += t;
87 : 2888 : n++;
88 : : }
89 : :
90 [ + + ]: 1448 : if (n != 2)
91 : 12 : return -EINVAL;
92 : :
93 : 1436 : *l = p - s + 1;
94 : 1436 : return 0;
95 : : }
96 : :
97 : 32 : return -EINVAL;
98 : : }
99 : :
100 : 6540 : int signature_element_length(const char *s, size_t *l) {
101 : 6540 : return signature_element_length_internal(s, true, 0, 0, l);
102 : : }
103 : :
104 : 1864 : bool signature_is_single(const char *s, bool allow_dict_entry) {
105 : : int r;
106 : : size_t t;
107 : :
108 [ - + ]: 1864 : if (!s)
109 : 0 : return false;
110 : :
111 : 1864 : r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t);
112 [ + + ]: 1864 : if (r < 0)
113 : 60 : return false;
114 : :
115 : 1804 : return s[t] == 0;
116 : : }
117 : :
118 : 532 : bool signature_is_pair(const char *s) {
119 : :
120 [ - + ]: 532 : if (!s)
121 : 0 : return false;
122 : :
123 [ + + ]: 532 : if (!bus_type_is_basic(*s))
124 : 12 : return false;
125 : :
126 : 520 : return signature_is_single(s + 1, false);
127 : : }
128 : :
129 : 3522 : bool signature_is_valid(const char *s, bool allow_dict_entry) {
130 : : const char *p;
131 : : int r;
132 : :
133 [ - + ]: 3522 : if (!s)
134 : 0 : return false;
135 : :
136 : 3522 : p = s;
137 [ + + ]: 7640 : while (*p) {
138 : : size_t t;
139 : :
140 : 4134 : r = signature_element_length_internal(p, allow_dict_entry, 0, 0, &t);
141 [ + + ]: 4134 : if (r < 0)
142 : 16 : return false;
143 : :
144 : 4118 : p += t;
145 : : }
146 : :
147 : 3506 : return p - s <= SD_BUS_MAXIMUM_SIGNATURE_LENGTH;
148 : : }
|