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 5434 : 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 5434 : if (!s)
20 0 : return -EINVAL;
21 :
22 5434 : assert(l);
23 :
24 5434 : if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) {
25 4177 : *l = 1;
26 4177 : return 0;
27 : }
28 :
29 1257 : if (*s == SD_BUS_TYPE_ARRAY) {
30 : size_t t;
31 :
32 321 : if (array_depth >= 32)
33 1 : return -EINVAL;
34 :
35 320 : r = signature_element_length_internal(s + 1, true, array_depth+1, struct_depth, &t);
36 320 : if (r < 0)
37 34 : return r;
38 :
39 286 : *l = t + 1;
40 286 : return 0;
41 : }
42 :
43 936 : if (*s == SD_BUS_TYPE_STRUCT_BEGIN) {
44 565 : const char *p = s + 1;
45 :
46 565 : if (struct_depth >= 32)
47 1 : return -EINVAL;
48 :
49 1688 : while (*p != SD_BUS_TYPE_STRUCT_END) {
50 : size_t t;
51 :
52 1163 : r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
53 1163 : if (r < 0)
54 39 : return r;
55 :
56 1124 : p += t;
57 : }
58 :
59 525 : 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 10 : return -EINVAL;
64 :
65 515 : *l = p - s + 1;
66 515 : return 0;
67 : }
68 :
69 371 : if (*s == SD_BUS_TYPE_DICT_ENTRY_BEGIN && allow_dict_entry) {
70 363 : const char *p = s + 1;
71 363 : unsigned n = 0;
72 :
73 363 : if (struct_depth >= 32)
74 0 : return -EINVAL;
75 :
76 1085 : while (*p != SD_BUS_TYPE_DICT_ENTRY_END) {
77 : size_t t;
78 :
79 723 : if (n == 0 && !bus_type_is_basic(*p))
80 1 : return -EINVAL;
81 :
82 722 : r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
83 722 : if (r < 0)
84 0 : return r;
85 :
86 722 : p += t;
87 722 : n++;
88 : }
89 :
90 362 : if (n != 2)
91 3 : return -EINVAL;
92 :
93 359 : *l = p - s + 1;
94 359 : return 0;
95 : }
96 :
97 8 : return -EINVAL;
98 : }
99 :
100 1635 : int signature_element_length(const char *s, size_t *l) {
101 1635 : return signature_element_length_internal(s, true, 0, 0, l);
102 : }
103 :
104 466 : bool signature_is_single(const char *s, bool allow_dict_entry) {
105 : int r;
106 : size_t t;
107 :
108 466 : if (!s)
109 0 : return false;
110 :
111 466 : r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t);
112 466 : if (r < 0)
113 15 : return false;
114 :
115 451 : return s[t] == 0;
116 : }
117 :
118 133 : bool signature_is_pair(const char *s) {
119 :
120 133 : if (!s)
121 0 : return false;
122 :
123 133 : if (!bus_type_is_basic(*s))
124 3 : return false;
125 :
126 130 : return signature_is_single(s + 1, false);
127 : }
128 :
129 947 : bool signature_is_valid(const char *s, bool allow_dict_entry) {
130 : const char *p;
131 : int r;
132 :
133 947 : if (!s)
134 0 : return false;
135 :
136 947 : p = s;
137 2071 : while (*p) {
138 : size_t t;
139 :
140 1128 : r = signature_element_length_internal(p, allow_dict_entry, 0, 0, &t);
141 1128 : if (r < 0)
142 4 : return false;
143 :
144 1124 : p += t;
145 : }
146 :
147 943 : return p - s <= SD_BUS_MAXIMUM_SIGNATURE_LENGTH;
148 : }
|