chiark / gitweb /
core/manager: remove infinite loop
[elogind.git] / src / libsystemd-bus / bus-signature.c
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 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         assert_return(s, -EINVAL);
37         assert(l);
38
39         if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) {
40                 *l = 1;
41                 return 0;
42         }
43
44         if (*s == SD_BUS_TYPE_ARRAY) {
45                 size_t t;
46
47                 if (array_depth >= 32)
48                         return -EINVAL;
49
50                 r = signature_element_length_internal(s + 1, true, array_depth+1, struct_depth, &t);
51                 if (r < 0)
52                         return r;
53
54                 *l = t + 1;
55                 return 0;
56         }
57
58         if (*s == SD_BUS_TYPE_STRUCT_BEGIN) {
59                 const char *p = s + 1;
60
61                 if (struct_depth >= 32)
62                         return -EINVAL;
63
64                 while (*p != SD_BUS_TYPE_STRUCT_END) {
65                         size_t t;
66
67                         r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
68                         if (r < 0)
69                                 return r;
70
71                         p += t;
72                 }
73
74                 *l = p - s + 1;
75                 return 0;
76         }
77
78         if (*s == SD_BUS_TYPE_DICT_ENTRY_BEGIN && allow_dict_entry) {
79                 const char *p = s + 1;
80                 unsigned n = 0;
81
82                 if (struct_depth >= 32)
83                         return -EINVAL;
84
85                 while (*p != SD_BUS_TYPE_DICT_ENTRY_END) {
86                         size_t t;
87
88                         if (n == 0 && !bus_type_is_basic(*p))
89                                 return -EINVAL;
90
91                         r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
92                         if (r < 0)
93                                 return r;
94
95                         p += t;
96                         n++;
97                 }
98
99                 if (n != 2)
100                         return -EINVAL;
101
102                 *l = p - s + 1;
103                 return 0;
104         }
105
106         return -EINVAL;
107 }
108
109
110 int signature_element_length(const char *s, size_t *l) {
111         return signature_element_length_internal(s, true, 0, 0, l);
112 }
113
114 bool signature_is_single(const char *s, bool allow_dict_entry) {
115         int r;
116         size_t t;
117
118         assert_return(s, false);
119
120         r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t);
121         if (r < 0)
122                 return false;
123
124         return s[t] == 0;
125 }
126
127 bool signature_is_pair(const char *s) {
128
129         assert_return(s, false);
130
131         if (!bus_type_is_basic(*s))
132                 return false;
133
134         return signature_is_single(s + 1, false);
135 }
136
137 bool signature_is_valid(const char *s, bool allow_dict_entry) {
138         const char *p;
139         int r;
140
141         assert_return(s, false);
142
143         p = s;
144         while (*p) {
145                 size_t t;
146
147                 r = signature_element_length_internal(p, allow_dict_entry, 0, 0, &t);
148                 if (r < 0)
149                         return false;
150
151                 p += t;
152         }
153
154         return p - s <= 255;
155 }