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