Line data Source code
1 : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2 :
3 : /***
4 : This file is part of systemd.
5 :
6 : Copyright 2013 Lennart Poettering
7 :
8 : systemd is free software; you can redistribute it and/or modify it
9 : under the terms of the GNU Lesser General Public License as published by
10 : the Free Software Foundation; either version 2.1 of the License, or
11 : (at your option) any later version.
12 :
13 : systemd is distributed in the hope that it will be useful, but
14 : WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : Lesser General Public License for more details.
17 :
18 : You should have received a copy of the GNU Lesser General Public License
19 : along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 : ***/
21 :
22 : #include <util.h>
23 :
24 : #include "bus-signature.h"
25 : #include "bus-type.h"
26 :
27 273811 : static int signature_element_length_internal(
28 : const char *s,
29 : bool allow_dict_entry,
30 : unsigned array_depth,
31 : unsigned struct_depth,
32 : size_t *l) {
33 :
34 : int r;
35 :
36 273811 : if (!s)
37 0 : return -EINVAL;
38 :
39 273811 : assert(l);
40 :
41 273811 : if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) {
42 194500 : *l = 1;
43 194500 : return 0;
44 : }
45 :
46 79311 : if (*s == SD_BUS_TYPE_ARRAY) {
47 : size_t t;
48 :
49 78067 : if (array_depth >= 32)
50 1 : return -EINVAL;
51 :
52 78066 : r = signature_element_length_internal(s + 1, true, array_depth+1, struct_depth, &t);
53 78066 : if (r < 0)
54 34 : return r;
55 :
56 78032 : *l = t + 1;
57 78032 : return 0;
58 : }
59 :
60 1244 : if (*s == SD_BUS_TYPE_STRUCT_BEGIN) {
61 872 : const char *p = s + 1;
62 :
63 872 : if (struct_depth >= 32)
64 1 : return -EINVAL;
65 :
66 3510 : while (*p != SD_BUS_TYPE_STRUCT_END) {
67 : size_t t;
68 :
69 1802 : r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
70 1802 : if (r < 0)
71 34 : return r;
72 :
73 1768 : p += t;
74 : }
75 :
76 837 : *l = p - s + 1;
77 837 : return 0;
78 : }
79 :
80 372 : if (*s == SD_BUS_TYPE_DICT_ENTRY_BEGIN && allow_dict_entry) {
81 363 : const char *p = s + 1;
82 363 : unsigned n = 0;
83 :
84 363 : if (struct_depth >= 32)
85 0 : return -EINVAL;
86 :
87 1448 : while (*p != SD_BUS_TYPE_DICT_ENTRY_END) {
88 : size_t t;
89 :
90 723 : if (n == 0 && !bus_type_is_basic(*p))
91 2 : return -EINVAL;
92 :
93 722 : r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
94 722 : if (r < 0)
95 0 : return r;
96 :
97 722 : p += t;
98 722 : n++;
99 : }
100 :
101 362 : if (n != 2)
102 3 : return -EINVAL;
103 :
104 359 : *l = p - s + 1;
105 359 : return 0;
106 : }
107 :
108 9 : return -EINVAL;
109 : }
110 :
111 :
112 176674 : int signature_element_length(const char *s, size_t *l) {
113 176674 : return signature_element_length_internal(s, true, 0, 0, l);
114 : }
115 :
116 15902 : bool signature_is_single(const char *s, bool allow_dict_entry) {
117 : int r;
118 : size_t t;
119 :
120 15902 : if (!s)
121 0 : return false;
122 :
123 15902 : r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t);
124 15902 : if (r < 0)
125 11 : return false;
126 :
127 15891 : return s[t] == 0;
128 : }
129 :
130 121 : bool signature_is_pair(const char *s) {
131 :
132 121 : if (!s)
133 0 : return false;
134 :
135 121 : if (!bus_type_is_basic(*s))
136 3 : return false;
137 :
138 118 : return signature_is_single(s + 1, false);
139 : }
140 :
141 501 : bool signature_is_valid(const char *s, bool allow_dict_entry) {
142 : const char *p;
143 : int r;
144 :
145 501 : if (!s)
146 0 : return false;
147 :
148 501 : p = s;
149 1643 : while (*p) {
150 : size_t t;
151 :
152 645 : r = signature_element_length_internal(p, allow_dict_entry, 0, 0, &t);
153 645 : if (r < 0)
154 4 : return false;
155 :
156 641 : p += t;
157 : }
158 :
159 497 : return p - s <= 255;
160 : }
|