]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-signature.c
tree-wide: drop 'This file is part of systemd' blurb
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-signature.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
de1c301e 2/***
de1c301e 3 Copyright 2013 Lennart Poettering
de1c301e
LP
4***/
5
6#include <util.h>
7
dccca82b
LP
8#include "sd-bus.h"
9
de1c301e
LP
10#include "bus-signature.h"
11#include "bus-type.h"
12
13static int signature_element_length_internal(
14 const char *s,
15 bool allow_dict_entry,
813a4f93
LP
16 unsigned array_depth,
17 unsigned struct_depth,
de1c301e
LP
18 size_t *l) {
19
20 int r;
21
35460afc
LP
22 if (!s)
23 return -EINVAL;
24
718db961 25 assert(l);
de1c301e
LP
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
813a4f93
LP
35 if (array_depth >= 32)
36 return -EINVAL;
37
38 r = signature_element_length_internal(s + 1, true, array_depth+1, struct_depth, &t);
de1c301e
LP
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
813a4f93
LP
49 if (struct_depth >= 32)
50 return -EINVAL;
51
de1c301e
LP
52 while (*p != SD_BUS_TYPE_STRUCT_END) {
53 size_t t;
54
813a4f93 55 r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
de1c301e
LP
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
813a4f93
LP
70 if (struct_depth >= 32)
71 return -EINVAL;
72
de1c301e
LP
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
813a4f93 79 r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
de1c301e
LP
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
813a4f93
LP
97int signature_element_length(const char *s, size_t *l) {
98 return signature_element_length_internal(s, true, 0, 0, l);
99}
100
29ddb38f 101bool signature_is_single(const char *s, bool allow_dict_entry) {
de1c301e
LP
102 int r;
103 size_t t;
104
35460afc
LP
105 if (!s)
106 return false;
de1c301e 107
29ddb38f 108 r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t);
de1c301e
LP
109 if (r < 0)
110 return false;
111
112 return s[t] == 0;
113}
114
115bool signature_is_pair(const char *s) {
718db961 116
35460afc
LP
117 if (!s)
118 return false;
de1c301e
LP
119
120 if (!bus_type_is_basic(*s))
121 return false;
122
29ddb38f 123 return signature_is_single(s + 1, false);
de1c301e
LP
124}
125
126bool signature_is_valid(const char *s, bool allow_dict_entry) {
127 const char *p;
128 int r;
129
35460afc
LP
130 if (!s)
131 return false;
de1c301e
LP
132
133 p = s;
134 while (*p) {
135 size_t t;
136
813a4f93 137 r = signature_element_length_internal(p, allow_dict_entry, 0, 0, &t);
de1c301e
LP
138 if (r < 0)
139 return false;
140
141 p += t;
142 }
143
144 return p - s <= 255;
145}