]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-signature.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-signature.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
de1c301e
LP
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 "bus-signature.h"
24#include "bus-type.h"
25
26static int signature_element_length_internal(
27 const char *s,
28 bool allow_dict_entry,
813a4f93
LP
29 unsigned array_depth,
30 unsigned struct_depth,
de1c301e
LP
31 size_t *l) {
32
33 int r;
34
35460afc
LP
35 if (!s)
36 return -EINVAL;
37
718db961 38 assert(l);
de1c301e
LP
39
40 if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) {
41 *l = 1;
42 return 0;
43 }
44
45 if (*s == SD_BUS_TYPE_ARRAY) {
46 size_t t;
47
813a4f93
LP
48 if (array_depth >= 32)
49 return -EINVAL;
50
51 r = signature_element_length_internal(s + 1, true, array_depth+1, struct_depth, &t);
de1c301e
LP
52 if (r < 0)
53 return r;
54
55 *l = t + 1;
56 return 0;
57 }
58
59 if (*s == SD_BUS_TYPE_STRUCT_BEGIN) {
60 const char *p = s + 1;
61
813a4f93
LP
62 if (struct_depth >= 32)
63 return -EINVAL;
64
de1c301e
LP
65 while (*p != SD_BUS_TYPE_STRUCT_END) {
66 size_t t;
67
813a4f93 68 r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
de1c301e
LP
69 if (r < 0)
70 return r;
71
72 p += t;
73 }
74
75 *l = p - s + 1;
76 return 0;
77 }
78
79 if (*s == SD_BUS_TYPE_DICT_ENTRY_BEGIN && allow_dict_entry) {
80 const char *p = s + 1;
81 unsigned n = 0;
82
813a4f93
LP
83 if (struct_depth >= 32)
84 return -EINVAL;
85
de1c301e
LP
86 while (*p != SD_BUS_TYPE_DICT_ENTRY_END) {
87 size_t t;
88
89 if (n == 0 && !bus_type_is_basic(*p))
90 return -EINVAL;
91
813a4f93 92 r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
de1c301e
LP
93 if (r < 0)
94 return r;
95
96 p += t;
97 n++;
98 }
99
100 if (n != 2)
101 return -EINVAL;
102
103 *l = p - s + 1;
104 return 0;
105 }
106
107 return -EINVAL;
108}
109
813a4f93
LP
110
111int signature_element_length(const char *s, size_t *l) {
112 return signature_element_length_internal(s, true, 0, 0, l);
113}
114
29ddb38f 115bool signature_is_single(const char *s, bool allow_dict_entry) {
de1c301e
LP
116 int r;
117 size_t t;
118
35460afc
LP
119 if (!s)
120 return false;
de1c301e 121
29ddb38f 122 r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t);
de1c301e
LP
123 if (r < 0)
124 return false;
125
126 return s[t] == 0;
127}
128
129bool signature_is_pair(const char *s) {
718db961 130
35460afc
LP
131 if (!s)
132 return false;
de1c301e
LP
133
134 if (!bus_type_is_basic(*s))
135 return false;
136
29ddb38f 137 return signature_is_single(s + 1, false);
de1c301e
LP
138}
139
140bool signature_is_valid(const char *s, bool allow_dict_entry) {
141 const char *p;
142 int r;
143
35460afc
LP
144 if (!s)
145 return false;
de1c301e
LP
146
147 p = s;
148 while (*p) {
149 size_t t;
150
813a4f93 151 r = signature_element_length_internal(p, allow_dict_entry, 0, 0, &t);
de1c301e
LP
152 if (r < 0)
153 return false;
154
155 p += t;
156 }
157
158 return p - s <= 255;
159}