Coverage Report

Created: 2025-06-24 06:40

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