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