chiark / gitweb /
662a1eac5f78775554ef4095333b0244382828ea
[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
8 #include <util.h>
9
10 #include "sd-bus.h"
11
12 #include "bus-signature.h"
13 #include "bus-type.h"
14
15 static int signature_element_length_internal(
16                 const char *s,
17                 bool allow_dict_entry,
18                 unsigned array_depth,
19                 unsigned struct_depth,
20                 size_t *l) {
21
22         int r;
23
24         if (!s)
25                 return -EINVAL;
26
27         assert(l);
28
29         if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) {
30                 *l = 1;
31                 return 0;
32         }
33
34         if (*s == SD_BUS_TYPE_ARRAY) {
35                 size_t t;
36
37                 if (array_depth >= 32)
38                         return -EINVAL;
39
40                 r = signature_element_length_internal(s + 1, true, array_depth+1, struct_depth, &t);
41                 if (r < 0)
42                         return r;
43
44                 *l = t + 1;
45                 return 0;
46         }
47
48         if (*s == SD_BUS_TYPE_STRUCT_BEGIN) {
49                 const char *p = s + 1;
50
51                 if (struct_depth >= 32)
52                         return -EINVAL;
53
54                 while (*p != SD_BUS_TYPE_STRUCT_END) {
55                         size_t t;
56
57                         r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
58                         if (r < 0)
59                                 return r;
60
61                         p += t;
62                 }
63
64                 *l = p - s + 1;
65                 return 0;
66         }
67
68         if (*s == SD_BUS_TYPE_DICT_ENTRY_BEGIN && allow_dict_entry) {
69                 const char *p = s + 1;
70                 unsigned n = 0;
71
72                 if (struct_depth >= 32)
73                         return -EINVAL;
74
75                 while (*p != SD_BUS_TYPE_DICT_ENTRY_END) {
76                         size_t t;
77
78                         if (n == 0 && !bus_type_is_basic(*p))
79                                 return -EINVAL;
80
81                         r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
82                         if (r < 0)
83                                 return r;
84
85                         p += t;
86                         n++;
87                 }
88
89                 if (n != 2)
90                         return -EINVAL;
91
92                 *l = p - s + 1;
93                 return 0;
94         }
95
96         return -EINVAL;
97 }
98
99 int signature_element_length(const char *s, size_t *l) {
100         return signature_element_length_internal(s, true, 0, 0, l);
101 }
102
103 bool signature_is_single(const char *s, bool allow_dict_entry) {
104         int r;
105         size_t t;
106
107         if (!s)
108                 return false;
109
110         r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t);
111         if (r < 0)
112                 return false;
113
114         return s[t] == 0;
115 }
116
117 bool signature_is_pair(const char *s) {
118
119         if (!s)
120                 return false;
121
122         if (!bus_type_is_basic(*s))
123                 return false;
124
125         return signature_is_single(s + 1, false);
126 }
127
128 bool signature_is_valid(const char *s, bool allow_dict_entry) {
129         const char *p;
130         int r;
131
132         if (!s)
133                 return false;
134
135         p = s;
136         while (*p) {
137                 size_t t;
138
139                 r = signature_element_length_internal(p, allow_dict_entry, 0, 0, &t);
140                 if (r < 0)
141                         return false;
142
143                 p += t;
144         }
145
146         return p - s <= 255;
147 }