Coverage Report

Created: 2019-06-19 13:33

/src/systemd/src/libsystemd/sd-bus/bus-signature.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: LGPL-2.1+ */
2
3
#include <util.h>
4
5
#include "sd-bus.h"
6
7
#include "bus-signature.h"
8
#include "bus-type.h"
9
10
static int signature_element_length_internal(
11
                const char *s,
12
                bool allow_dict_entry,
13
                unsigned array_depth,
14
                unsigned struct_depth,
15
59.5M
                size_t *l) {
16
59.5M
17
59.5M
        int r;
18
59.5M
19
59.5M
        if (!s)
20
0
                return -EINVAL;
21
59.5M
22
59.5M
        assert(l);
23
59.5M
24
59.5M
        if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) {
25
48.7M
                *l = 1;
26
48.7M
                return 0;
27
48.7M
        }
28
10.7M
29
10.7M
        if (*s == SD_BUS_TYPE_ARRAY) {
30
1.58M
                size_t t;
31
1.58M
32
1.58M
                if (array_depth >= 32)
33
1
                        return -EINVAL;
34
1.58M
35
1.58M
                r = signature_element_length_internal(s + 1, true, array_depth+1, struct_depth, &t);
36
1.58M
                if (r < 0)
37
708
                        return r;
38
1.58M
39
1.58M
                *l = t + 1;
40
1.58M
                return 0;
41
1.58M
        }
42
9.17M
43
9.17M
        if (*s == SD_BUS_TYPE_STRUCT_BEGIN) {
44
9.04M
                const char *p = s + 1;
45
9.04M
46
9.04M
                if (struct_depth >= 32)
47
1
                        return -EINVAL;
48
9.04M
49
25.1M
                while (*p != SD_BUS_TYPE_STRUCT_END) {
50
16.1M
                        size_t t;
51
16.1M
52
16.1M
                        r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
53
16.1M
                        if (r < 0)
54
345
                                return r;
55
16.1M
56
16.1M
                        p += t;
57
16.1M
                }
58
9.04M
59
9.04M
                if (p - s < 2)
60
1
                        /* D-Bus spec: Empty structures are not allowed; there
61
1
                         * must be at least one type code between the parentheses.
62
1
                         */
63
1
                        return -EINVAL;
64
9.04M
65
9.04M
                *l = p - s + 1;
66
9.04M
                return 0;
67
9.04M
        }
68
134k
69
134k
        if (*s == SD_BUS_TYPE_DICT_ENTRY_BEGIN && allow_dict_entry) {
70
134k
                const char *p = s + 1;
71
134k
                unsigned n = 0;
72
134k
73
134k
                if (struct_depth >= 32)
74
1
                        return -EINVAL;
75
134k
76
2.17M
                while (*p != SD_BUS_TYPE_DICT_ENTRY_END) {
77
2.03M
                        size_t t;
78
2.03M
79
2.03M
                        if (n == 0 && !bus_type_is_basic(*p))
80
11
                                return -EINVAL;
81
2.03M
82
2.03M
                        r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
83
2.03M
                        if (r < 0)
84
94
                                return r;
85
2.03M
86
2.03M
                        p += t;
87
2.03M
                        n++;
88
2.03M
                }
89
134k
90
134k
                if (n != 2)
91
28
                        return -EINVAL;
92
134k
93
134k
                *l = p - s + 1;
94
134k
                return 0;
95
134k
        }
96
203
97
203
        return -EINVAL;
98
203
}
99
100
38.2M
int signature_element_length(const char *s, size_t *l) {
101
38.2M
        return signature_element_length_internal(s, true, 0, 0, l);
102
38.2M
}
103
104
70.8k
bool signature_is_single(const char *s, bool allow_dict_entry) {
105
70.8k
        int r;
106
70.8k
        size_t t;
107
70.8k
108
70.8k
        if (!s)
109
0
                return false;
110
70.8k
111
70.8k
        r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t);
112
70.8k
        if (r < 0)
113
11
                return false;
114
70.7k
115
70.7k
        return s[t] == 0;
116
70.7k
}
117
118
33.1k
bool signature_is_pair(const char *s) {
119
33.1k
120
33.1k
        if (!s)
121
0
                return false;
122
33.1k
123
33.1k
        if (!bus_type_is_basic(*s))
124
0
                return false;
125
33.1k
126
33.1k
        return signature_is_single(s + 1, false);
127
33.1k
}
128
129
538k
bool signature_is_valid(const char *s, bool allow_dict_entry) {
130
538k
        const char *p;
131
538k
        int r;
132
538k
133
538k
        if (!s)
134
0
                return false;
135
538k
136
538k
        p = s;
137
1.99M
        while (*p) {
138
1.45M
                size_t t;
139
1.45M
140
1.45M
                r = signature_element_length_internal(p, allow_dict_entry, 0, 0, &t);
141
1.45M
                if (r < 0)
142
235
                        return false;
143
1.45M
144
1.45M
                p += t;
145
1.45M
        }
146
538k
147
538k
        return p - s <= SD_BUS_MAXIMUM_SIGNATURE_LENGTH;
148
538k
}