Bug Summary

File:build-scan/../src/libsystemd/sd-bus/bus-message.c
Warning:line 473, column 33
Potential leak of memory pointed to by 'm'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name bus-message.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/libsystemd/libsystemd_static.a.p -I src/libsystemd -I ../src/libsystemd -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility default -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/libsystemd/sd-bus/bus-message.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2/***
3***/
4
5#include <errno(*__errno_location ()).h>
6#include <fcntl.h>
7#include <sys/mman.h>
8
9#include "sd-bus.h"
10
11#include "alloc-util.h"
12#include "bus-gvariant.h"
13#include "bus-internal.h"
14#include "bus-message.h"
15#include "bus-signature.h"
16#include "bus-type.h"
17#include "bus-util.h"
18#include "fd-util.h"
19#include "io-util.h"
20#include "memfd-util.h"
21#include "string-util.h"
22#include "strv.h"
23#include "time-util.h"
24#include "utf8.h"
25#include "util.h"
26
27static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
28
29static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
30
31 if (p == NULL((void*)0))
32 return NULL((void*)0);
33
34 if (old_base == new_base)
35 return (void*) p;
36
37 if ((uint8_t*) p < (uint8_t*) old_base)
38 return (void*) p;
39
40 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
41 return (void*) p;
42
43 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
44}
45
46static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
47 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 47, __PRETTY_FUNCTION__); } while (0)
;
48 assert(part)do { if ((__builtin_expect(!!(!(part)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("part"), "../src/libsystemd/sd-bus/bus-message.c"
, 48, __PRETTY_FUNCTION__); } while (0)
;
49
50 if (part->memfd >= 0)
51 close_and_munmap(part->memfd, part->mmap_begin, part->mapped);
52 else if (part->munmap_this)
53 munmap(part->mmap_begin, part->mapped);
54 else if (part->free_this)
55 free(part->data);
56
57 if (part != &m->body)
58 free(part);
59}
60
61static void message_reset_parts(sd_bus_message *m) {
62 struct bus_body_part *part;
63
64 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 64, __PRETTY_FUNCTION__); } while (0)
;
65
66 part = &m->body;
67 while (m->n_body_parts > 0) {
68 struct bus_body_part *next = part->next;
69 message_free_part(m, part);
70 part = next;
71 m->n_body_parts--;
72 }
73
74 m->body_end = NULL((void*)0);
75
76 m->cached_rindex_part = NULL((void*)0);
77 m->cached_rindex_part_begin = 0;
78}
79
80static struct bus_container *message_get_last_container(sd_bus_message *m) {
81 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 81, __PRETTY_FUNCTION__); } while (0)
;
82
83 if (m->n_containers == 0)
84 return &m->root_container;
85
86 assert(m->containers)do { if ((__builtin_expect(!!(!(m->containers)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m->containers"), "../src/libsystemd/sd-bus/bus-message.c"
, 86, __PRETTY_FUNCTION__); } while (0)
;
87 return m->containers + m->n_containers - 1;
88}
89
90static void message_free_last_container(sd_bus_message *m) {
91 struct bus_container *c;
92
93 c = message_get_last_container(m);
94
95 free(c->signature);
96 free(c->peeked_signature);
97 free(c->offsets);
98
99 /* Move to previous container, but not if we are on root container */
100 if (m->n_containers > 0)
101 m->n_containers--;
102}
103
104static void message_reset_containers(sd_bus_message *m) {
105 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 105, __PRETTY_FUNCTION__); } while (0)
;
106
107 while (m->n_containers > 0)
108 message_free_last_container(m);
109
110 m->containers = mfree(m->containers);
111 m->containers_allocated = 0;
112 m->root_container.index = 0;
113}
114
115static sd_bus_message* message_free(sd_bus_message *m) {
116 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 116, __PRETTY_FUNCTION__); } while (0)
;
117
118 if (m->free_header)
119 free(m->header);
120
121 message_reset_parts(m);
122
123 /* Note that we don't unref m->bus here. That's already done by sd_bus_message_unref() as each user
124 * reference to the bus message also is considered a reference to the bus connection itself. */
125
126 if (m->free_fds) {
127 close_many(m->fds, m->n_fds);
128 free(m->fds);
129 }
130
131 if (m->iovec != m->iovec_fixed)
132 free(m->iovec);
133
134 message_reset_containers(m);
135 assert(m->n_containers == 0)do { if ((__builtin_expect(!!(!(m->n_containers == 0)),0))
) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("m->n_containers == 0"
), "../src/libsystemd/sd-bus/bus-message.c", 135, __PRETTY_FUNCTION__
); } while (0)
;
136 message_free_last_container(m);
137
138 bus_creds_done(&m->creds);
139 return mfree(m);
140}
141
142static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool_Bool add_offset) {
143 void *op, *np;
144 size_t old_size, new_size, start;
145
146 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 146, __PRETTY_FUNCTION__); } while (0)
;
147
148 if (m->poisoned)
149 return NULL((void*)0);
150
151 old_size = sizeof(struct bus_header) + m->fields_size;
152 start = ALIGN_TO(old_size, align);
153 new_size = start + sz;
154
155 if (new_size < start ||
156 new_size > (size_t) ((uint32_t) -1))
157 goto poison;
158
159 if (old_size == new_size)
160 return (uint8_t*) m->header + old_size;
161
162 if (m->free_header) {
163 np = realloc(m->header, ALIGN8(new_size)(((new_size) + 7) & ~7));
164 if (!np)
165 goto poison;
166 } else {
167 /* Initially, the header is allocated as part of
168 * the sd_bus_message itself, let's replace it by
169 * dynamic data */
170
171 np = malloc(ALIGN8(new_size)(((new_size) + 7) & ~7));
172 if (!np)
173 goto poison;
174
175 memcpy(np, m->header, sizeof(struct bus_header));
176 }
177
178 /* Zero out padding */
179 if (start > old_size)
180 memzero((uint8_t*) np + old_size, start - old_size)({ size_t _l_ = (start - old_size); void *_x_ = ((uint8_t*) np
+ old_size); _l_ == 0 ? _x_ : memset(_x_, 0, _l_); })
;
181
182 op = m->header;
183 m->header = np;
184 m->fields_size = new_size - sizeof(struct bus_header);
185
186 /* Adjust quick access pointers */
187 m->path = adjust_pointer(m->path, op, old_size, m->header);
188 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
189 m->member = adjust_pointer(m->member, op, old_size, m->header);
190 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
191 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
192 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
193
194 m->free_header = true1;
195
196 if (add_offset) {
197 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(m->header_offsets), typeof(&*(m->header_offsets
))), sizeof(m->header_offsets)/sizeof((m->header_offsets
)[0]), ((void)0)))
)
198 goto poison;
199
200 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
201 }
202
203 return (uint8_t*) np + start;
204
205poison:
206 m->poisoned = true1;
207 return NULL((void*)0);
208}
209
210static int message_append_field_string(
211 sd_bus_message *m,
212 uint64_t h,
213 char type,
214 const char *s,
215 const char **ret) {
216
217 size_t l;
218 uint8_t *p;
219
220 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 220, __PRETTY_FUNCTION__); } while (0)
;
221
222 /* dbus1 only allows 8bit header field ids */
223 if (h > 0xFF)
224 return -EINVAL22;
225
226 /* dbus1 doesn't allow strings over 32bit, let's enforce this
227 * globally, to not risk convertability */
228 l = strlen(s);
229 if (l > UINT32_MAX(4294967295U))
230 return -EINVAL22;
231
232 /* Signature "(yv)" where the variant contains "s" */
233
234 if (BUS_MESSAGE_IS_GVARIANT(m)) {
235
236 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
237 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true1);
238 if (!p)
239 return -ENOMEM12;
240
241 *((uint64_t*) p) = h;
242 memcpy(p+8, s, l);
243 p[8+l] = 0;
244 p[8+l+1] = 0;
245 p[8+l+2] = type;
246
247 if (ret)
248 *ret = (char*) p + 8;
249
250 } else {
251 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
252 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false0);
253 if (!p)
254 return -ENOMEM12;
255
256 p[0] = (uint8_t) h;
257 p[1] = 1;
258 p[2] = type;
259 p[3] = 0;
260
261 ((uint32_t*) p)[1] = l;
262 memcpy(p + 8, s, l + 1);
263
264 if (ret)
265 *ret = (char*) p + 8;
266 }
267
268 return 0;
269}
270
271static int message_append_field_signature(
272 sd_bus_message *m,
273 uint64_t h,
274 const char *s,
275 const char **ret) {
276
277 size_t l;
278 uint8_t *p;
279
280 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 280, __PRETTY_FUNCTION__); } while (0)
;
281
282 /* dbus1 only allows 8bit header field ids */
283 if (h > 0xFF)
284 return -EINVAL22;
285
286 /* dbus1 doesn't allow signatures over 8bit, let's enforce
287 * this globally, to not risk convertability */
288 l = strlen(s);
289 if (l > 255)
290 return -EINVAL22;
291
292 /* Signature "(yv)" where the variant contains "g" */
293
294 if (BUS_MESSAGE_IS_GVARIANT(m))
295 /* For gvariant the serialization is the same as for normal strings */
296 return message_append_field_string(m, h, 'g', s, ret);
297 else {
298 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
299 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false0);
300 if (!p)
301 return -ENOMEM12;
302
303 p[0] = (uint8_t) h;
304 p[1] = 1;
305 p[2] = SD_BUS_TYPE_SIGNATURE;
306 p[3] = 0;
307 p[4] = l;
308 memcpy(p + 5, s, l + 1);
309
310 if (ret)
311 *ret = (const char*) p + 5;
312 }
313
314 return 0;
315}
316
317static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
318 uint8_t *p;
319
320 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 320, __PRETTY_FUNCTION__); } while (0)
;
321
322 /* dbus1 only allows 8bit header field ids */
323 if (h > 0xFF)
324 return -EINVAL22;
325
326 if (BUS_MESSAGE_IS_GVARIANT(m)) {
327 /* (field id 64bit + ((value + NUL + signature string 'u') */
328
329 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true1);
330 if (!p)
331 return -ENOMEM12;
332
333 *((uint64_t*) p) = h;
334 *((uint32_t*) (p + 8)) = x;
335 p[12] = 0;
336 p[13] = 'u';
337 } else {
338 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
339 p = message_extend_fields(m, 8, 4 + 4, false0);
340 if (!p)
341 return -ENOMEM12;
342
343 p[0] = (uint8_t) h;
344 p[1] = 1;
345 p[2] = 'u';
346 p[3] = 0;
347
348 ((uint32_t*) p)[1] = x;
349 }
350
351 return 0;
352}
353
354static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
355 uint8_t *p;
356
357 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 357, __PRETTY_FUNCTION__); } while (0)
;
358
359 /* dbus1 only allows 8bit header field ids */
360 if (h > 0xFF)
361 return -EINVAL22;
362
363 if (BUS_MESSAGE_IS_GVARIANT(m)) {
364 /* (field id 64bit + ((value + NUL + signature string 't') */
365
366 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true1);
367 if (!p)
368 return -ENOMEM12;
369
370 *((uint64_t*) p) = h;
371 *((uint64_t*) (p + 8)) = x;
372 p[16] = 0;
373 p[17] = 't';
374 } else {
375 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
376 p = message_extend_fields(m, 8, 4 + 4 + 8, false0);
377 if (!p)
378 return -ENOMEM12;
379
380 p[0] = (uint8_t) h;
381 p[1] = 1;
382 p[2] = 't';
383 p[3] = 0;
384 p[4] = 0;
385 p[5] = 0;
386 p[6] = 0;
387 p[7] = 0;
388
389 ((uint64_t*) p)[1] = x;
390 }
391
392 return 0;
393}
394
395static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
396 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 396, __PRETTY_FUNCTION__); } while (0)
;
397
398 if (BUS_MESSAGE_IS_GVARIANT(m))
399 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
400 else {
401 /* 64bit cookies are not supported on dbus1 */
402 if (cookie > 0xffffffffUL)
403 return -EOPNOTSUPP95;
404
405 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
406 }
407}
408
409int bus_message_from_header(
410 sd_bus *bus,
411 void *header,
412 size_t header_accessible,
413 void *footer,
414 size_t footer_accessible,
415 size_t message_size,
416 int *fds,
417 size_t n_fds,
418 const char *label,
419 size_t extra,
420 sd_bus_message **ret) {
421
422 _cleanup_free___attribute__((cleanup(freep))) sd_bus_message *m = NULL((void*)0);
423 struct bus_header *h;
424 size_t a, label_sz;
425
426 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-message.c"
, 426, __PRETTY_FUNCTION__); } while (0)
;
2
Assuming 'bus' is non-null
3
Taking false branch
4
Loop condition is false. Exiting loop
427 assert(header || header_accessible <= 0)do { if ((__builtin_expect(!!(!(header || header_accessible <=
0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("header || header_accessible <= 0"
), "../src/libsystemd/sd-bus/bus-message.c", 427, __PRETTY_FUNCTION__
); } while (0)
;
5
Assuming 'header' is non-null
6
Taking false branch
7
Loop condition is false. Exiting loop
428 assert(footer || footer_accessible <= 0)do { if ((__builtin_expect(!!(!(footer || footer_accessible <=
0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("footer || footer_accessible <= 0"
), "../src/libsystemd/sd-bus/bus-message.c", 428, __PRETTY_FUNCTION__
); } while (0)
;
8
Taking false branch
9
Loop condition is false. Exiting loop
429 assert(fds || n_fds <= 0)do { if ((__builtin_expect(!!(!(fds || n_fds <= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("fds || n_fds <= 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 429, __PRETTY_FUNCTION__); } while (0)
;
10
Assuming 'fds' is non-null
11
Taking false branch
12
Loop condition is false. Exiting loop
430 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/libsystemd/sd-bus/bus-message.c"
, 430, __PRETTY_FUNCTION__); } while (0)
;
13
Taking false branch
14
Loop condition is false. Exiting loop
431
432 if (header_accessible < sizeof(struct bus_header))
15
Assuming the condition is false
16
Taking false branch
433 return -EBADMSG74;
434
435 if (header_accessible
16.1
'header_accessible' is <= 'message_size'
> message_size)
17
Taking false branch
436 return -EBADMSG74;
437 if (footer_accessible
17.1
'footer_accessible' is <= 'message_size'
> message_size)
18
Taking false branch
438 return -EBADMSG74;
439
440 h = header;
441 if (!IN_SET(h->version, 1, 2)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){1, 2})/sizeof(int)]; switch(h->version
) { case 1: case 2: _found = 1; break; default: break; } _found
; })
)
19
Control jumps to 'case 2:' at line 441
20
Execution continues on line 441
21
Taking false branch
442 return -EBADMSG74;
443
444 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
22
Assuming field 'type' is not equal to _SD_BUS_MESSAGE_TYPE_INVALID
23
Taking false branch
445 return -EBADMSG74;
446
447 if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN})/sizeof
(int)]; switch(h->endian) { case BUS_LITTLE_ENDIAN: case BUS_BIG_ENDIAN
: _found = 1; break; default: break; } _found; })
)
24
Control jumps to 'case BUS_BIG_ENDIAN:' at line 447
25
Execution continues on line 447
26
Taking false branch
448 return -EBADMSG74;
449
450 /* Note that we are happy with unknown flags in the flags header! */
451
452 a = ALIGN(sizeof(sd_bus_message))(((sizeof(sd_bus_message)) + 7) & ~7) + ALIGN(extra)(((extra) + 7) & ~7);
453
454 if (label) {
27
Assuming 'label' is null
28
Taking false branch
455 label_sz = strlen(label);
456 a += label_sz + 1;
457 }
458
459 m = malloc0(a)(calloc(1, (a)));
29
Memory is allocated
460 if (!m)
30
Assuming 'm' is non-null
31
Taking false branch
461 return -ENOMEM12;
462
463 m->sealed = true1;
464 m->header = header;
465 m->header_accessible = header_accessible;
466 m->footer = footer;
467 m->footer_accessible = footer_accessible;
468
469 if (BUS_MESSAGE_IS_GVARIANT(m)) {
32
Taking true branch
470 size_t ws;
471
472 if (h->dbus2.cookie == 0)
33
Assuming field 'cookie' is equal to 0
34
Taking true branch
473 return -EBADMSG74;
35
Potential leak of memory pointed to by 'm'
474
475 /* dbus2 derives the sizes from the message size and
476 the offset table at the end, since it is formatted as
477 gvariant "yyyyuta{tv}v". Since the message itself is a
478 structure with precisely to variable sized entries,
479 there's only one offset in the table, which marks the
480 end of the fields array. */
481
482 ws = bus_gvariant_determine_word_size(message_size, 0);
483 if (footer_accessible < ws)
484 return -EBADMSG74;
485
486 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
487 if (ALIGN8(m->fields_size)(((m->fields_size) + 7) & ~7) > message_size - ws)
488 return -EBADMSG74;
489 if (m->fields_size < sizeof(struct bus_header))
490 return -EBADMSG74;
491
492 m->fields_size -= sizeof(struct bus_header);
493 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size)(((m->fields_size) + 7) & ~7));
494 } else {
495 if (h->dbus1.serial == 0)
496 return -EBADMSG74;
497
498 /* dbus1 has the sizes in the header */
499 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
500 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
501
502 if (sizeof(struct bus_header) + ALIGN8(m->fields_size)(((m->fields_size) + 7) & ~7) + m->body_size != message_size)
503 return -EBADMSG74;
504 }
505
506 m->fds = fds;
507 m->n_fds = n_fds;
508
509 if (label) {
510 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message))(((sizeof(sd_bus_message)) + 7) & ~7) + ALIGN(extra)(((extra) + 7) & ~7);
511 memcpy(m->creds.label, label, label_sz + 1);
512
513 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
514 }
515
516 m->n_ref = 1;
517 m->bus = sd_bus_ref(bus);
518
519 *ret = TAKE_PTR(m)({ typeof(m) _ptr_ = (m); (m) = ((void*)0); _ptr_; });
520
521 return 0;
522}
523
524int bus_message_from_malloc(
525 sd_bus *bus,
526 void *buffer,
527 size_t length,
528 int *fds,
529 size_t n_fds,
530 const char *label,
531 sd_bus_message **ret) {
532
533 _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *m = NULL((void*)0);
534 size_t sz;
535 int r;
536
537 r = bus_message_from_header(
1
Calling 'bus_message_from_header'
538 bus,
539 buffer, length, /* in this case the initial bytes and the final bytes are the same */
540 buffer, length,
541 length,
542 fds, n_fds,
543 label,
544 0, &m);
545 if (r < 0)
546 return r;
547
548 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size)(((m->fields_size) + 7) & ~7);
549 if (sz > 0) {
550 m->n_body_parts = 1;
551 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size)(((m->fields_size) + 7) & ~7);
552 m->body.size = sz;
553 m->body.sealed = true1;
554 m->body.memfd = -1;
555 }
556
557 m->n_iovec = 1;
558 m->iovec = m->iovec_fixed;
559 m->iovec[0].iov_base = buffer;
560 m->iovec[0].iov_len = length;
561
562 r = bus_message_parse_fields(m);
563 if (r < 0)
564 return r;
565
566 /* We take possession of the memory and fds now */
567 m->free_header = true1;
568 m->free_fds = true1;
569
570 *ret = TAKE_PTR(m)({ typeof(m) _ptr_ = (m); (m) = ((void*)0); _ptr_; });
571 return 0;
572}
573
574_public___attribute__ ((visibility("default"))) int sd_bus_message_new(
575 sd_bus *bus,
576 sd_bus_message **m,
577 uint8_t type) {
578
579 sd_bus_message *t;
580
581 assert_return(bus, -ENOTCONN)do { if (!(((__builtin_expect(!!(bus),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-message.c"
, 581, __PRETTY_FUNCTION__), 0))) return (-107); } while (0)
;
582 assert_return(bus->state != BUS_UNSET, -ENOTCONN)do { if (!(((__builtin_expect(!!(bus->state != BUS_UNSET),
1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("bus->state != BUS_UNSET"), "../src/libsystemd/sd-bus/bus-message.c"
, 582, __PRETTY_FUNCTION__), 0))) return (-107); } while (0)
;
583 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 583, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
584 assert_return(type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL)do { if (!(((__builtin_expect(!!(type < _SD_BUS_MESSAGE_TYPE_MAX
),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("type < _SD_BUS_MESSAGE_TYPE_MAX"), "../src/libsystemd/sd-bus/bus-message.c"
, 584, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
585
586 t = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header))(calloc(1, ((((sizeof(sd_bus_message)) + 7) & ~7) + sizeof
(struct bus_header))))
;
587 if (!t)
588 return -ENOMEM12;
589
590 t->n_ref = 1;
591 t->bus = sd_bus_ref(bus);
592 t->header = (struct bus_header*) ((uint8_t*) t + ALIGN(sizeof(struct sd_bus_message))(((sizeof(struct sd_bus_message)) + 7) & ~7));
593 t->header->endian = BUS_NATIVE_ENDIAN;
594 t->header->type = type;
595 t->header->version = bus->message_version;
596 t->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){BUS_HELLO, BUS_RUNNING})/sizeof(int)]; switch
(bus->state) { case BUS_HELLO: case BUS_RUNNING: _found = 1
; break; default: break; } _found; })
;
597 t->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(t);
598
599 if (bus->allow_interactive_authorization)
600 t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
601
602 *m = t;
603 return 0;
604}
605
606_public___attribute__ ((visibility("default"))) int sd_bus_message_new_signal(
607 sd_bus *bus,
608 sd_bus_message **m,
609 const char *path,
610 const char *interface,
611 const char *member) {
612
613 _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *t = NULL((void*)0);
614 int r;
615
616 assert_return(bus, -ENOTCONN)do { if (!(((__builtin_expect(!!(bus),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-message.c"
, 616, __PRETTY_FUNCTION__), 0))) return (-107); } while (0)
;
617 assert_return(bus->state != BUS_UNSET, -ENOTCONN)do { if (!(((__builtin_expect(!!(bus->state != BUS_UNSET),
1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("bus->state != BUS_UNSET"), "../src/libsystemd/sd-bus/bus-message.c"
, 617, __PRETTY_FUNCTION__), 0))) return (-107); } while (0)
;
618 assert_return(object_path_is_valid(path), -EINVAL)do { if (!(((__builtin_expect(!!(object_path_is_valid(path)),
1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("object_path_is_valid(path)"), "../src/libsystemd/sd-bus/bus-message.c"
, 618, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
619 assert_return(interface_name_is_valid(interface), -EINVAL)do { if (!(((__builtin_expect(!!(interface_name_is_valid(interface
)),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("interface_name_is_valid(interface)"), "../src/libsystemd/sd-bus/bus-message.c"
, 619, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
620 assert_return(member_name_is_valid(member), -EINVAL)do { if (!(((__builtin_expect(!!(member_name_is_valid(member)
),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("member_name_is_valid(member)"), "../src/libsystemd/sd-bus/bus-message.c"
, 620, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
621 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 621, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
622
623 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_SIGNAL);
624 if (r < 0)
625 return -ENOMEM12;
626
627 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/libsystemd/sd-bus/bus-message.c"
, 627, __PRETTY_FUNCTION__); } while (0)
;
628
629 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
630
631 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
632 if (r < 0)
633 return r;
634 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
635 if (r < 0)
636 return r;
637 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
638 if (r < 0)
639 return r;
640
641 *m = TAKE_PTR(t)({ typeof(t) _ptr_ = (t); (t) = ((void*)0); _ptr_; });
642 return 0;
643}
644
645_public___attribute__ ((visibility("default"))) int sd_bus_message_new_method_call(
646 sd_bus *bus,
647 sd_bus_message **m,
648 const char *destination,
649 const char *path,
650 const char *interface,
651 const char *member) {
652
653 _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *t = NULL((void*)0);
654 int r;
655
656 assert_return(bus, -ENOTCONN)do { if (!(((__builtin_expect(!!(bus),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-message.c"
, 656, __PRETTY_FUNCTION__), 0))) return (-107); } while (0)
;
657 assert_return(bus->state != BUS_UNSET, -ENOTCONN)do { if (!(((__builtin_expect(!!(bus->state != BUS_UNSET),
1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("bus->state != BUS_UNSET"), "../src/libsystemd/sd-bus/bus-message.c"
, 657, __PRETTY_FUNCTION__), 0))) return (-107); } while (0)
;
658 assert_return(!destination || service_name_is_valid(destination), -EINVAL)do { if (!(((__builtin_expect(!!(!destination || service_name_is_valid
(destination)),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("!destination || service_name_is_valid(destination)"), "../src/libsystemd/sd-bus/bus-message.c"
, 658, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
659 assert_return(object_path_is_valid(path), -EINVAL)do { if (!(((__builtin_expect(!!(object_path_is_valid(path)),
1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("object_path_is_valid(path)"), "../src/libsystemd/sd-bus/bus-message.c"
, 659, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
660 assert_return(!interface || interface_name_is_valid(interface), -EINVAL)do { if (!(((__builtin_expect(!!(!interface || interface_name_is_valid
(interface)),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("!interface || interface_name_is_valid(interface)"), "../src/libsystemd/sd-bus/bus-message.c"
, 660, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
661 assert_return(member_name_is_valid(member), -EINVAL)do { if (!(((__builtin_expect(!!(member_name_is_valid(member)
),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("member_name_is_valid(member)"), "../src/libsystemd/sd-bus/bus-message.c"
, 661, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
662 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 662, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
663
664 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_CALL);
665 if (r < 0)
666 return -ENOMEM12;
667
668 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/libsystemd/sd-bus/bus-message.c"
, 668, __PRETTY_FUNCTION__); } while (0)
;
669
670 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
671 if (r < 0)
672 return r;
673 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
674 if (r < 0)
675 return r;
676
677 if (interface) {
678 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
679 if (r < 0)
680 return r;
681 }
682
683 if (destination) {
684 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
685 if (r < 0)
686 return r;
687 }
688
689 *m = TAKE_PTR(t)({ typeof(t) _ptr_ = (t); (t) = ((void*)0); _ptr_; });
690 return 0;
691}
692
693static int message_new_reply(
694 sd_bus_message *call,
695 uint8_t type,
696 sd_bus_message **m) {
697
698 _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *t = NULL((void*)0);
699 uint64_t cookie;
700 int r;
701
702 assert_return(call, -EINVAL)do { if (!(((__builtin_expect(!!(call),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("call"), "../src/libsystemd/sd-bus/bus-message.c"
, 702, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
703 assert_return(call->sealed, -EPERM)do { if (!(((__builtin_expect(!!(call->sealed),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("call->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 703, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
704 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL)do { if (!(((__builtin_expect(!!(call->header->type == SD_BUS_MESSAGE_METHOD_CALL
),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("call->header->type == SD_BUS_MESSAGE_METHOD_CALL"),
"../src/libsystemd/sd-bus/bus-message.c", 704, __PRETTY_FUNCTION__
), 0))) return (-22); } while (0)
;
705 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN)do { if (!(((__builtin_expect(!!(call->bus->state != BUS_UNSET
),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("call->bus->state != BUS_UNSET"), "../src/libsystemd/sd-bus/bus-message.c"
, 705, __PRETTY_FUNCTION__), 0))) return (-107); } while (0)
;
706 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 706, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
707
708 cookie = BUS_MESSAGE_COOKIE(call);
709 if (cookie == 0)
710 return -EOPNOTSUPP95;
711
712 r = sd_bus_message_new(call->bus, &t, type);
713 if (r < 0)
714 return -ENOMEM12;
715
716 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/libsystemd/sd-bus/bus-message.c"
, 716, __PRETTY_FUNCTION__); } while (0)
;
717
718 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
719 t->reply_cookie = cookie;
720 r = message_append_reply_cookie(t, t->reply_cookie);
721 if (r < 0)
722 return r;
723
724 if (call->sender) {
725 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
726 if (r < 0)
727 return r;
728 }
729
730 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
731 t->enforced_reply_signature = call->enforced_reply_signature;
732
733 *m = TAKE_PTR(t)({ typeof(t) _ptr_ = (t); (t) = ((void*)0); _ptr_; });
734 return 0;
735}
736
737_public___attribute__ ((visibility("default"))) int sd_bus_message_new_method_return(
738 sd_bus_message *call,
739 sd_bus_message **m) {
740
741 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
742}
743
744_public___attribute__ ((visibility("default"))) int sd_bus_message_new_method_error(
745 sd_bus_message *call,
746 sd_bus_message **m,
747 const sd_bus_error *e) {
748
749 _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *t = NULL((void*)0);
750 int r;
751
752 assert_return(sd_bus_error_is_set(e), -EINVAL)do { if (!(((__builtin_expect(!!(sd_bus_error_is_set(e)),1)))
? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"sd_bus_error_is_set(e)"), "../src/libsystemd/sd-bus/bus-message.c"
, 752, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
753 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 753, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
754
755 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
756 if (r < 0)
757 return r;
758
759 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
760 if (r < 0)
761 return r;
762
763 if (e->message) {
764 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
765 if (r < 0)
766 return r;
767 }
768
769 t->error._need_free = -1;
770
771 *m = TAKE_PTR(t)({ typeof(t) _ptr_ = (t); (t) = ((void*)0); _ptr_; });
772 return 0;
773}
774
775_public___attribute__ ((visibility("default"))) int sd_bus_message_new_method_errorf(
776 sd_bus_message *call,
777 sd_bus_message **m,
778 const char *name,
779 const char *format,
780 ...) {
781
782 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
783 va_list ap;
784
785 assert_return(name, -EINVAL)do { if (!(((__builtin_expect(!!(name),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("name"), "../src/libsystemd/sd-bus/bus-message.c"
, 785, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
786 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 786, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
787
788 va_start(ap, format)__builtin_va_start(ap, format);
789 bus_error_setfv(&error, name, format, ap);
790 va_end(ap)__builtin_va_end(ap);
791
792 return sd_bus_message_new_method_error(call, m, &error);
793}
794
795_public___attribute__ ((visibility("default"))) int sd_bus_message_new_method_errno(
796 sd_bus_message *call,
797 sd_bus_message **m,
798 int error,
799 const sd_bus_error *p) {
800
801 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error berror = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
802
803 if (sd_bus_error_is_set(p))
804 return sd_bus_message_new_method_error(call, m, p);
805
806 sd_bus_error_set_errno(&berror, error);
807
808 return sd_bus_message_new_method_error(call, m, &berror);
809}
810
811_public___attribute__ ((visibility("default"))) int sd_bus_message_new_method_errnof(
812 sd_bus_message *call,
813 sd_bus_message **m,
814 int error,
815 const char *format,
816 ...) {
817
818 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error berror = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
819 va_list ap;
820
821 va_start(ap, format)__builtin_va_start(ap, format);
822 sd_bus_error_set_errnofv(&berror, error, format, ap);
823 va_end(ap)__builtin_va_end(ap);
824
825 return sd_bus_message_new_method_error(call, m, &berror);
826}
827
828void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
829 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-message.c"
, 829, __PRETTY_FUNCTION__); } while (0)
;
830 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 830, __PRETTY_FUNCTION__); } while (0)
;
831
832 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
833 m->creds.well_known_names_local = true1;
834 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
835}
836
837void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
838 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-message.c"
, 838, __PRETTY_FUNCTION__); } while (0)
;
839 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 839, __PRETTY_FUNCTION__); } while (0)
;
840
841 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
842 m->creds.well_known_names_driver = true1;
843 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
844}
845
846int bus_message_new_synthetic_error(
847 sd_bus *bus,
848 uint64_t cookie,
849 const sd_bus_error *e,
850 sd_bus_message **m) {
851
852 _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *t = NULL((void*)0);
853 int r;
854
855 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-message.c"
, 855, __PRETTY_FUNCTION__); } while (0)
;
856 assert(sd_bus_error_is_set(e))do { if ((__builtin_expect(!!(!(sd_bus_error_is_set(e))),0)))
log_assert_failed_realm(LOG_REALM_SYSTEMD, ("sd_bus_error_is_set(e)"
), "../src/libsystemd/sd-bus/bus-message.c", 856, __PRETTY_FUNCTION__
); } while (0)
;
857 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 857, __PRETTY_FUNCTION__); } while (0)
;
858
859 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_ERROR);
860 if (r < 0)
861 return -ENOMEM12;
862
863 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/libsystemd/sd-bus/bus-message.c"
, 863, __PRETTY_FUNCTION__); } while (0)
;
864
865 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
866 t->reply_cookie = cookie;
867
868 r = message_append_reply_cookie(t, t->reply_cookie);
869 if (r < 0)
870 return r;
871
872 if (bus && bus->unique_name) {
873 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
874 if (r < 0)
875 return r;
876 }
877
878 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
879 if (r < 0)
880 return r;
881
882 if (e->message) {
883 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
884 if (r < 0)
885 return r;
886 }
887
888 t->error._need_free = -1;
889
890 bus_message_set_sender_driver(bus, t);
891
892 *m = TAKE_PTR(t)({ typeof(t) _ptr_ = (t); (t) = ((void*)0); _ptr_; });
893 return 0;
894}
895
896_public___attribute__ ((visibility("default"))) sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
897 if (!m)
898 return NULL((void*)0);
899
900 /* We are fine if this message so far was either explicitly reffed or not reffed but queued into at
901 * least one bus connection object. */
902 assert(m->n_ref > 0 || m->n_queued > 0)do { if ((__builtin_expect(!!(!(m->n_ref > 0 || m->n_queued
> 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("m->n_ref > 0 || m->n_queued > 0"
), "../src/libsystemd/sd-bus/bus-message.c", 902, __PRETTY_FUNCTION__
); } while (0)
;
903
904 m->n_ref++;
905
906 /* Each user reference to a bus message shall also be considered a ref on the bus */
907 sd_bus_ref(m->bus);
908 return m;
909}
910
911_public___attribute__ ((visibility("default"))) sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
912 if (!m)
913 return NULL((void*)0);
914
915 assert(m->n_ref > 0)do { if ((__builtin_expect(!!(!(m->n_ref > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m->n_ref > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 915, __PRETTY_FUNCTION__); } while (0)
;
916
917 sd_bus_unref(m->bus); /* Each regular ref is also a ref on the bus connection. Let's hence drop it
918 * here. Note we have to do this before decrementing our own n_ref here, since
919 * otherwise, if this message is currently queued sd_bus_unref() might call
920 * bus_message_unref_queued() for this which might then destroy the message
921 * while we are still processing it. */
922 m->n_ref--;
923
924 if (m->n_ref > 0 || m->n_queued > 0)
925 return NULL((void*)0);
926
927 /* Unset the bus field if neither the user has a reference nor this message is queued. We are careful
928 * to reset the field only after the last reference to the bus is dropped, after all we might keep
929 * multiple references to the bus, once for each reference kept on outselves. */
930 m->bus = NULL((void*)0);
931
932 return message_free(m);
933}
934
935sd_bus_message* bus_message_ref_queued(sd_bus_message *m, sd_bus *bus) {
936 if (!m)
937 return NULL((void*)0);
938
939 /* If this is a different bus than the message is associated with, then implicitly turn this into a
940 * regular reference. This means that you can create a memory leak by enqueuing a message generated
941 * on one bus onto another at the same time as enqueueing a message from the second one on the first,
942 * as we'll not detect the cyclic references there. */
943 if (bus != m->bus)
944 return sd_bus_message_ref(m);
945
946 assert(m->n_ref > 0 || m->n_queued > 0)do { if ((__builtin_expect(!!(!(m->n_ref > 0 || m->n_queued
> 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("m->n_ref > 0 || m->n_queued > 0"
), "../src/libsystemd/sd-bus/bus-message.c", 946, __PRETTY_FUNCTION__
); } while (0)
;
947 m->n_queued++;
948
949 return m;
950}
951
952sd_bus_message* bus_message_unref_queued(sd_bus_message *m, sd_bus *bus) {
953 if (!m)
954 return NULL((void*)0);
955
956 if (bus != m->bus)
957 return sd_bus_message_unref(m);
958
959 assert(m->n_queued > 0)do { if ((__builtin_expect(!!(!(m->n_queued > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m->n_queued > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 959, __PRETTY_FUNCTION__); } while (0)
;
960 m->n_queued--;
961
962 if (m->n_ref > 0 || m->n_queued > 0)
963 return NULL((void*)0);
964
965 m->bus = NULL((void*)0);
966
967 return message_free(m);
968}
969
970_public___attribute__ ((visibility("default"))) int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
971 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 971, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
972 assert_return(type, -EINVAL)do { if (!(((__builtin_expect(!!(type),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("type"), "../src/libsystemd/sd-bus/bus-message.c"
, 972, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
973
974 *type = m->header->type;
975 return 0;
976}
977
978_public___attribute__ ((visibility("default"))) int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
979 uint64_t c;
980
981 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 981, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
982 assert_return(cookie, -EINVAL)do { if (!(((__builtin_expect(!!(cookie),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("cookie"), "../src/libsystemd/sd-bus/bus-message.c"
, 982, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
983
984 c = BUS_MESSAGE_COOKIE(m);
985 if (c == 0)
986 return -ENODATA61;
987
988 *cookie = BUS_MESSAGE_COOKIE(m);
989 return 0;
990}
991
992_public___attribute__ ((visibility("default"))) int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
993 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 993, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
994 assert_return(cookie, -EINVAL)do { if (!(((__builtin_expect(!!(cookie),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("cookie"), "../src/libsystemd/sd-bus/bus-message.c"
, 994, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
995
996 if (m->reply_cookie == 0)
997 return -ENODATA61;
998
999 *cookie = m->reply_cookie;
1000 return 0;
1001}
1002
1003_public___attribute__ ((visibility("default"))) int sd_bus_message_get_expect_reply(sd_bus_message *m) {
1004 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1004, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1005
1006 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
1007 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
1008}
1009
1010_public___attribute__ ((visibility("default"))) int sd_bus_message_get_auto_start(sd_bus_message *m) {
1011 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1011, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1012
1013 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
1014}
1015
1016_public___attribute__ ((visibility("default"))) int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
1017 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1017, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1018
1019 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
1020 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
1021}
1022
1023_public___attribute__ ((visibility("default"))) const char *sd_bus_message_get_path(sd_bus_message *m) {
1024 assert_return(m, NULL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1024, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
1025
1026 return m->path;
1027}
1028
1029_public___attribute__ ((visibility("default"))) const char *sd_bus_message_get_interface(sd_bus_message *m) {
1030 assert_return(m, NULL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1030, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
1031
1032 return m->interface;
1033}
1034
1035_public___attribute__ ((visibility("default"))) const char *sd_bus_message_get_member(sd_bus_message *m) {
1036 assert_return(m, NULL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1036, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
1037
1038 return m->member;
1039}
1040
1041_public___attribute__ ((visibility("default"))) const char *sd_bus_message_get_destination(sd_bus_message *m) {
1042 assert_return(m, NULL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1042, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
1043
1044 return m->destination;
1045}
1046
1047_public___attribute__ ((visibility("default"))) const char *sd_bus_message_get_sender(sd_bus_message *m) {
1048 assert_return(m, NULL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1048, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
1049
1050 return m->sender;
1051}
1052
1053_public___attribute__ ((visibility("default"))) const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1054 assert_return(m, NULL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1054, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
1055
1056 if (!sd_bus_error_is_set(&m->error))
1057 return NULL((void*)0);
1058
1059 return &m->error;
1060}
1061
1062_public___attribute__ ((visibility("default"))) int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1063 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1063, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1064 assert_return(usec, -EINVAL)do { if (!(((__builtin_expect(!!(usec),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("usec"), "../src/libsystemd/sd-bus/bus-message.c"
, 1064, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1065
1066 if (m->monotonic <= 0)
1067 return -ENODATA61;
1068
1069 *usec = m->monotonic;
1070 return 0;
1071}
1072
1073_public___attribute__ ((visibility("default"))) int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1074 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1074, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1075 assert_return(usec, -EINVAL)do { if (!(((__builtin_expect(!!(usec),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("usec"), "../src/libsystemd/sd-bus/bus-message.c"
, 1075, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1076
1077 if (m->realtime <= 0)
1078 return -ENODATA61;
1079
1080 *usec = m->realtime;
1081 return 0;
1082}
1083
1084_public___attribute__ ((visibility("default"))) int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1085 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1085, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1086 assert_return(seqnum, -EINVAL)do { if (!(((__builtin_expect(!!(seqnum),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("seqnum"), "../src/libsystemd/sd-bus/bus-message.c"
, 1086, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1087
1088 if (m->seqnum <= 0)
1089 return -ENODATA61;
1090
1091 *seqnum = m->seqnum;
1092 return 0;
1093}
1094
1095_public___attribute__ ((visibility("default"))) sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1096 assert_return(m, NULL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1096, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
1097
1098 if (m->creds.mask == 0)
1099 return NULL((void*)0);
1100
1101 return &m->creds;
1102}
1103
1104_public___attribute__ ((visibility("default"))) int sd_bus_message_is_signal(
1105 sd_bus_message *m,
1106 const char *interface,
1107 const char *member) {
1108
1109 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1109, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1110
1111 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1112 return 0;
1113
1114 if (interface && !streq_ptr(m->interface, interface))
1115 return 0;
1116
1117 if (member && !streq_ptr(m->member, member))
1118 return 0;
1119
1120 return 1;
1121}
1122
1123_public___attribute__ ((visibility("default"))) int sd_bus_message_is_method_call(
1124 sd_bus_message *m,
1125 const char *interface,
1126 const char *member) {
1127
1128 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1128, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1129
1130 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1131 return 0;
1132
1133 if (interface && !streq_ptr(m->interface, interface))
1134 return 0;
1135
1136 if (member && !streq_ptr(m->member, member))
1137 return 0;
1138
1139 return 1;
1140}
1141
1142_public___attribute__ ((visibility("default"))) int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1143 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1143, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1144
1145 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1146 return 0;
1147
1148 if (name && !streq_ptr(m->error.name, name))
1149 return 0;
1150
1151 return 1;
1152}
1153
1154_public___attribute__ ((visibility("default"))) int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1155 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1155, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1156 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 1156, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
1157 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM)do { if (!(((__builtin_expect(!!(m->header->type == SD_BUS_MESSAGE_METHOD_CALL
),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("m->header->type == SD_BUS_MESSAGE_METHOD_CALL"), "../src/libsystemd/sd-bus/bus-message.c"
, 1157, __PRETTY_FUNCTION__), 0))) return (-1); } while (0)
;
1158
1159 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b)(m->header->flags) = (!b) ? ((m->header->flags) |
(BUS_MESSAGE_NO_REPLY_EXPECTED)) : ((m->header->flags)
& ~(BUS_MESSAGE_NO_REPLY_EXPECTED))
;
1160
1161 return 0;
1162}
1163
1164_public___attribute__ ((visibility("default"))) int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1165 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1165, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1166 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 1166, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
1167
1168 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b)(m->header->flags) = (!b) ? ((m->header->flags) |
(BUS_MESSAGE_NO_AUTO_START)) : ((m->header->flags) &
~(BUS_MESSAGE_NO_AUTO_START))
;
1169
1170 return 0;
1171}
1172
1173_public___attribute__ ((visibility("default"))) int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1174 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1174, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1175 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 1175, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
1176
1177 SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b)(m->header->flags) = (b) ? ((m->header->flags) | (
BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION)) : ((m->header
->flags) & ~(BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
))
;
1178
1179 return 0;
1180}
1181
1182struct bus_body_part *message_append_part(sd_bus_message *m) {
1183 struct bus_body_part *part;
1184
1185 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1185, __PRETTY_FUNCTION__); } while (0)
;
1186
1187 if (m->poisoned)
1188 return NULL((void*)0);
1189
1190 if (m->n_body_parts <= 0) {
1191 part = &m->body;
1192 zero(*part)(({ size_t _l_ = (sizeof(*part)); void *_x_ = (&(*part));
_l_ == 0 ? _x_ : memset(_x_, 0, _l_); }))
;
1193 } else {
1194 assert(m->body_end)do { if ((__builtin_expect(!!(!(m->body_end)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m->body_end"), "../src/libsystemd/sd-bus/bus-message.c"
, 1194, __PRETTY_FUNCTION__); } while (0)
;
1195
1196 part = new0(struct bus_body_part, 1)((struct bus_body_part*) calloc((1), sizeof(struct bus_body_part
)))
;
1197 if (!part) {
1198 m->poisoned = true1;
1199 return NULL((void*)0);
1200 }
1201
1202 m->body_end->next = part;
1203 }
1204
1205 part->memfd = -1;
1206 m->body_end = part;
1207 m->n_body_parts++;
1208
1209 return part;
1210}
1211
1212static void part_zero(struct bus_body_part *part, size_t sz) {
1213 assert(part)do { if ((__builtin_expect(!!(!(part)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("part"), "../src/libsystemd/sd-bus/bus-message.c"
, 1213, __PRETTY_FUNCTION__); } while (0)
;
1214 assert(sz > 0)do { if ((__builtin_expect(!!(!(sz > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("sz > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 1214, __PRETTY_FUNCTION__); } while (0)
;
1215 assert(sz < 8)do { if ((__builtin_expect(!!(!(sz < 8)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("sz < 8"), "../src/libsystemd/sd-bus/bus-message.c"
, 1215, __PRETTY_FUNCTION__); } while (0)
;
1216
1217 /* All other fields can be left in their defaults */
1218 assert(!part->data)do { if ((__builtin_expect(!!(!(!part->data)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("!part->data"), "../src/libsystemd/sd-bus/bus-message.c"
, 1218, __PRETTY_FUNCTION__); } while (0)
;
1219 assert(part->memfd < 0)do { if ((__builtin_expect(!!(!(part->memfd < 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("part->memfd < 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 1219, __PRETTY_FUNCTION__); } while (0)
;
1220
1221 part->size = sz;
1222 part->is_zero = true1;
1223 part->sealed = true1;
1224}
1225
1226static int part_make_space(
1227 struct sd_bus_message *m,
1228 struct bus_body_part *part,
1229 size_t sz,
1230 void **q) {
1231
1232 void *n;
1233
1234 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1234, __PRETTY_FUNCTION__); } while (0)
;
1235 assert(part)do { if ((__builtin_expect(!!(!(part)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("part"), "../src/libsystemd/sd-bus/bus-message.c"
, 1235, __PRETTY_FUNCTION__); } while (0)
;
1236 assert(!part->sealed)do { if ((__builtin_expect(!!(!(!part->sealed)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("!part->sealed"), "../src/libsystemd/sd-bus/bus-message.c"
, 1236, __PRETTY_FUNCTION__); } while (0)
;
1237
1238 if (m->poisoned)
1239 return -ENOMEM12;
1240
1241 if (part->allocated == 0 || sz > part->allocated) {
1242 size_t new_allocated;
1243
1244 new_allocated = sz > 0 ? 2 * sz : 64;
1245 n = realloc(part->data, new_allocated);
1246 if (!n) {
1247 m->poisoned = true1;
1248 return -ENOMEM12;
1249 }
1250
1251 part->data = n;
1252 part->allocated = new_allocated;
1253 part->free_this = true1;
1254 }
1255
1256 if (q)
1257 *q = part->data ? (uint8_t*) part->data + part->size : NULL((void*)0);
1258
1259 part->size = sz;
1260 return 0;
1261}
1262
1263static int message_add_offset(sd_bus_message *m, size_t offset) {
1264 struct bus_container *c;
1265
1266 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1266, __PRETTY_FUNCTION__); } while (0)
;
1267 assert(BUS_MESSAGE_IS_GVARIANT(m))do { if ((__builtin_expect(!!(!(BUS_MESSAGE_IS_GVARIANT(m))),
0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("BUS_MESSAGE_IS_GVARIANT(m)"
), "../src/libsystemd/sd-bus/bus-message.c", 1267, __PRETTY_FUNCTION__
); } while (0)
;
1268
1269 /* Add offset to current container, unless this is the first
1270 * item in it, which will have the 0 offset, which we can
1271 * ignore. */
1272 c = message_get_last_container(m);
1273
1274 if (!c->need_offsets)
1275 return 0;
1276
1277 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1)greedy_realloc((void**) &(c->offsets), &(c->offsets_allocated
), (c->n_offsets + 1), sizeof((c->offsets)[0]))
)
1278 return -ENOMEM12;
1279
1280 c->offsets[c->n_offsets++] = offset;
1281 return 0;
1282}
1283
1284static void message_extend_containers(sd_bus_message *m, size_t expand) {
1285 struct bus_container *c;
1286
1287 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1287, __PRETTY_FUNCTION__); } while (0)
;
1288
1289 if (expand <= 0)
1290 return;
1291
1292 /* Update counters */
1293 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1294
1295 if (c->array_size)
1296 *c->array_size += expand;
1297 }
1298}
1299
1300static void *message_extend_body(
1301 sd_bus_message *m,
1302 size_t align,
1303 size_t sz,
1304 bool_Bool add_offset,
1305 bool_Bool force_inline) {
1306
1307 size_t start_body, end_body, padding, added;
1308 void *p;
1309 int r;
1310
1311 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1311, __PRETTY_FUNCTION__); } while (0)
;
1312 assert(align > 0)do { if ((__builtin_expect(!!(!(align > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("align > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 1312, __PRETTY_FUNCTION__); } while (0)
;
1313 assert(!m->sealed)do { if ((__builtin_expect(!!(!(!m->sealed)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("!m->sealed"), "../src/libsystemd/sd-bus/bus-message.c"
, 1313, __PRETTY_FUNCTION__); } while (0)
;
1314
1315 if (m->poisoned)
1316 return NULL((void*)0);
1317
1318 start_body = ALIGN_TO((size_t) m->body_size, align);
1319 end_body = start_body + sz;
1320
1321 padding = start_body - m->body_size;
1322 added = padding + sz;
1323
1324 /* Check for 32bit overflows */
1325 if (end_body > (size_t) ((uint32_t) -1) ||
1326 end_body < start_body) {
1327 m->poisoned = true1;
1328 return NULL((void*)0);
1329 }
1330
1331 if (added > 0) {
1332 struct bus_body_part *part = NULL((void*)0);
1333 bool_Bool add_new_part;
1334
1335 add_new_part =
1336 m->n_body_parts <= 0 ||
1337 m->body_end->sealed ||
1338 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1339 (force_inline && m->body_end->size > MEMFD_MIN_SIZE(512*1024));
1340 /* If this must be an inlined extension, let's create a new part if
1341 * the previous part is large enough to be inlined. */
1342
1343 if (add_new_part) {
1344 if (padding > 0) {
1345 part = message_append_part(m);
1346 if (!part)
1347 return NULL((void*)0);
1348
1349 part_zero(part, padding);
1350 }
1351
1352 part = message_append_part(m);
1353 if (!part)
1354 return NULL((void*)0);
1355
1356 r = part_make_space(m, part, sz, &p);
1357 if (r < 0)
1358 return NULL((void*)0);
1359 } else {
1360 struct bus_container *c;
1361 void *op;
1362 size_t os, start_part, end_part;
1363
1364 part = m->body_end;
1365 op = part->data;
1366 os = part->size;
1367
1368 start_part = ALIGN_TO(part->size, align);
1369 end_part = start_part + sz;
1370
1371 r = part_make_space(m, part, end_part, &p);
1372 if (r < 0)
1373 return NULL((void*)0);
1374
1375 if (padding > 0) {
1376 memzero(p, padding)({ size_t _l_ = (padding); void *_x_ = (p); _l_ == 0 ? _x_ : memset
(_x_, 0, _l_); })
;
1377 p = (uint8_t*) p + padding;
1378 }
1379
1380 /* Readjust pointers */
1381 for (c = m->containers; c < m->containers + m->n_containers; c++)
1382 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1383
1384 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1385 }
1386 } else
1387 /* Return something that is not NULL and is aligned */
1388 p = (uint8_t*) align;
1389
1390 m->body_size = end_body;
1391 message_extend_containers(m, added);
1392
1393 if (add_offset) {
1394 r = message_add_offset(m, end_body);
1395 if (r < 0) {
1396 m->poisoned = true1;
1397 return NULL((void*)0);
1398 }
1399 }
1400
1401 return p;
1402}
1403
1404static int message_push_fd(sd_bus_message *m, int fd) {
1405 int *f, copy;
1406
1407 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1407, __PRETTY_FUNCTION__); } while (0)
;
1408
1409 if (fd < 0)
1410 return -EINVAL22;
1411
1412 if (!m->allow_fds)
1413 return -EOPNOTSUPP95;
1414
1415 copy = fcntl(fd, F_DUPFD_CLOEXEC1030, 3);
1416 if (copy < 0)
1417 return -errno(*__errno_location ());
1418
1419 f = reallocarray(m->fds, sizeof(int), m->n_fds + 1);
1420 if (!f) {
1421 m->poisoned = true1;
1422 safe_close(copy);
1423 return -ENOMEM12;
1424 }
1425
1426 m->fds = f;
1427 m->fds[m->n_fds] = copy;
1428 m->free_fds = true1;
1429
1430 return copy;
1431}
1432
1433int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1434 _cleanup_close___attribute__((cleanup(closep))) int fd = -1;
1435 struct bus_container *c;
1436 ssize_t align, sz;
1437 void *a;
1438
1439 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1439, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1440 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 1440, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
1441 assert_return(bus_type_is_basic(type), -EINVAL)do { if (!(((__builtin_expect(!!(bus_type_is_basic(type)),1))
) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"bus_type_is_basic(type)"), "../src/libsystemd/sd-bus/bus-message.c"
, 1441, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1442 assert_return(!m->poisoned, -ESTALE)do { if (!(((__builtin_expect(!!(!m->poisoned),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->poisoned"
), "../src/libsystemd/sd-bus/bus-message.c", 1442, __PRETTY_FUNCTION__
), 0))) return (-116); } while (0)
;
1443
1444 c = message_get_last_container(m);
1445
1446 if (c->signature && c->signature[c->index]) {
1447 /* Container signature is already set */
1448
1449 if (c->signature[c->index] != type)
1450 return -ENXIO6;
1451 } else {
1452 char *e;
1453
1454 /* Maybe we can append to the signature? But only if this is the top-level container */
1455 if (c->enclosing != 0)
1456 return -ENXIO6;
1457
1458 e = strextend(&c->signature, CHAR_TO_STR(type), NULL)strextend_with_separator(&c->signature, ((void*)0), ((
char[2]) { type, 0 }), ((void*)0))
;
1459 if (!e) {
1460 m->poisoned = true1;
1461 return -ENOMEM12;
1462 }
1463 }
1464
1465 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1466 uint8_t u8;
1467 uint32_t u32;
1468
1469 switch (type) {
1470
1471 case SD_BUS_TYPE_SIGNATURE:
1472 case SD_BUS_TYPE_STRING:
1473 p = strempty(p);
1474
1475 _fallthrough_;
1476 case SD_BUS_TYPE_OBJECT_PATH:
1477 if (!p)
1478 return -EINVAL22;
1479
1480 align = 1;
1481 sz = strlen(p) + 1;
1482 break;
1483
1484 case SD_BUS_TYPE_BOOLEAN:
1485
1486 u8 = p && *(int*) p;
1487 p = &u8;
1488
1489 align = sz = 1;
1490 break;
1491
1492 case SD_BUS_TYPE_UNIX_FD:
1493
1494 if (!p)
1495 return -EINVAL22;
1496
1497 fd = message_push_fd(m, *(int*) p);
1498 if (fd < 0)
1499 return fd;
1500
1501 u32 = m->n_fds;
1502 p = &u32;
1503
1504 align = sz = 4;
1505 break;
1506
1507 default:
1508 align = bus_gvariant_get_alignment(CHAR_TO_STR(type)((char[2]) { type, 0 }));
1509 sz = bus_gvariant_get_size(CHAR_TO_STR(type)((char[2]) { type, 0 }));
1510 break;
1511 }
1512
1513 assert(align > 0)do { if ((__builtin_expect(!!(!(align > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("align > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 1513, __PRETTY_FUNCTION__); } while (0)
;
1514 assert(sz > 0)do { if ((__builtin_expect(!!(!(sz > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("sz > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 1514, __PRETTY_FUNCTION__); } while (0)
;
1515
1516 a = message_extend_body(m, align, sz, true1, false0);
1517 if (!a)
1518 return -ENOMEM12;
1519
1520 memcpy(a, p, sz);
1521
1522 if (stored)
1523 *stored = (const uint8_t*) a;
1524
1525 } else {
1526 uint32_t u32;
1527
1528 switch (type) {
1529
1530 case SD_BUS_TYPE_STRING:
1531 /* To make things easy we'll serialize a NULL string
1532 * into the empty string */
1533 p = strempty(p);
1534
1535 _fallthrough_;
1536 case SD_BUS_TYPE_OBJECT_PATH:
1537
1538 if (!p)
1539 return -EINVAL22;
1540
1541 align = 4;
1542 sz = 4 + strlen(p) + 1;
1543 break;
1544
1545 case SD_BUS_TYPE_SIGNATURE:
1546
1547 p = strempty(p);
1548
1549 align = 1;
1550 sz = 1 + strlen(p) + 1;
1551 break;
1552
1553 case SD_BUS_TYPE_BOOLEAN:
1554
1555 u32 = p && *(int*) p;
1556 p = &u32;
1557
1558 align = sz = 4;
1559 break;
1560
1561 case SD_BUS_TYPE_UNIX_FD:
1562
1563 if (!p)
1564 return -EINVAL22;
1565
1566 fd = message_push_fd(m, *(int*) p);
1567 if (fd < 0)
1568 return fd;
1569
1570 u32 = m->n_fds;
1571 p = &u32;
1572
1573 align = sz = 4;
1574 break;
1575
1576 default:
1577 align = bus_type_get_alignment(type);
1578 sz = bus_type_get_size(type);
1579 break;
1580 }
1581
1582 assert(align > 0)do { if ((__builtin_expect(!!(!(align > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("align > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 1582, __PRETTY_FUNCTION__); } while (0)
;
1583 assert(sz > 0)do { if ((__builtin_expect(!!(!(sz > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("sz > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 1583, __PRETTY_FUNCTION__); } while (0)
;
1584
1585 a = message_extend_body(m, align, sz, false0, false0);
1586 if (!a)
1587 return -ENOMEM12;
1588
1589 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH
})/sizeof(int)]; switch(type) { case SD_BUS_TYPE_STRING: case
SD_BUS_TYPE_OBJECT_PATH: _found = 1; break; default: break; }
_found; })
) {
1590 *(uint32_t*) a = sz - 5;
1591 memcpy((uint8_t*) a + 4, p, sz - 4);
1592
1593 if (stored)
1594 *stored = (const uint8_t*) a + 4;
1595
1596 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1597 *(uint8_t*) a = sz - 2;
1598 memcpy((uint8_t*) a + 1, p, sz - 1);
1599
1600 if (stored)
1601 *stored = (const uint8_t*) a + 1;
1602 } else {
1603 memcpy(a, p, sz);
1604
1605 if (stored)
1606 *stored = a;
1607 }
1608 }
1609
1610 if (type == SD_BUS_TYPE_UNIX_FD)
1611 m->n_fds++;
1612
1613 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1614 c->index++;
1615
1616 fd = -1;
1617 return 0;
1618}
1619
1620_public___attribute__ ((visibility("default"))) int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1621 return message_append_basic(m, type, p, NULL((void*)0));
1622}
1623
1624_public___attribute__ ((visibility("default"))) int sd_bus_message_append_string_space(
1625 sd_bus_message *m,
1626 size_t size,
1627 char **s) {
1628
1629 struct bus_container *c;
1630 void *a;
1631
1632 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1632, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1633 assert_return(s, -EINVAL)do { if (!(((__builtin_expect(!!(s),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/libsystemd/sd-bus/bus-message.c"
, 1633, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1634 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 1634, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
1635 assert_return(!m->poisoned, -ESTALE)do { if (!(((__builtin_expect(!!(!m->poisoned),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->poisoned"
), "../src/libsystemd/sd-bus/bus-message.c", 1635, __PRETTY_FUNCTION__
), 0))) return (-116); } while (0)
;
1636
1637 c = message_get_last_container(m);
1638
1639 if (c->signature && c->signature[c->index]) {
1640 /* Container signature is already set */
1641
1642 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1643 return -ENXIO6;
1644 } else {
1645 char *e;
1646
1647 /* Maybe we can append to the signature? But only if this is the top-level container */
1648 if (c->enclosing != 0)
1649 return -ENXIO6;
1650
1651 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL)strextend_with_separator(&c->signature, ((void*)0), ((
char[2]) { SD_BUS_TYPE_STRING, 0 }), ((void*)0))
;
1652 if (!e) {
1653 m->poisoned = true1;
1654 return -ENOMEM12;
1655 }
1656 }
1657
1658 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1659 a = message_extend_body(m, 1, size + 1, true1, false0);
1660 if (!a)
1661 return -ENOMEM12;
1662
1663 *s = a;
1664 } else {
1665 a = message_extend_body(m, 4, 4 + size + 1, false0, false0);
1666 if (!a)
1667 return -ENOMEM12;
1668
1669 *(uint32_t*) a = size;
1670 *s = (char*) a + 4;
1671 }
1672
1673 (*s)[size] = 0;
1674
1675 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1676 c->index++;
1677
1678 return 0;
1679}
1680
1681_public___attribute__ ((visibility("default"))) int sd_bus_message_append_string_iovec(
1682 sd_bus_message *m,
1683 const struct iovec *iov,
1684 unsigned n /* should be size_t, but is API now… 😞 */) {
1685
1686 size_t size;
1687 unsigned i;
1688 char *p;
1689 int r;
1690
1691 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1691, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1692 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 1692, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
1693 assert_return(iov || n == 0, -EINVAL)do { if (!(((__builtin_expect(!!(iov || n == 0),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("iov || n == 0"
), "../src/libsystemd/sd-bus/bus-message.c", 1693, __PRETTY_FUNCTION__
), 0))) return (-22); } while (0)
;
1694 assert_return(!m->poisoned, -ESTALE)do { if (!(((__builtin_expect(!!(!m->poisoned),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->poisoned"
), "../src/libsystemd/sd-bus/bus-message.c", 1694, __PRETTY_FUNCTION__
), 0))) return (-116); } while (0)
;
1695
1696 size = IOVEC_TOTAL_SIZE(iov, n);
1697
1698 r = sd_bus_message_append_string_space(m, size, &p);
1699 if (r < 0)
1700 return r;
1701
1702 for (i = 0; i < n; i++) {
1703
1704 if (iov[i].iov_base)
1705 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1706 else
1707 memset(p, ' ', iov[i].iov_len);
1708
1709 p += iov[i].iov_len;
1710 }
1711
1712 return 0;
1713}
1714
1715static int bus_message_open_array(
1716 sd_bus_message *m,
1717 struct bus_container *c,
1718 const char *contents,
1719 uint32_t **array_size,
1720 size_t *begin,
1721 bool_Bool *need_offsets) {
1722
1723 unsigned nindex;
1724 int alignment, r;
1725
1726 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1726, __PRETTY_FUNCTION__); } while (0)
;
1727 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-message.c"
, 1727, __PRETTY_FUNCTION__); } while (0)
;
1728 assert(contents)do { if ((__builtin_expect(!!(!(contents)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("contents"), "../src/libsystemd/sd-bus/bus-message.c"
, 1728, __PRETTY_FUNCTION__); } while (0)
;
1729 assert(array_size)do { if ((__builtin_expect(!!(!(array_size)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("array_size"), "../src/libsystemd/sd-bus/bus-message.c"
, 1729, __PRETTY_FUNCTION__); } while (0)
;
1730 assert(begin)do { if ((__builtin_expect(!!(!(begin)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("begin"), "../src/libsystemd/sd-bus/bus-message.c"
, 1730, __PRETTY_FUNCTION__); } while (0)
;
1731 assert(need_offsets)do { if ((__builtin_expect(!!(!(need_offsets)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("need_offsets"), "../src/libsystemd/sd-bus/bus-message.c"
, 1731, __PRETTY_FUNCTION__); } while (0)
;
1732
1733 if (!signature_is_single(contents, true1))
1734 return -EINVAL22;
1735
1736 if (c->signature && c->signature[c->index]) {
1737
1738 /* Verify the existing signature */
1739
1740 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1741 return -ENXIO6;
1742
1743 if (!startswith(c->signature + c->index + 1, contents))
1744 return -ENXIO6;
1745
1746 nindex = c->index + 1 + strlen(contents);
1747 } else {
1748 char *e;
1749
1750 if (c->enclosing != 0)
1751 return -ENXIO6;
1752
1753 /* Extend the existing signature */
1754
1755 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL)strextend_with_separator(&c->signature, ((void*)0), ((
char[2]) { SD_BUS_TYPE_ARRAY, 0 }), contents, ((void*)0))
;
1756 if (!e) {
1757 m->poisoned = true1;
1758 return -ENOMEM12;
1759 }
1760
1761 nindex = e - c->signature;
1762 }
1763
1764 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1765 alignment = bus_gvariant_get_alignment(contents);
1766 if (alignment < 0)
1767 return alignment;
1768
1769 /* Add alignment padding and add to offset list */
1770 if (!message_extend_body(m, alignment, 0, false0, false0))
1771 return -ENOMEM12;
1772
1773 r = bus_gvariant_is_fixed_size(contents);
1774 if (r < 0)
1775 return r;
1776
1777 *begin = m->body_size;
1778 *need_offsets = r == 0;
1779 } else {
1780 void *a, *op;
1781 size_t os;
1782 struct bus_body_part *o;
1783
1784 alignment = bus_type_get_alignment(contents[0]);
1785 if (alignment < 0)
1786 return alignment;
1787
1788 a = message_extend_body(m, 4, 4, false0, false0);
1789 if (!a)
1790 return -ENOMEM12;
1791
1792 o = m->body_end;
1793 op = m->body_end->data;
1794 os = m->body_end->size;
1795
1796 /* Add alignment between size and first element */
1797 if (!message_extend_body(m, alignment, 0, false0, false0))
1798 return -ENOMEM12;
1799
1800 /* location of array size might have changed so let's readjust a */
1801 if (o == m->body_end)
1802 a = adjust_pointer(a, op, os, m->body_end->data);
1803
1804 *(uint32_t*) a = 0;
1805 *array_size = a;
1806 }
1807
1808 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1809 c->index = nindex;
1810
1811 return 0;
1812}
1813
1814static int bus_message_open_variant(
1815 sd_bus_message *m,
1816 struct bus_container *c,
1817 const char *contents) {
1818
1819 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1819, __PRETTY_FUNCTION__); } while (0)
;
1820 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-message.c"
, 1820, __PRETTY_FUNCTION__); } while (0)
;
1821 assert(contents)do { if ((__builtin_expect(!!(!(contents)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("contents"), "../src/libsystemd/sd-bus/bus-message.c"
, 1821, __PRETTY_FUNCTION__); } while (0)
;
1822
1823 if (!signature_is_single(contents, false0))
1824 return -EINVAL22;
1825
1826 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1827 return -EINVAL22;
1828
1829 if (c->signature && c->signature[c->index]) {
1830
1831 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1832 return -ENXIO6;
1833
1834 } else {
1835 char *e;
1836
1837 if (c->enclosing != 0)
1838 return -ENXIO6;
1839
1840 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL)strextend_with_separator(&c->signature, ((void*)0), ((
char[2]) { SD_BUS_TYPE_VARIANT, 0 }), ((void*)0))
;
1841 if (!e) {
1842 m->poisoned = true1;
1843 return -ENOMEM12;
1844 }
1845 }
1846
1847 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1848 /* Variants are always aligned to 8 */
1849
1850 if (!message_extend_body(m, 8, 0, false0, false0))
1851 return -ENOMEM12;
1852
1853 } else {
1854 size_t l;
1855 void *a;
1856
1857 l = strlen(contents);
1858 a = message_extend_body(m, 1, 1 + l + 1, false0, false0);
1859 if (!a)
1860 return -ENOMEM12;
1861
1862 *(uint8_t*) a = l;
1863 memcpy((uint8_t*) a + 1, contents, l + 1);
1864 }
1865
1866 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1867 c->index++;
1868
1869 return 0;
1870}
1871
1872static int bus_message_open_struct(
1873 sd_bus_message *m,
1874 struct bus_container *c,
1875 const char *contents,
1876 size_t *begin,
1877 bool_Bool *need_offsets) {
1878
1879 size_t nindex;
1880 int r;
1881
1882 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1882, __PRETTY_FUNCTION__); } while (0)
;
1883 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-message.c"
, 1883, __PRETTY_FUNCTION__); } while (0)
;
1884 assert(contents)do { if ((__builtin_expect(!!(!(contents)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("contents"), "../src/libsystemd/sd-bus/bus-message.c"
, 1884, __PRETTY_FUNCTION__); } while (0)
;
1885 assert(begin)do { if ((__builtin_expect(!!(!(begin)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("begin"), "../src/libsystemd/sd-bus/bus-message.c"
, 1885, __PRETTY_FUNCTION__); } while (0)
;
1886 assert(need_offsets)do { if ((__builtin_expect(!!(!(need_offsets)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("need_offsets"), "../src/libsystemd/sd-bus/bus-message.c"
, 1886, __PRETTY_FUNCTION__); } while (0)
;
1887
1888 if (!signature_is_valid(contents, false0))
1889 return -EINVAL22;
1890
1891 if (c->signature && c->signature[c->index]) {
1892 size_t l;
1893
1894 l = strlen(contents);
1895
1896 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1897 !startswith(c->signature + c->index + 1, contents) ||
1898 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1899 return -ENXIO6;
1900
1901 nindex = c->index + 1 + l + 1;
1902 } else {
1903 char *e;
1904
1905 if (c->enclosing != 0)
1906 return -ENXIO6;
1907
1908 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL)strextend_with_separator(&c->signature, ((void*)0), ((
char[2]) { SD_BUS_TYPE_STRUCT_BEGIN, 0 }), contents, ((char[2
]) { SD_BUS_TYPE_STRUCT_END, 0 }), ((void*)0))
;
1909 if (!e) {
1910 m->poisoned = true1;
1911 return -ENOMEM12;
1912 }
1913
1914 nindex = e - c->signature;
1915 }
1916
1917 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1918 int alignment;
1919
1920 alignment = bus_gvariant_get_alignment(contents);
1921 if (alignment < 0)
1922 return alignment;
1923
1924 if (!message_extend_body(m, alignment, 0, false0, false0))
1925 return -ENOMEM12;
1926
1927 r = bus_gvariant_is_fixed_size(contents);
1928 if (r < 0)
1929 return r;
1930
1931 *begin = m->body_size;
1932 *need_offsets = r == 0;
1933 } else {
1934 /* Align contents to 8 byte boundary */
1935 if (!message_extend_body(m, 8, 0, false0, false0))
1936 return -ENOMEM12;
1937 }
1938
1939 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1940 c->index = nindex;
1941
1942 return 0;
1943}
1944
1945static int bus_message_open_dict_entry(
1946 sd_bus_message *m,
1947 struct bus_container *c,
1948 const char *contents,
1949 size_t *begin,
1950 bool_Bool *need_offsets) {
1951
1952 int r;
1953
1954 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 1954, __PRETTY_FUNCTION__); } while (0)
;
1955 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-message.c"
, 1955, __PRETTY_FUNCTION__); } while (0)
;
1956 assert(contents)do { if ((__builtin_expect(!!(!(contents)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("contents"), "../src/libsystemd/sd-bus/bus-message.c"
, 1956, __PRETTY_FUNCTION__); } while (0)
;
1957 assert(begin)do { if ((__builtin_expect(!!(!(begin)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("begin"), "../src/libsystemd/sd-bus/bus-message.c"
, 1957, __PRETTY_FUNCTION__); } while (0)
;
1958 assert(need_offsets)do { if ((__builtin_expect(!!(!(need_offsets)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("need_offsets"), "../src/libsystemd/sd-bus/bus-message.c"
, 1958, __PRETTY_FUNCTION__); } while (0)
;
1959
1960 if (!signature_is_pair(contents))
1961 return -EINVAL22;
1962
1963 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1964 return -ENXIO6;
1965
1966 if (c->signature && c->signature[c->index]) {
1967 size_t l;
1968
1969 l = strlen(contents);
1970
1971 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1972 !startswith(c->signature + c->index + 1, contents) ||
1973 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1974 return -ENXIO6;
1975 } else
1976 return -ENXIO6;
1977
1978 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1979 int alignment;
1980
1981 alignment = bus_gvariant_get_alignment(contents);
1982 if (alignment < 0)
1983 return alignment;
1984
1985 if (!message_extend_body(m, alignment, 0, false0, false0))
1986 return -ENOMEM12;
1987
1988 r = bus_gvariant_is_fixed_size(contents);
1989 if (r < 0)
1990 return r;
1991
1992 *begin = m->body_size;
1993 *need_offsets = r == 0;
1994 } else {
1995 /* Align contents to 8 byte boundary */
1996 if (!message_extend_body(m, 8, 0, false0, false0))
1997 return -ENOMEM12;
1998 }
1999
2000 return 0;
2001}
2002
2003_public___attribute__ ((visibility("default"))) int sd_bus_message_open_container(
2004 sd_bus_message *m,
2005 char type,
2006 const char *contents) {
2007
2008 struct bus_container *c;
2009 uint32_t *array_size = NULL((void*)0);
2010 _cleanup_free___attribute__((cleanup(freep))) char *signature = NULL((void*)0);
2011 size_t before, begin = 0;
2012 bool_Bool need_offsets = false0;
2013 int r;
2014
2015 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 2015, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2016 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 2016, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
2017 assert_return(contents, -EINVAL)do { if (!(((__builtin_expect(!!(contents),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("contents"), "../src/libsystemd/sd-bus/bus-message.c"
, 2017, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2018 assert_return(!m->poisoned, -ESTALE)do { if (!(((__builtin_expect(!!(!m->poisoned),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->poisoned"
), "../src/libsystemd/sd-bus/bus-message.c", 2018, __PRETTY_FUNCTION__
), 0))) return (-116); } while (0)
;
2019
2020 /* Make sure we have space for one more container */
2021 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)greedy_realloc((void**) &(m->containers), &(m->
containers_allocated), (m->n_containers + 1), sizeof((m->
containers)[0]))
) {
2022 m->poisoned = true1;
2023 return -ENOMEM12;
2024 }
2025
2026 c = message_get_last_container(m);
2027
2028 signature = strdup(contents);
2029 if (!signature) {
2030 m->poisoned = true1;
2031 return -ENOMEM12;
2032 }
2033
2034 /* Save old index in the parent container, in case we have to
2035 * abort this container */
2036 c->saved_index = c->index;
2037 before = m->body_size;
2038
2039 if (type == SD_BUS_TYPE_ARRAY)
2040 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2041 else if (type == SD_BUS_TYPE_VARIANT)
2042 r = bus_message_open_variant(m, c, contents);
2043 else if (type == SD_BUS_TYPE_STRUCT)
2044 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2045 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2046 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2047 else
2048 r = -EINVAL22;
2049 if (r < 0)
2050 return r;
2051
2052 /* OK, let's fill it in */
2053 m->containers[m->n_containers++] = (struct bus_container) {
2054 .enclosing = type,
2055 .signature = TAKE_PTR(signature)({ typeof(signature) _ptr_ = (signature); (signature) = ((void
*)0); _ptr_; })
,
2056 .array_size = array_size,
2057 .before = before,
2058 .begin = begin,
2059 .need_offsets = need_offsets,
2060 };
2061
2062 return 0;
2063}
2064
2065static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2066
2067 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 2067, __PRETTY_FUNCTION__); } while (0)
;
2068 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-message.c"
, 2068, __PRETTY_FUNCTION__); } while (0)
;
2069
2070 if (!BUS_MESSAGE_IS_GVARIANT(m))
2071 return 0;
2072
2073 if (c->need_offsets) {
2074 size_t payload, sz, i;
2075 uint8_t *a;
2076
2077 /* Variable-width arrays */
2078
2079 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2080 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2081
2082 a = message_extend_body(m, 1, sz * c->n_offsets, true1, false0);
2083 if (!a)
2084 return -ENOMEM12;
2085
2086 for (i = 0; i < c->n_offsets; i++)
2087 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2088 } else {
2089 void *a;
2090
2091 /* Fixed-width or empty arrays */
2092
2093 a = message_extend_body(m, 1, 0, true1, false0); /* let's add offset to parent */
2094 if (!a)
2095 return -ENOMEM12;
2096 }
2097
2098 return 0;
2099}
2100
2101static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2102 uint8_t *a;
2103 size_t l;
2104
2105 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 2105, __PRETTY_FUNCTION__); } while (0)
;
2106 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-message.c"
, 2106, __PRETTY_FUNCTION__); } while (0)
;
2107 assert(c->signature)do { if ((__builtin_expect(!!(!(c->signature)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c->signature"), "../src/libsystemd/sd-bus/bus-message.c"
, 2107, __PRETTY_FUNCTION__); } while (0)
;
2108
2109 if (!BUS_MESSAGE_IS_GVARIANT(m))
2110 return 0;
2111
2112 l = strlen(c->signature);
2113
2114 a = message_extend_body(m, 1, 1 + l, true1, false0);
2115 if (!a)
2116 return -ENOMEM12;
2117
2118 a[0] = 0;
2119 memcpy(a+1, c->signature, l);
2120
2121 return 0;
2122}
2123
2124static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool_Bool add_offset) {
2125 bool_Bool fixed_size = true1;
2126 size_t n_variable = 0;
2127 unsigned i = 0;
2128 const char *p;
2129 uint8_t *a;
2130 int r;
2131
2132 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 2132, __PRETTY_FUNCTION__); } while (0)
;
2133 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-message.c"
, 2133, __PRETTY_FUNCTION__); } while (0)
;
2134
2135 if (!BUS_MESSAGE_IS_GVARIANT(m))
2136 return 0;
2137
2138 p = strempty(c->signature);
2139 while (*p != 0) {
2140 size_t n;
2141
2142 r = signature_element_length(p, &n);
2143 if (r < 0)
2144 return r;
2145 else {
2146 char t[n+1];
2147
2148 memcpy(t, p, n);
2149 t[n] = 0;
2150
2151 r = bus_gvariant_is_fixed_size(t);
2152 if (r < 0)
2153 return r;
2154 }
2155
2156 assert(!c->need_offsets || i <= c->n_offsets)do { if ((__builtin_expect(!!(!(!c->need_offsets || i <=
c->n_offsets)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("!c->need_offsets || i <= c->n_offsets"), "../src/libsystemd/sd-bus/bus-message.c"
, 2156, __PRETTY_FUNCTION__); } while (0)
;
2157
2158 /* We need to add an offset for each item that has a
2159 * variable size and that is not the last one in the
2160 * list */
2161 if (r == 0)
2162 fixed_size = false0;
2163 if (r == 0 && p[n] != 0)
2164 n_variable++;
2165
2166 i++;
2167 p += n;
2168 }
2169
2170 assert(!c->need_offsets || i == c->n_offsets)do { if ((__builtin_expect(!!(!(!c->need_offsets || i == c
->n_offsets)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("!c->need_offsets || i == c->n_offsets"), "../src/libsystemd/sd-bus/bus-message.c"
, 2170, __PRETTY_FUNCTION__); } while (0)
;
2171 assert(c->need_offsets || n_variable == 0)do { if ((__builtin_expect(!!(!(c->need_offsets || n_variable
== 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("c->need_offsets || n_variable == 0"
), "../src/libsystemd/sd-bus/bus-message.c", 2171, __PRETTY_FUNCTION__
); } while (0)
;
2172
2173 if (isempty(c->signature)) {
2174 /* The unary type is encoded as fixed 1 byte padding */
2175 a = message_extend_body(m, 1, 1, add_offset, false0);
2176 if (!a)
2177 return -ENOMEM12;
2178
2179 *a = 0;
2180 } else if (n_variable <= 0) {
2181 int alignment = 1;
2182
2183 /* Structures with fixed-size members only have to be
2184 * fixed-size themselves. But gvariant requires all fixed-size
2185 * elements to be sized a multiple of their alignment. Hence,
2186 * we must *always* add final padding after the last member so
2187 * the overall size of the structure is properly aligned. */
2188 if (fixed_size)
2189 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2190
2191 assert(alignment > 0)do { if ((__builtin_expect(!!(!(alignment > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("alignment > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 2191, __PRETTY_FUNCTION__); } while (0)
;
2192
2193 a = message_extend_body(m, alignment, 0, add_offset, false0);
2194 if (!a)
2195 return -ENOMEM12;
2196 } else {
2197 size_t sz;
2198 unsigned j;
2199
2200 assert(c->offsets[c->n_offsets-1] == m->body_size)do { if ((__builtin_expect(!!(!(c->offsets[c->n_offsets
-1] == m->body_size)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("c->offsets[c->n_offsets-1] == m->body_size"), "../src/libsystemd/sd-bus/bus-message.c"
, 2200, __PRETTY_FUNCTION__); } while (0)
;
2201
2202 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2203
2204 a = message_extend_body(m, 1, sz * n_variable, add_offset, false0);
2205 if (!a)
2206 return -ENOMEM12;
2207
2208 p = strempty(c->signature);
2209 for (i = 0, j = 0; i < c->n_offsets; i++) {
2210 unsigned k;
2211 size_t n;
2212
2213 r = signature_element_length(p, &n);
2214 if (r < 0)
2215 return r;
2216 else {
2217 char t[n+1];
2218
2219 memcpy(t, p, n);
2220 t[n] = 0;
2221
2222 p += n;
2223
2224 r = bus_gvariant_is_fixed_size(t);
2225 if (r < 0)
2226 return r;
2227 if (r > 0 || p[0] == 0)
2228 continue;
2229 }
2230
2231 k = n_variable - 1 - j;
2232
2233 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2234
2235 j++;
2236 }
2237 }
2238
2239 return 0;
2240}
2241
2242_public___attribute__ ((visibility("default"))) int sd_bus_message_close_container(sd_bus_message *m) {
2243 struct bus_container *c;
2244 int r;
2245
2246 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 2246, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2247 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 2247, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
2248 assert_return(m->n_containers > 0, -EINVAL)do { if (!(((__builtin_expect(!!(m->n_containers > 0),1
))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("m->n_containers > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 2248, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2249 assert_return(!m->poisoned, -ESTALE)do { if (!(((__builtin_expect(!!(!m->poisoned),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->poisoned"
), "../src/libsystemd/sd-bus/bus-message.c", 2249, __PRETTY_FUNCTION__
), 0))) return (-116); } while (0)
;
2250
2251 c = message_get_last_container(m);
2252
2253 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2254 if (c->signature && c->signature[c->index] != 0)
2255 return -EINVAL22;
2256
2257 m->n_containers--;
2258
2259 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2260 r = bus_message_close_array(m, c);
2261 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2262 r = bus_message_close_variant(m, c);
2263 else if (IN_SET(c->enclosing, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY
})/sizeof(int)]; switch(c->enclosing) { case SD_BUS_TYPE_STRUCT
: case SD_BUS_TYPE_DICT_ENTRY: _found = 1; break; default: break
; } _found; })
)
2264 r = bus_message_close_struct(m, c, true1);
2265 else
2266 assert_not_reached("Unknown container type")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, (
"Unknown container type"), "../src/libsystemd/sd-bus/bus-message.c"
, 2266, __PRETTY_FUNCTION__); } while (0)
;
2267
2268 free(c->signature);
2269 free(c->offsets);
2270
2271 return r;
2272}
2273
2274typedef struct {
2275 const char *types;
2276 unsigned n_struct;
2277 unsigned n_array;
2278} TypeStack;
2279
2280static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2281 assert(stack)do { if ((__builtin_expect(!!(!(stack)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("stack"), "../src/libsystemd/sd-bus/bus-message.c"
, 2281, __PRETTY_FUNCTION__); } while (0)
;
2282 assert(max > 0)do { if ((__builtin_expect(!!(!(max > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("max > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 2282, __PRETTY_FUNCTION__); } while (0)
;
2283
2284 if (*i >= max)
2285 return -EINVAL22;
2286
2287 stack[*i].types = types;
2288 stack[*i].n_struct = n_struct;
2289 stack[*i].n_array = n_array;
2290 (*i)++;
2291
2292 return 0;
2293}
2294
2295static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2296 assert(stack)do { if ((__builtin_expect(!!(!(stack)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("stack"), "../src/libsystemd/sd-bus/bus-message.c"
, 2296, __PRETTY_FUNCTION__); } while (0)
;
2297 assert(max > 0)do { if ((__builtin_expect(!!(!(max > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("max > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 2297, __PRETTY_FUNCTION__); } while (0)
;
2298 assert(types)do { if ((__builtin_expect(!!(!(types)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("types"), "../src/libsystemd/sd-bus/bus-message.c"
, 2298, __PRETTY_FUNCTION__); } while (0)
;
2299 assert(n_struct)do { if ((__builtin_expect(!!(!(n_struct)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n_struct"), "../src/libsystemd/sd-bus/bus-message.c"
, 2299, __PRETTY_FUNCTION__); } while (0)
;
2300 assert(n_array)do { if ((__builtin_expect(!!(!(n_array)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n_array"), "../src/libsystemd/sd-bus/bus-message.c"
, 2300, __PRETTY_FUNCTION__); } while (0)
;
2301
2302 if (*i <= 0)
2303 return 0;
2304
2305 (*i)--;
2306 *types = stack[*i].types;
2307 *n_struct = stack[*i].n_struct;
2308 *n_array = stack[*i].n_array;
2309
2310 return 1;
2311}
2312
2313_public___attribute__ ((visibility("default"))) int sd_bus_message_appendv(
2314 sd_bus_message *m,
2315 const char *types,
2316 va_list ap) {
2317
2318 unsigned n_array, n_struct;
2319 TypeStack stack[BUS_CONTAINER_DEPTH128];
2320 unsigned stack_ptr = 0;
2321 int r;
2322
2323 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 2323, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2324 assert_return(types, -EINVAL)do { if (!(((__builtin_expect(!!(types),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("types"), "../src/libsystemd/sd-bus/bus-message.c"
, 2324, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2325 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 2325, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
2326 assert_return(!m->poisoned, -ESTALE)do { if (!(((__builtin_expect(!!(!m->poisoned),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->poisoned"
), "../src/libsystemd/sd-bus/bus-message.c", 2326, __PRETTY_FUNCTION__
), 0))) return (-116); } while (0)
;
2327
2328 n_array = (unsigned) -1;
2329 n_struct = strlen(types);
2330
2331 for (;;) {
2332 const char *t;
2333
2334 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2335 r = type_stack_pop(stack, ELEMENTSOF(stack)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(stack), typeof(&*(stack))), sizeof(stack)/sizeof(
(stack)[0]), ((void)0)))
, &stack_ptr, &types, &n_struct, &n_array);
2336 if (r < 0)
2337 return r;
2338 if (r == 0)
2339 break;
2340
2341 r = sd_bus_message_close_container(m);
2342 if (r < 0)
2343 return r;
2344
2345 continue;
2346 }
2347
2348 t = types;
2349 if (n_array != (unsigned) -1)
2350 n_array--;
2351 else {
2352 types++;
2353 n_struct--;
2354 }
2355
2356 switch (*t) {
2357
2358 case SD_BUS_TYPE_BYTE: {
2359 uint8_t x;
2360
2361 x = (uint8_t) va_arg(ap, int)__builtin_va_arg(ap, int);
2362 r = sd_bus_message_append_basic(m, *t, &x);
2363 break;
2364 }
2365
2366 case SD_BUS_TYPE_BOOLEAN:
2367 case SD_BUS_TYPE_INT32:
2368 case SD_BUS_TYPE_UINT32:
2369 case SD_BUS_TYPE_UNIX_FD: {
2370 uint32_t x;
2371
2372 /* We assume a boolean is the same as int32_t */
2373 assert_cc(sizeof(int32_t) == sizeof(int))GCC diagnostic push ; GCC diagnostic ignored "-Wdeclaration-after-statement"
; struct _assert_struct_11 { char x[(sizeof(int32_t) == sizeof
(int)) ? 0 : -1]; }; GCC diagnostic pop
;
2374
2375 x = va_arg(ap, uint32_t)__builtin_va_arg(ap, uint32_t);
2376 r = sd_bus_message_append_basic(m, *t, &x);
2377 break;
2378 }
2379
2380 case SD_BUS_TYPE_INT16:
2381 case SD_BUS_TYPE_UINT16: {
2382 uint16_t x;
2383
2384 x = (uint16_t) va_arg(ap, int)__builtin_va_arg(ap, int);
2385 r = sd_bus_message_append_basic(m, *t, &x);
2386 break;
2387 }
2388
2389 case SD_BUS_TYPE_INT64:
2390 case SD_BUS_TYPE_UINT64: {
2391 uint64_t x;
2392
2393 x = va_arg(ap, uint64_t)__builtin_va_arg(ap, uint64_t);
2394 r = sd_bus_message_append_basic(m, *t, &x);
2395 break;
2396 }
2397
2398 case SD_BUS_TYPE_DOUBLE: {
2399 double x;
2400
2401 x = va_arg(ap, double)__builtin_va_arg(ap, double);
2402 r = sd_bus_message_append_basic(m, *t, &x);
2403 break;
2404 }
2405
2406 case SD_BUS_TYPE_STRING:
2407 case SD_BUS_TYPE_OBJECT_PATH:
2408 case SD_BUS_TYPE_SIGNATURE: {
2409 const char *x;
2410
2411 x = va_arg(ap, const char*)__builtin_va_arg(ap, const char*);
2412 r = sd_bus_message_append_basic(m, *t, x);
2413 break;
2414 }
2415
2416 case SD_BUS_TYPE_ARRAY: {
2417 size_t k;
2418
2419 r = signature_element_length(t + 1, &k);
2420 if (r < 0)
2421 return r;
2422
2423 {
2424 char s[k + 1];
2425 memcpy(s, t + 1, k);
2426 s[k] = 0;
2427
2428 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2429 if (r < 0)
2430 return r;
2431 }
2432
2433 if (n_array == (unsigned) -1) {
2434 types += k;
2435 n_struct -= k;
2436 }
2437
2438 r = type_stack_push(stack, ELEMENTSOF(stack)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(stack), typeof(&*(stack))), sizeof(stack)/sizeof(
(stack)[0]), ((void)0)))
, &stack_ptr, types, n_struct, n_array);
2439 if (r < 0)
2440 return r;
2441
2442 types = t + 1;
2443 n_struct = k;
2444 n_array = va_arg(ap, unsigned)__builtin_va_arg(ap, unsigned);
2445
2446 break;
2447 }
2448
2449 case SD_BUS_TYPE_VARIANT: {
2450 const char *s;
2451
2452 s = va_arg(ap, const char*)__builtin_va_arg(ap, const char*);
2453 if (!s)
2454 return -EINVAL22;
2455
2456 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2457 if (r < 0)
2458 return r;
2459
2460 r = type_stack_push(stack, ELEMENTSOF(stack)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(stack), typeof(&*(stack))), sizeof(stack)/sizeof(
(stack)[0]), ((void)0)))
, &stack_ptr, types, n_struct, n_array);
2461 if (r < 0)
2462 return r;
2463
2464 types = s;
2465 n_struct = strlen(s);
2466 n_array = (unsigned) -1;
2467
2468 break;
2469 }
2470
2471 case SD_BUS_TYPE_STRUCT_BEGIN:
2472 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2473 size_t k;
2474
2475 r = signature_element_length(t, &k);
2476 if (r < 0)
2477 return r;
2478
2479 {
2480 char s[k - 1];
2481
2482 memcpy(s, t + 1, k - 2);
2483 s[k - 2] = 0;
2484
2485 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2486 if (r < 0)
2487 return r;
2488 }
2489
2490 if (n_array == (unsigned) -1) {
2491 types += k - 1;
2492 n_struct -= k - 1;
2493 }
2494
2495 r = type_stack_push(stack, ELEMENTSOF(stack)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(stack), typeof(&*(stack))), sizeof(stack)/sizeof(
(stack)[0]), ((void)0)))
, &stack_ptr, types, n_struct, n_array);
2496 if (r < 0)
2497 return r;
2498
2499 types = t + 1;
2500 n_struct = k - 2;
2501 n_array = (unsigned) -1;
2502
2503 break;
2504 }
2505
2506 default:
2507 r = -EINVAL22;
2508 }
2509
2510 if (r < 0)
2511 return r;
2512 }
2513
2514 return 1;
2515}
2516
2517_public___attribute__ ((visibility("default"))) int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2518 va_list ap;
2519 int r;
2520
2521 va_start(ap, types)__builtin_va_start(ap, types);
2522 r = sd_bus_message_appendv(m, types, ap);
2523 va_end(ap)__builtin_va_end(ap);
2524
2525 return r;
2526}
2527
2528_public___attribute__ ((visibility("default"))) int sd_bus_message_append_array_space(
2529 sd_bus_message *m,
2530 char type,
2531 size_t size,
2532 void **ptr) {
2533
2534 ssize_t align, sz;
2535 void *a;
2536 int r;
2537
2538 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 2538, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2539 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 2539, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
2540 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL)do { if (!(((__builtin_expect(!!(bus_type_is_trivial(type) &&
type != SD_BUS_TYPE_BOOLEAN),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN"
), "../src/libsystemd/sd-bus/bus-message.c", 2540, __PRETTY_FUNCTION__
), 0))) return (-22); } while (0)
;
2541 assert_return(ptr || size == 0, -EINVAL)do { if (!(((__builtin_expect(!!(ptr || size == 0),1))) ? (1)
: (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("ptr || size == 0"
), "../src/libsystemd/sd-bus/bus-message.c", 2541, __PRETTY_FUNCTION__
), 0))) return (-22); } while (0)
;
2542 assert_return(!m->poisoned, -ESTALE)do { if (!(((__builtin_expect(!!(!m->poisoned),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->poisoned"
), "../src/libsystemd/sd-bus/bus-message.c", 2542, __PRETTY_FUNCTION__
), 0))) return (-116); } while (0)
;
2543
2544 /* alignment and size of the trivial types (except bool) is
2545 * identical for gvariant and dbus1 marshalling */
2546 align = bus_type_get_alignment(type);
2547 sz = bus_type_get_size(type);
2548
2549 assert_se(align > 0)do { if ((__builtin_expect(!!(!(align > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("align > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 2549, __PRETTY_FUNCTION__); } while (0)
;
2550 assert_se(sz > 0)do { if ((__builtin_expect(!!(!(sz > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("sz > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 2550, __PRETTY_FUNCTION__); } while (0)
;
2551
2552 if (size % sz != 0)
2553 return -EINVAL22;
2554
2555 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type)((char[2]) { type, 0 }));
2556 if (r < 0)
2557 return r;
2558
2559 a = message_extend_body(m, align, size, false0, false0);
2560 if (!a)
2561 return -ENOMEM12;
2562
2563 r = sd_bus_message_close_container(m);
2564 if (r < 0)
2565 return r;
2566
2567 *ptr = a;
2568 return 0;
2569}
2570
2571_public___attribute__ ((visibility("default"))) int sd_bus_message_append_array(
2572 sd_bus_message *m,
2573 char type,
2574 const void *ptr,
2575 size_t size) {
2576 int r;
2577 void *p;
2578
2579 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 2579, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2580 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 2580, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
2581 assert_return(bus_type_is_trivial(type), -EINVAL)do { if (!(((__builtin_expect(!!(bus_type_is_trivial(type)),1
))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("bus_type_is_trivial(type)"), "../src/libsystemd/sd-bus/bus-message.c"
, 2581, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2582 assert_return(ptr || size == 0, -EINVAL)do { if (!(((__builtin_expect(!!(ptr || size == 0),1))) ? (1)
: (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("ptr || size == 0"
), "../src/libsystemd/sd-bus/bus-message.c", 2582, __PRETTY_FUNCTION__
), 0))) return (-22); } while (0)
;
2583 assert_return(!m->poisoned, -ESTALE)do { if (!(((__builtin_expect(!!(!m->poisoned),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->poisoned"
), "../src/libsystemd/sd-bus/bus-message.c", 2583, __PRETTY_FUNCTION__
), 0))) return (-116); } while (0)
;
2584
2585 r = sd_bus_message_append_array_space(m, type, size, &p);
2586 if (r < 0)
2587 return r;
2588
2589 memcpy_safe(p, ptr, size);
2590
2591 return 0;
2592}
2593
2594_public___attribute__ ((visibility("default"))) int sd_bus_message_append_array_iovec(
2595 sd_bus_message *m,
2596 char type,
2597 const struct iovec *iov,
2598 unsigned n /* should be size_t, but is API now… 😞 */) {
2599
2600 size_t size;
2601 unsigned i;
2602 void *p;
2603 int r;
2604
2605 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 2605, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2606 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 2606, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
2607 assert_return(bus_type_is_trivial(type), -EINVAL)do { if (!(((__builtin_expect(!!(bus_type_is_trivial(type)),1
))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("bus_type_is_trivial(type)"), "../src/libsystemd/sd-bus/bus-message.c"
, 2607, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2608 assert_return(iov || n == 0, -EINVAL)do { if (!(((__builtin_expect(!!(iov || n == 0),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("iov || n == 0"
), "../src/libsystemd/sd-bus/bus-message.c", 2608, __PRETTY_FUNCTION__
), 0))) return (-22); } while (0)
;
2609 assert_return(!m->poisoned, -ESTALE)do { if (!(((__builtin_expect(!!(!m->poisoned),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->poisoned"
), "../src/libsystemd/sd-bus/bus-message.c", 2609, __PRETTY_FUNCTION__
), 0))) return (-116); } while (0)
;
2610
2611 size = IOVEC_TOTAL_SIZE(iov, n);
2612
2613 r = sd_bus_message_append_array_space(m, type, size, &p);
2614 if (r < 0)
2615 return r;
2616
2617 for (i = 0; i < n; i++) {
2618
2619 if (iov[i].iov_base)
2620 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2621 else
2622 memzero(p, iov[i].iov_len)({ size_t _l_ = (iov[i].iov_len); void *_x_ = (p); _l_ == 0 ?
_x_ : memset(_x_, 0, _l_); })
;
2623
2624 p = (uint8_t*) p + iov[i].iov_len;
2625 }
2626
2627 return 0;
2628}
2629
2630_public___attribute__ ((visibility("default"))) int sd_bus_message_append_array_memfd(
2631 sd_bus_message *m,
2632 char type,
2633 int memfd,
2634 uint64_t offset,
2635 uint64_t size) {
2636
2637 _cleanup_close___attribute__((cleanup(closep))) int copy_fd = -1;
2638 struct bus_body_part *part;
2639 ssize_t align, sz;
2640 uint64_t real_size;
2641 void *a;
2642 int r;
2643
2644 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 2644, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2645 assert_return(memfd >= 0, -EBADF)do { if (!(((__builtin_expect(!!(memfd >= 0),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("memfd >= 0"
), "../src/libsystemd/sd-bus/bus-message.c", 2645, __PRETTY_FUNCTION__
), 0))) return (-9); } while (0)
;
2646 assert_return(bus_type_is_trivial(type), -EINVAL)do { if (!(((__builtin_expect(!!(bus_type_is_trivial(type)),1
))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("bus_type_is_trivial(type)"), "../src/libsystemd/sd-bus/bus-message.c"
, 2646, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2647 assert_return(size > 0, -EINVAL)do { if (!(((__builtin_expect(!!(size > 0),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("size > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 2647, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2648 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 2648, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
2649 assert_return(!m->poisoned, -ESTALE)do { if (!(((__builtin_expect(!!(!m->poisoned),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->poisoned"
), "../src/libsystemd/sd-bus/bus-message.c", 2649, __PRETTY_FUNCTION__
), 0))) return (-116); } while (0)
;
2650
2651 r = memfd_set_sealed(memfd);
2652 if (r < 0)
2653 return r;
2654
2655 copy_fd = fcntl(memfd, F_DUPFD_CLOEXEC1030, 3);
2656 if (copy_fd < 0)
2657 return copy_fd;
2658
2659 r = memfd_get_size(memfd, &real_size);
2660 if (r < 0)
2661 return r;
2662
2663 if (offset == 0 && size == (uint64_t) -1)
2664 size = real_size;
2665 else if (offset + size > real_size)
2666 return -EMSGSIZE90;
2667
2668 align = bus_type_get_alignment(type);
2669 sz = bus_type_get_size(type);
2670
2671 assert_se(align > 0)do { if ((__builtin_expect(!!(!(align > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("align > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 2671, __PRETTY_FUNCTION__); } while (0)
;
2672 assert_se(sz > 0)do { if ((__builtin_expect(!!(!(sz > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("sz > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 2672, __PRETTY_FUNCTION__); } while (0)
;
2673
2674 if (offset % align != 0)
2675 return -EINVAL22;
2676
2677 if (size % sz != 0)
2678 return -EINVAL22;
2679
2680 if (size > (uint64_t) (uint32_t) -1)
2681 return -EINVAL22;
2682
2683 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type)((char[2]) { type, 0 }));
2684 if (r < 0)
2685 return r;
2686
2687 a = message_extend_body(m, align, 0, false0, false0);
2688 if (!a)
2689 return -ENOMEM12;
2690
2691 part = message_append_part(m);
2692 if (!part)
2693 return -ENOMEM12;
2694
2695 part->memfd = copy_fd;
2696 part->memfd_offset = offset;
2697 part->sealed = true1;
2698 part->size = size;
2699 copy_fd = -1;
2700
2701 m->body_size += size;
2702 message_extend_containers(m, size);
2703
2704 return sd_bus_message_close_container(m);
2705}
2706
2707_public___attribute__ ((visibility("default"))) int sd_bus_message_append_string_memfd(
2708 sd_bus_message *m,
2709 int memfd,
2710 uint64_t offset,
2711 uint64_t size) {
2712
2713 _cleanup_close___attribute__((cleanup(closep))) int copy_fd = -1;
2714 struct bus_body_part *part;
2715 struct bus_container *c;
2716 uint64_t real_size;
2717 void *a;
2718 int r;
2719
2720 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 2720, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2721 assert_return(memfd >= 0, -EBADF)do { if (!(((__builtin_expect(!!(memfd >= 0),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("memfd >= 0"
), "../src/libsystemd/sd-bus/bus-message.c", 2721, __PRETTY_FUNCTION__
), 0))) return (-9); } while (0)
;
2722 assert_return(size > 0, -EINVAL)do { if (!(((__builtin_expect(!!(size > 0),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("size > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 2722, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2723 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 2723, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
2724 assert_return(!m->poisoned, -ESTALE)do { if (!(((__builtin_expect(!!(!m->poisoned),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->poisoned"
), "../src/libsystemd/sd-bus/bus-message.c", 2724, __PRETTY_FUNCTION__
), 0))) return (-116); } while (0)
;
2725
2726 r = memfd_set_sealed(memfd);
2727 if (r < 0)
2728 return r;
2729
2730 copy_fd = fcntl(memfd, FD_CLOEXEC1, 3);
2731 if (copy_fd < 0)
2732 return copy_fd;
2733
2734 r = memfd_get_size(memfd, &real_size);
2735 if (r < 0)
2736 return r;
2737
2738 if (offset == 0 && size == (uint64_t) -1)
2739 size = real_size;
2740 else if (offset + size > real_size)
2741 return -EMSGSIZE90;
2742
2743 /* We require this to be NUL terminated */
2744 if (size == 0)
2745 return -EINVAL22;
2746
2747 if (size > (uint64_t) (uint32_t) -1)
2748 return -EINVAL22;
2749
2750 c = message_get_last_container(m);
2751 if (c->signature && c->signature[c->index]) {
2752 /* Container signature is already set */
2753
2754 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2755 return -ENXIO6;
2756 } else {
2757 char *e;
2758
2759 /* Maybe we can append to the signature? But only if this is the top-level container */
2760 if (c->enclosing != 0)
2761 return -ENXIO6;
2762
2763 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL)strextend_with_separator(&c->signature, ((void*)0), ((
char[2]) { SD_BUS_TYPE_STRING, 0 }), ((void*)0))
;
2764 if (!e) {
2765 m->poisoned = true1;
2766 return -ENOMEM12;
2767 }
2768 }
2769
2770 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2771 a = message_extend_body(m, 4, 4, false0, false0);
2772 if (!a)
2773 return -ENOMEM12;
2774
2775 *(uint32_t*) a = size - 1;
2776 }
2777
2778 part = message_append_part(m);
2779 if (!part)
2780 return -ENOMEM12;
2781
2782 part->memfd = copy_fd;
2783 part->memfd_offset = offset;
2784 part->sealed = true1;
2785 part->size = size;
2786 copy_fd = -1;
2787
2788 m->body_size += size;
2789 message_extend_containers(m, size);
2790
2791 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2792 r = message_add_offset(m, m->body_size);
2793 if (r < 0) {
2794 m->poisoned = true1;
2795 return -ENOMEM12;
2796 }
2797 }
2798
2799 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2800 c->index++;
2801
2802 return 0;
2803}
2804
2805_public___attribute__ ((visibility("default"))) int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2806 char **i;
2807 int r;
2808
2809 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 2809, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2810 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 2810, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
2811 assert_return(!m->poisoned, -ESTALE)do { if (!(((__builtin_expect(!!(!m->poisoned),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->poisoned"
), "../src/libsystemd/sd-bus/bus-message.c", 2811, __PRETTY_FUNCTION__
), 0))) return (-116); } while (0)
;
2812
2813 r = sd_bus_message_open_container(m, 'a', "s");
2814 if (r < 0)
2815 return r;
2816
2817 STRV_FOREACH(i, l)for ((i) = (l); (i) && *(i); (i)++) {
2818 r = sd_bus_message_append_basic(m, 's', *i);
2819 if (r < 0)
2820 return r;
2821 }
2822
2823 return sd_bus_message_close_container(m);
2824}
2825
2826static int bus_message_close_header(sd_bus_message *m) {
2827
2828 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 2828, __PRETTY_FUNCTION__); } while (0)
;
2829
2830 /* The actual user data is finished now, we just complete the
2831 variant and struct now (at least on gvariant). Remember
2832 this position, so that during parsing we know where to
2833 put the outer container end. */
2834 m->user_body_size = m->body_size;
2835
2836 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2837 const char *signature;
2838 size_t sz, l;
2839 void *d;
2840
2841 /* Add offset table to end of fields array */
2842 if (m->n_header_offsets >= 1) {
2843 uint8_t *a;
2844 unsigned i;
2845
2846 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1])do { if ((__builtin_expect(!!(!(m->fields_size == m->header_offsets
[m->n_header_offsets-1])),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("m->fields_size == m->header_offsets[m->n_header_offsets-1]"
), "../src/libsystemd/sd-bus/bus-message.c", 2846, __PRETTY_FUNCTION__
); } while (0)
;
2847
2848 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2849 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false0);
2850 if (!a)
2851 return -ENOMEM12;
2852
2853 for (i = 0; i < m->n_header_offsets; i++)
2854 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2855 }
2856
2857 /* Add gvariant NUL byte plus signature to the end of
2858 * the body, followed by the final offset pointing to
2859 * the end of the fields array */
2860
2861 signature = strempty(m->root_container.signature);
2862 l = strlen(signature);
2863
2864 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size)(((m->fields_size) + 7) & ~7) + m->body_size + 1 + l + 2, 1);
2865 d = message_extend_body(m, 1, 1 + l + 2 + sz, false0, true1);
2866 if (!d)
2867 return -ENOMEM12;
2868
2869 *(uint8_t*) d = 0;
2870 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2871 memcpy((uint8_t*) d + 2, signature, l);
2872 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2873
2874 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2875
2876 m->footer = d;
2877 m->footer_accessible = 1 + l + 2 + sz;
2878 } else {
2879 m->header->dbus1.fields_size = m->fields_size;
2880 m->header->dbus1.body_size = m->body_size;
2881 }
2882
2883 return 0;
2884}
2885
2886_public___attribute__ ((visibility("default"))) int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t timeout_usec) {
2887 struct bus_body_part *part;
2888 size_t a;
2889 unsigned i;
2890 int r;
2891
2892 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 2892, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2893
2894 if (m->sealed)
2895 return -EPERM1;
2896
2897 if (m->n_containers > 0)
2898 return -EBADMSG74;
2899
2900 if (m->poisoned)
2901 return -ESTALE116;
2902
2903 if (cookie > 0xffffffffULL &&
2904 !BUS_MESSAGE_IS_GVARIANT(m))
2905 return -EOPNOTSUPP95;
2906
2907 /* In vtables the return signature of method calls is listed,
2908 * let's check if they match if this is a response */
2909 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2910 m->enforced_reply_signature &&
2911 !streq(strempty(m->root_container.signature), m->enforced_reply_signature)(strcmp((strempty(m->root_container.signature)),(m->enforced_reply_signature
)) == 0)
)
2912 return -ENOMSG42;
2913
2914 /* If gvariant marshalling is used we need to close the body structure */
2915 r = bus_message_close_struct(m, &m->root_container, false0);
2916 if (r < 0)
2917 return r;
2918
2919 /* If there's a non-trivial signature set, then add it in
2920 * here, but only on dbus1 */
2921 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2922 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL((void*)0));
2923 if (r < 0)
2924 return r;
2925 }
2926
2927 if (m->n_fds > 0) {
2928 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2929 if (r < 0)
2930 return r;
2931 }
2932
2933 r = bus_message_close_header(m);
2934 if (r < 0)
2935 return r;
2936
2937 if (BUS_MESSAGE_IS_GVARIANT(m))
2938 m->header->dbus2.cookie = cookie;
2939 else
2940 m->header->dbus1.serial = (uint32_t) cookie;
2941
2942 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout_usec;
2943
2944 /* Add padding at the end of the fields part, since we know
2945 * the body needs to start at an 8 byte alignment. We made
2946 * sure we allocated enough space for this, so all we need to
2947 * do here is to zero it out. */
2948 a = ALIGN8(m->fields_size)(((m->fields_size) + 7) & ~7) - m->fields_size;
2949 if (a > 0)
2950 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a)({ size_t _l_ = (a); void *_x_ = ((uint8_t*) BUS_MESSAGE_FIELDS
(m) + m->fields_size); _l_ == 0 ? _x_ : memset(_x_, 0, _l_
); })
;
2951
2952 /* If this is something we can send as memfd, then let's seal
2953 the memfd now. Note that we can send memfds as payload only
2954 for directed messages, and not for broadcasts. */
2955 if (m->destination && m->bus->use_memfd) {
2956 MESSAGE_FOREACH_PART(part, i, m)for ((i) = 0, (part) = &(m)->body; (i) < (m)->n_body_parts
; (i)++, (part) = (part)->next)
2957 if (part->memfd >= 0 &&
2958 !part->sealed &&
2959 (part->size > MEMFD_MIN_SIZE(512*1024) || m->bus->use_memfd < 0) &&
2960 part != m->body_end) { /* The last part may never be sent as memfd */
2961 uint64_t sz;
2962
2963 /* Try to seal it if that makes
2964 * sense. First, unmap our own map to
2965 * make sure we don't keep it busy. */
2966 bus_body_part_unmap(part);
2967
2968 /* Then, sync up real memfd size */
2969 sz = part->size;
2970 r = memfd_set_size(part->memfd, sz);
2971 if (r < 0)
2972 return r;
2973
2974 /* Finally, try to seal */
2975 if (memfd_set_sealed(part->memfd) >= 0)
2976 part->sealed = true1;
2977 }
2978 }
2979
2980 m->root_container.end = m->user_body_size;
2981 m->root_container.index = 0;
2982 m->root_container.offset_index = 0;
2983 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2984
2985 m->sealed = true1;
2986
2987 return 0;
2988}
2989
2990int bus_body_part_map(struct bus_body_part *part) {
2991 void *p;
2992 size_t psz, shift;
2993
2994 assert_se(part)do { if ((__builtin_expect(!!(!(part)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("part"), "../src/libsystemd/sd-bus/bus-message.c"
, 2994, __PRETTY_FUNCTION__); } while (0)
;
2995
2996 if (part->data)
2997 return 0;
2998
2999 if (part->size <= 0)
3000 return 0;
3001
3002 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3003 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3004 static const uint8_t zeroes[7] = { };
3005 part->data = (void*) zeroes;
3006 return 0;
3007 }
3008
3009 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3010 psz = PAGE_ALIGN(part->size + shift)ALIGN_TO((part->size + shift), page_size());
3011
3012 if (part->memfd >= 0)
3013 p = mmap(NULL((void*)0), psz, PROT_READ0x1, MAP_PRIVATE0x02, part->memfd, part->memfd_offset - shift);
3014 else if (part->is_zero)
3015 p = mmap(NULL((void*)0), psz, PROT_READ0x1, MAP_PRIVATE0x02|MAP_ANONYMOUS0x20, -1, 0);
3016 else
3017 return -EINVAL22;
3018
3019 if (p == MAP_FAILED((void *) -1))
3020 return -errno(*__errno_location ());
3021
3022 part->mapped = psz;
3023 part->mmap_begin = p;
3024 part->data = (uint8_t*) p + shift;
3025 part->munmap_this = true1;
3026
3027 return 0;
3028}
3029
3030void bus_body_part_unmap(struct bus_body_part *part) {
3031
3032 assert_se(part)do { if ((__builtin_expect(!!(!(part)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("part"), "../src/libsystemd/sd-bus/bus-message.c"
, 3032, __PRETTY_FUNCTION__); } while (0)
;
3033
3034 if (part->memfd < 0)
3035 return;
3036
3037 if (!part->mmap_begin)
3038 return;
3039
3040 if (!part->munmap_this)
3041 return;
3042
3043 assert_se(munmap(part->mmap_begin, part->mapped) == 0)do { if ((__builtin_expect(!!(!(munmap(part->mmap_begin, part
->mapped) == 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("munmap(part->mmap_begin, part->mapped) == 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 3043, __PRETTY_FUNCTION__); } while (0)
;
3044
3045 part->mmap_begin = NULL((void*)0);
3046 part->data = NULL((void*)0);
3047 part->mapped = 0;
3048 part->munmap_this = false0;
3049
3050 return;
3051}
3052
3053static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3054 size_t k, start, end;
3055
3056 assert(rindex)do { if ((__builtin_expect(!!(!(rindex)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rindex"), "../src/libsystemd/sd-bus/bus-message.c"
, 3056, __PRETTY_FUNCTION__); } while (0)
;
3057 assert(align > 0)do { if ((__builtin_expect(!!(!(align > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("align > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 3057, __PRETTY_FUNCTION__); } while (0)
;
3058
3059 start = ALIGN_TO((size_t) *rindex, align);
3060 end = start + nbytes;
3061
3062 if (end > sz)
3063 return -EBADMSG74;
3064
3065 /* Verify that padding is 0 */
3066 for (k = *rindex; k < start; k++)
3067 if (((const uint8_t*) p)[k] != 0)
3068 return -EBADMSG74;
3069
3070 if (r)
3071 *r = (uint8_t*) p + start;
3072
3073 *rindex = end;
3074
3075 return 1;
3076}
3077
3078static bool_Bool message_end_of_signature(sd_bus_message *m) {
3079 struct bus_container *c;
3080
3081 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 3081, __PRETTY_FUNCTION__); } while (0)
;
3082
3083 c = message_get_last_container(m);
3084 return !c->signature || c->signature[c->index] == 0;
3085}
3086
3087static bool_Bool message_end_of_array(sd_bus_message *m, size_t index) {
3088 struct bus_container *c;
3089
3090 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 3090, __PRETTY_FUNCTION__); } while (0)
;
3091
3092 c = message_get_last_container(m);
3093 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3094 return false0;
3095
3096 if (BUS_MESSAGE_IS_GVARIANT(m))
3097 return index >= c->end;
3098 else {
3099 assert(c->array_size)do { if ((__builtin_expect(!!(!(c->array_size)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c->array_size"), "../src/libsystemd/sd-bus/bus-message.c"
, 3099, __PRETTY_FUNCTION__); } while (0)
;
3100 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3101 }
3102}
3103
3104_public___attribute__ ((visibility("default"))) int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3105 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 3105, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
3106 assert_return(m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 3106, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
3107
3108 if (complete && m->n_containers > 0)
3109 return false0;
3110
3111 if (message_end_of_signature(m))
3112 return true1;
3113
3114 if (message_end_of_array(m, m->rindex))
3115 return true1;
3116
3117 return false0;
3118}
3119
3120static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3121 struct bus_body_part *part;
3122 size_t begin;
3123 int r;
3124
3125 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 3125, __PRETTY_FUNCTION__); } while (0)
;
3126
3127 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3128 part = m->cached_rindex_part;
3129 begin = m->cached_rindex_part_begin;
3130 } else {
3131 part = &m->body;
3132 begin = 0;
3133 }
3134
3135 while (part) {
3136 if (index < begin)
3137 return NULL((void*)0);
3138
3139 if (index + sz <= begin + part->size) {
3140
3141 r = bus_body_part_map(part);
3142 if (r < 0)
3143 return NULL((void*)0);
3144
3145 if (p)
3146 *p = (uint8_t*) part->data + index - begin;
3147
3148 m->cached_rindex_part = part;
3149 m->cached_rindex_part_begin = begin;
3150
3151 return part;
3152 }
3153
3154 begin += part->size;
3155 part = part->next;
3156 }
3157
3158 return NULL((void*)0);
3159}
3160
3161static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3162 int r;
3163
3164 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 3164, __PRETTY_FUNCTION__); } while (0)
;
3165 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-message.c"
, 3165, __PRETTY_FUNCTION__); } while (0)
;
3166 assert(rindex)do { if ((__builtin_expect(!!(!(rindex)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rindex"), "../src/libsystemd/sd-bus/bus-message.c"
, 3166, __PRETTY_FUNCTION__); } while (0)
;
3167
3168 if (!BUS_MESSAGE_IS_GVARIANT(m))
3169 return 0;
3170
3171 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3172 int sz;
3173
3174 sz = bus_gvariant_get_size(c->signature);
3175 if (sz < 0) {
3176 int alignment;
3177
3178 if (c->offset_index+1 >= c->n_offsets)
3179 goto end;
3180
3181 /* Variable-size array */
3182
3183 alignment = bus_gvariant_get_alignment(c->signature);
3184 assert(alignment > 0)do { if ((__builtin_expect(!!(!(alignment > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("alignment > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 3184, __PRETTY_FUNCTION__); } while (0)
;
3185
3186 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3187 assert(c->offsets[c->offset_index+1] >= *rindex)do { if ((__builtin_expect(!!(!(c->offsets[c->offset_index
+1] >= *rindex)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("c->offsets[c->offset_index+1] >= *rindex"), "../src/libsystemd/sd-bus/bus-message.c"
, 3187, __PRETTY_FUNCTION__); } while (0)
;
3188 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3189 } else {
3190
3191 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3192 goto end;
3193
3194 /* Fixed-size array */
3195 *rindex = c->begin + (c->offset_index+1) * sz;
3196 c->item_size = sz;
3197 }
3198
3199 c->offset_index++;
3200
3201 } else if (IN_SET(c->enclosing, 0, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){0, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY
})/sizeof(int)]; switch(c->enclosing) { case 0: case SD_BUS_TYPE_STRUCT
: case SD_BUS_TYPE_DICT_ENTRY: _found = 1; break; default: break
; } _found; })
) {
3202
3203 int alignment;
3204 size_t n, j;
3205
3206 if (c->offset_index+1 >= c->n_offsets)
3207 goto end;
3208
3209 r = signature_element_length(c->signature + c->index, &n);
3210 if (r < 0)
3211 return r;
3212
3213 r = signature_element_length(c->signature + c->index + n, &j);
3214 if (r < 0)
3215 return r;
3216 else {
3217 char t[j+1];
3218 memcpy(t, c->signature + c->index + n, j);
3219 t[j] = 0;
3220
3221 alignment = bus_gvariant_get_alignment(t);
3222 }
3223
3224 assert(alignment > 0)do { if ((__builtin_expect(!!(!(alignment > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("alignment > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 3224, __PRETTY_FUNCTION__); } while (0)
;
3225
3226 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3227 assert(c->offsets[c->offset_index+1] >= *rindex)do { if ((__builtin_expect(!!(!(c->offsets[c->offset_index
+1] >= *rindex)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("c->offsets[c->offset_index+1] >= *rindex"), "../src/libsystemd/sd-bus/bus-message.c"
, 3227, __PRETTY_FUNCTION__); } while (0)
;
3228 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3229
3230 c->offset_index++;
3231
3232 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3233 goto end;
3234 else
3235 assert_not_reached("Unknown container type")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, (
"Unknown container type"), "../src/libsystemd/sd-bus/bus-message.c"
, 3235, __PRETTY_FUNCTION__); } while (0)
;
3236
3237 return 0;
3238
3239end:
3240 /* Reached the end */
3241 *rindex = c->end;
3242 c->item_size = 0;
3243 return 0;
3244}
3245
3246static int message_peek_body(
3247 sd_bus_message *m,
3248 size_t *rindex,
3249 size_t align,
3250 size_t nbytes,
3251 void **ret) {
3252
3253 size_t k, start, end, padding;
3254 struct bus_body_part *part;
3255 uint8_t *q;
3256
3257 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 3257, __PRETTY_FUNCTION__); } while (0)
;
3258 assert(rindex)do { if ((__builtin_expect(!!(!(rindex)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rindex"), "../src/libsystemd/sd-bus/bus-message.c"
, 3258, __PRETTY_FUNCTION__); } while (0)
;
3259 assert(align > 0)do { if ((__builtin_expect(!!(!(align > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("align > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 3259, __PRETTY_FUNCTION__); } while (0)
;
3260
3261 start = ALIGN_TO((size_t) *rindex, align);
3262 padding = start - *rindex;
3263 end = start + nbytes;
3264
3265 if (end > m->user_body_size)
3266 return -EBADMSG74;
3267
3268 part = find_part(m, *rindex, padding, (void**) &q);
3269 if (!part)
3270 return -EBADMSG74;
3271
3272 if (q) {
3273 /* Verify padding */
3274 for (k = 0; k < padding; k++)
3275 if (q[k] != 0)
3276 return -EBADMSG74;
3277 }
3278
3279 part = find_part(m, start, nbytes, (void**) &q);
3280 if (!part || (nbytes > 0 && !q))
3281 return -EBADMSG74;
3282
3283 *rindex = end;
3284
3285 if (ret)
3286 *ret = q;
3287
3288 return 0;
3289}
3290
3291static bool_Bool validate_nul(const char *s, size_t l) {
3292
3293 /* Check for NUL chars in the string */
3294 if (memchr(s, 0, l))
3295 return false0;
3296
3297 /* Check for NUL termination */
3298 if (s[l] != 0)
3299 return false0;
3300
3301 return true1;
3302}
3303
3304static bool_Bool validate_string(const char *s, size_t l) {
3305
3306 if (!validate_nul(s, l))
3307 return false0;
3308
3309 /* Check if valid UTF8 */
3310 if (!utf8_is_valid(s))
3311 return false0;
3312
3313 return true1;
3314}
3315
3316static bool_Bool validate_signature(const char *s, size_t l) {
3317
3318 if (!validate_nul(s, l))
3319 return false0;
3320
3321 /* Check if valid signature */
3322 if (!signature_is_valid(s, true1))
3323 return false0;
3324
3325 return true1;
3326}
3327
3328static bool_Bool validate_object_path(const char *s, size_t l) {
3329
3330 if (!validate_nul(s, l))
3331 return false0;
3332
3333 if (!object_path_is_valid(s))
3334 return false0;
3335
3336 return true1;
3337}
3338
3339_public___attribute__ ((visibility("default"))) int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3340 struct bus_container *c;
3341 size_t rindex;
3342 void *q;
3343 int r;
3344
3345 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 3345, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
3346 assert_return(m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 3346, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
3347 assert_return(bus_type_is_basic(type), -EINVAL)do { if (!(((__builtin_expect(!!(bus_type_is_basic(type)),1))
) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"bus_type_is_basic(type)"), "../src/libsystemd/sd-bus/bus-message.c"
, 3347, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
3348
3349 if (message_end_of_signature(m))
3350 return -ENXIO6;
3351
3352 if (message_end_of_array(m, m->rindex))
3353 return 0;
3354
3355 c = message_get_last_container(m);
3356 if (c->signature[c->index] != type)
3357 return -ENXIO6;
3358
3359 rindex = m->rindex;
3360
3361 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3362
3363 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE})/sizeof(int)]; switch(type) { case SD_BUS_TYPE_STRING
: case SD_BUS_TYPE_OBJECT_PATH: case SD_BUS_TYPE_SIGNATURE: _found
= 1; break; default: break; } _found; })
) {
3364 bool_Bool ok;
3365
3366 /* D-Bus spec: The marshalling formats for the string-like types all end
3367 * with a single zero (NUL) byte, but that byte is not considered to be part
3368 * of the text. */
3369 if (c->item_size == 0)
3370 return -EBADMSG74;
3371
3372 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3373 if (r < 0)
3374 return r;
3375
3376 if (type == SD_BUS_TYPE_STRING)
3377 ok = validate_string(q, c->item_size-1);
3378 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3379 ok = validate_object_path(q, c->item_size-1);
3380 else
3381 ok = validate_signature(q, c->item_size-1);
3382
3383 if (!ok)
3384 return -EBADMSG74;
3385
3386 if (p)
3387 *(const char**) p = q;
3388 } else {
3389 int sz, align;
3390
3391 sz = bus_gvariant_get_size(CHAR_TO_STR(type)((char[2]) { type, 0 }));
3392 assert(sz > 0)do { if ((__builtin_expect(!!(!(sz > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("sz > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 3392, __PRETTY_FUNCTION__); } while (0)
;
3393 if ((size_t) sz != c->item_size)
3394 return -EBADMSG74;
3395
3396 align = bus_gvariant_get_alignment(CHAR_TO_STR(type)((char[2]) { type, 0 }));
3397 assert(align > 0)do { if ((__builtin_expect(!!(!(align > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("align > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 3397, __PRETTY_FUNCTION__); } while (0)
;
3398
3399 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3400 if (r < 0)
3401 return r;
3402
3403 switch (type) {
3404
3405 case SD_BUS_TYPE_BYTE:
3406 if (p)
3407 *(uint8_t*) p = *(uint8_t*) q;
3408 break;
3409
3410 case SD_BUS_TYPE_BOOLEAN:
3411 if (p)
3412 *(int*) p = !!*(uint8_t*) q;
3413 break;
3414
3415 case SD_BUS_TYPE_INT16:
3416 case SD_BUS_TYPE_UINT16:
3417 if (p)
3418 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3419 break;
3420
3421 case SD_BUS_TYPE_INT32:
3422 case SD_BUS_TYPE_UINT32:
3423 if (p)
3424 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3425 break;
3426
3427 case SD_BUS_TYPE_INT64:
3428 case SD_BUS_TYPE_UINT64:
3429 case SD_BUS_TYPE_DOUBLE:
3430 if (p)
3431 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3432 break;
3433
3434 case SD_BUS_TYPE_UNIX_FD: {
3435 uint32_t j;
3436
3437 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3438 if (j >= m->n_fds)
3439 return -EBADMSG74;
3440
3441 if (p)
3442 *(int*) p = m->fds[j];
3443
3444 break;
3445 }
3446
3447 default:
3448 assert_not_reached("unexpected type")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, (
"unexpected type"), "../src/libsystemd/sd-bus/bus-message.c",
3448, __PRETTY_FUNCTION__); } while (0)
;
3449 }
3450 }
3451
3452 r = container_next_item(m, c, &rindex);
3453 if (r < 0)
3454 return r;
3455 } else {
3456
3457 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH
})/sizeof(int)]; switch(type) { case SD_BUS_TYPE_STRING: case
SD_BUS_TYPE_OBJECT_PATH: _found = 1; break; default: break; }
_found; })
) {
3458 uint32_t l;
3459 bool_Bool ok;
3460
3461 r = message_peek_body(m, &rindex, 4, 4, &q);
3462 if (r < 0)
3463 return r;
3464
3465 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3466 if (l == UINT32_MAX(4294967295U))
3467 /* avoid overflow right below */
3468 return -EBADMSG74;
3469
3470 r = message_peek_body(m, &rindex, 1, l+1, &q);
3471 if (r < 0)
3472 return r;
3473
3474 if (type == SD_BUS_TYPE_OBJECT_PATH)
3475 ok = validate_object_path(q, l);
3476 else
3477 ok = validate_string(q, l);
3478 if (!ok)
3479 return -EBADMSG74;
3480
3481 if (p)
3482 *(const char**) p = q;
3483
3484 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3485 uint8_t l;
3486
3487 r = message_peek_body(m, &rindex, 1, 1, &q);
3488 if (r < 0)
3489 return r;
3490
3491 l = *(uint8_t*) q;
3492 if (l == UINT8_MAX(255))
3493 /* avoid overflow right below */
3494 return -EBADMSG74;
3495
3496 r = message_peek_body(m, &rindex, 1, l+1, &q);
3497 if (r < 0)
3498 return r;
3499
3500 if (!validate_signature(q, l))
3501 return -EBADMSG74;
3502
3503 if (p)
3504 *(const char**) p = q;
3505
3506 } else {
3507 ssize_t sz, align;
3508
3509 align = bus_type_get_alignment(type);
3510 assert(align > 0)do { if ((__builtin_expect(!!(!(align > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("align > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 3510, __PRETTY_FUNCTION__); } while (0)
;
3511
3512 sz = bus_type_get_size(type);
3513 assert(sz > 0)do { if ((__builtin_expect(!!(!(sz > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("sz > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 3513, __PRETTY_FUNCTION__); } while (0)
;
3514
3515 r = message_peek_body(m, &rindex, align, sz, &q);
3516 if (r < 0)
3517 return r;
3518
3519 switch (type) {
3520
3521 case SD_BUS_TYPE_BYTE:
3522 if (p)
3523 *(uint8_t*) p = *(uint8_t*) q;
3524 break;
3525
3526 case SD_BUS_TYPE_BOOLEAN:
3527 if (p)
3528 *(int*) p = !!*(uint32_t*) q;
3529 break;
3530
3531 case SD_BUS_TYPE_INT16:
3532 case SD_BUS_TYPE_UINT16:
3533 if (p)
3534 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3535 break;
3536
3537 case SD_BUS_TYPE_INT32:
3538 case SD_BUS_TYPE_UINT32:
3539 if (p)
3540 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3541 break;
3542
3543 case SD_BUS_TYPE_INT64:
3544 case SD_BUS_TYPE_UINT64:
3545 case SD_BUS_TYPE_DOUBLE:
3546 if (p)
3547 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3548 break;
3549
3550 case SD_BUS_TYPE_UNIX_FD: {
3551 uint32_t j;
3552
3553 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3554 if (j >= m->n_fds)
3555 return -EBADMSG74;
3556
3557 if (p)
3558 *(int*) p = m->fds[j];
3559 break;
3560 }
3561
3562 default:
3563 assert_not_reached("Unknown basic type...")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, (
"Unknown basic type..."), "../src/libsystemd/sd-bus/bus-message.c"
, 3563, __PRETTY_FUNCTION__); } while (0)
;
3564 }
3565 }
3566 }
3567
3568 m->rindex = rindex;
3569
3570 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3571 c->index++;
3572
3573 return 1;
3574}
3575
3576static int bus_message_enter_array(
3577 sd_bus_message *m,
3578 struct bus_container *c,
3579 const char *contents,
3580 uint32_t **array_size,
3581 size_t *item_size,
3582 size_t **offsets,
3583 size_t *n_offsets) {
3584
3585 size_t rindex;
3586 void *q;
3587 int r;
3588
3589 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 3589, __PRETTY_FUNCTION__); } while (0)
;
3590 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-message.c"
, 3590, __PRETTY_FUNCTION__); } while (0)
;
3591 assert(contents)do { if ((__builtin_expect(!!(!(contents)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("contents"), "../src/libsystemd/sd-bus/bus-message.c"
, 3591, __PRETTY_FUNCTION__); } while (0)
;
3592 assert(array_size)do { if ((__builtin_expect(!!(!(array_size)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("array_size"), "../src/libsystemd/sd-bus/bus-message.c"
, 3592, __PRETTY_FUNCTION__); } while (0)
;
3593 assert(item_size)do { if ((__builtin_expect(!!(!(item_size)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("item_size"), "../src/libsystemd/sd-bus/bus-message.c"
, 3593, __PRETTY_FUNCTION__); } while (0)
;
3594 assert(offsets)do { if ((__builtin_expect(!!(!(offsets)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("offsets"), "../src/libsystemd/sd-bus/bus-message.c"
, 3594, __PRETTY_FUNCTION__); } while (0)
;
3595 assert(n_offsets)do { if ((__builtin_expect(!!(!(n_offsets)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n_offsets"), "../src/libsystemd/sd-bus/bus-message.c"
, 3595, __PRETTY_FUNCTION__); } while (0)
;
3596
3597 if (!signature_is_single(contents, true1))
3598 return -EINVAL22;
3599
3600 if (!c->signature || c->signature[c->index] == 0)
3601 return -ENXIO6;
3602
3603 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3604 return -ENXIO6;
3605
3606 if (!startswith(c->signature + c->index + 1, contents))
3607 return -ENXIO6;
3608
3609 rindex = m->rindex;
3610
3611 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3612 /* dbus1 */
3613 int alignment;
3614
3615 r = message_peek_body(m, &rindex, 4, 4, &q);
3616 if (r < 0)
3617 return r;
3618
3619 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE67108864)
3620 return -EBADMSG74;
3621
3622 alignment = bus_type_get_alignment(contents[0]);
3623 if (alignment < 0)
3624 return alignment;
3625
3626 r = message_peek_body(m, &rindex, alignment, 0, NULL((void*)0));
3627 if (r < 0)
3628 return r;
3629
3630 *array_size = (uint32_t*) q;
3631
3632 } else if (c->item_size <= 0) {
3633
3634 /* gvariant: empty array */
3635 *item_size = 0;
3636 *offsets = NULL((void*)0);
3637 *n_offsets = 0;
3638
3639 } else if (bus_gvariant_is_fixed_size(contents)) {
3640
3641 /* gvariant: fixed length array */
3642 *item_size = bus_gvariant_get_size(contents);
3643 *offsets = NULL((void*)0);
3644 *n_offsets = 0;
3645
3646 } else {
3647 size_t where, previous = 0, framing, sz;
3648 int alignment;
3649 unsigned i;
3650
3651 /* gvariant: variable length array */
3652 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3653
3654 where = rindex + c->item_size - sz;
3655 r = message_peek_body(m, &where, 1, sz, &q);
3656 if (r < 0)
3657 return r;
3658
3659 framing = bus_gvariant_read_word_le(q, sz);
3660 if (framing > c->item_size - sz)
3661 return -EBADMSG74;
3662 if ((c->item_size - framing) % sz != 0)
3663 return -EBADMSG74;
3664
3665 *n_offsets = (c->item_size - framing) / sz;
3666
3667 where = rindex + framing;
3668 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3669 if (r < 0)
3670 return r;
3671
3672 *offsets = new(size_t, *n_offsets)((size_t*) malloc_multiply(sizeof(size_t), (*n_offsets)));
3673 if (!*offsets)
3674 return -ENOMEM12;
3675
3676 alignment = bus_gvariant_get_alignment(c->signature);
3677 assert(alignment > 0)do { if ((__builtin_expect(!!(!(alignment > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("alignment > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 3677, __PRETTY_FUNCTION__); } while (0)
;
3678
3679 for (i = 0; i < *n_offsets; i++) {
3680 size_t x, start;
3681
3682 start = ALIGN_TO(previous, alignment);
3683
3684 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3685 if (x > c->item_size - sz)
3686 return -EBADMSG74;
3687 if (x < start)
3688 return -EBADMSG74;
3689
3690 (*offsets)[i] = rindex + x;
3691 previous = x;
3692 }
3693
3694 *item_size = (*offsets)[0] - rindex;
3695 }
3696
3697 m->rindex = rindex;
3698
3699 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3700 c->index += 1 + strlen(contents);
3701
3702 return 1;
3703}
3704
3705static int bus_message_enter_variant(
3706 sd_bus_message *m,
3707 struct bus_container *c,
3708 const char *contents,
3709 size_t *item_size) {
3710
3711 size_t rindex;
3712 uint8_t l;
3713 void *q;
3714 int r;
3715
3716 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 3716, __PRETTY_FUNCTION__); } while (0)
;
3717 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-message.c"
, 3717, __PRETTY_FUNCTION__); } while (0)
;
3718 assert(contents)do { if ((__builtin_expect(!!(!(contents)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("contents"), "../src/libsystemd/sd-bus/bus-message.c"
, 3718, __PRETTY_FUNCTION__); } while (0)
;
3719 assert(item_size)do { if ((__builtin_expect(!!(!(item_size)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("item_size"), "../src/libsystemd/sd-bus/bus-message.c"
, 3719, __PRETTY_FUNCTION__); } while (0)
;
3720
3721 if (!signature_is_single(contents, false0))
3722 return -EINVAL22;
3723
3724 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3725 return -EINVAL22;
3726
3727 if (!c->signature || c->signature[c->index] == 0)
3728 return -ENXIO6;
3729
3730 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3731 return -ENXIO6;
3732
3733 rindex = m->rindex;
3734
3735 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3736 size_t k, where;
3737
3738 k = strlen(contents);
3739 if (1+k > c->item_size)
3740 return -EBADMSG74;
3741
3742 where = rindex + c->item_size - (1+k);
3743 r = message_peek_body(m, &where, 1, 1+k, &q);
3744 if (r < 0)
3745 return r;
3746
3747 if (*(char*) q != 0)
3748 return -EBADMSG74;
3749
3750 if (memcmp((uint8_t*) q+1, contents, k))
3751 return -ENXIO6;
3752
3753 *item_size = c->item_size - (1+k);
3754
3755 } else {
3756 r = message_peek_body(m, &rindex, 1, 1, &q);
3757 if (r < 0)
3758 return r;
3759
3760 l = *(uint8_t*) q;
3761 if (l == UINT8_MAX(255))
3762 /* avoid overflow right below */
3763 return -EBADMSG74;
3764
3765 r = message_peek_body(m, &rindex, 1, l+1, &q);
3766 if (r < 0)
3767 return r;
3768
3769 if (!validate_signature(q, l))
3770 return -EBADMSG74;
3771
3772 if (!streq(q, contents)(strcmp((q),(contents)) == 0))
3773 return -ENXIO6;
3774 }
3775
3776 m->rindex = rindex;
3777
3778 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3779 c->index++;
3780
3781 return 1;
3782}
3783
3784static int build_struct_offsets(
3785 sd_bus_message *m,
3786 const char *signature,
3787 size_t size,
3788 size_t *item_size,
3789 size_t **offsets,
3790 size_t *n_offsets) {
3791
3792 unsigned n_variable = 0, n_total = 0, v;
3793 size_t previous, where;
3794 const char *p;
3795 size_t sz;
3796 void *q;
3797 int r;
3798
3799 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 3799, __PRETTY_FUNCTION__); } while (0)
;
3800 assert(item_size)do { if ((__builtin_expect(!!(!(item_size)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("item_size"), "../src/libsystemd/sd-bus/bus-message.c"
, 3800, __PRETTY_FUNCTION__); } while (0)
;
3801 assert(offsets)do { if ((__builtin_expect(!!(!(offsets)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("offsets"), "../src/libsystemd/sd-bus/bus-message.c"
, 3801, __PRETTY_FUNCTION__); } while (0)
;
3802 assert(n_offsets)do { if ((__builtin_expect(!!(!(n_offsets)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n_offsets"), "../src/libsystemd/sd-bus/bus-message.c"
, 3802, __PRETTY_FUNCTION__); } while (0)
;
3803
3804 if (isempty(signature)) {
3805 /* Unary type is encoded as *fixed* 1 byte padding */
3806 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3807 if (r < 0)
3808 return r;
3809
3810 if (*(uint8_t *) q != 0)
3811 return -EBADMSG74;
3812
3813 *item_size = 0;
3814 *offsets = NULL((void*)0);
3815 *n_offsets = 0;
3816 return 0;
3817 }
3818
3819 sz = bus_gvariant_determine_word_size(size, 0);
3820 if (sz <= 0)
3821 return -EBADMSG74;
3822
3823 /* First, loop over signature and count variable elements and
3824 * elements in general. We use this to know how large the
3825 * offset array is at the end of the structure. Note that
3826 * GVariant only stores offsets for all variable size elements
3827 * that are not the last item. */
3828
3829 p = signature;
3830 while (*p != 0) {
3831 size_t n;
3832
3833 r = signature_element_length(p, &n);
3834 if (r < 0)
3835 return r;
3836 else {
3837 char t[n+1];
3838
3839 memcpy(t, p, n);
3840 t[n] = 0;
3841
3842 r = bus_gvariant_is_fixed_size(t);
3843 }
3844
3845 if (r < 0)
3846 return r;
3847 if (r == 0 && p[n] != 0) /* except the last item */
3848 n_variable++;
3849 n_total++;
3850
3851 p += n;
3852 }
3853
3854 if (size < n_variable * sz)
3855 return -EBADMSG74;
3856
3857 where = m->rindex + size - (n_variable * sz);
3858 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3859 if (r < 0)
3860 return r;
3861
3862 v = n_variable;
3863
3864 *offsets = new(size_t, n_total)((size_t*) malloc_multiply(sizeof(size_t), (n_total)));
3865 if (!*offsets)
3866 return -ENOMEM12;
3867
3868 *n_offsets = 0;
3869
3870 /* Second, loop again and build an offset table */
3871 p = signature;
3872 previous = m->rindex;
3873 while (*p != 0) {
3874 size_t n, offset;
3875 int k;
3876
3877 r = signature_element_length(p, &n);
3878 if (r < 0)
3879 return r;
3880 else {
3881 char t[n+1];
3882
3883 memcpy(t, p, n);
3884 t[n] = 0;
3885
3886 size_t align = bus_gvariant_get_alignment(t);
3887 assert(align > 0)do { if ((__builtin_expect(!!(!(align > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("align > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 3887, __PRETTY_FUNCTION__); } while (0)
;
3888
3889 /* The possible start of this member after including alignment */
3890 size_t start = ALIGN_TO(previous, align);
3891
3892 k = bus_gvariant_get_size(t);
3893 if (k < 0) {
3894 size_t x;
3895
3896 /* Variable size */
3897 if (v > 0) {
3898 v--;
3899
3900 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3901 if (x >= size)
3902 return -EBADMSG74;
3903 } else
3904 /* The last item's end is determined
3905 * from the start of the offset array */
3906 x = size - (n_variable * sz);
3907
3908 offset = m->rindex + x;
3909 if (offset < start) {
3910 log_debug("For type %s with alignment %zu, message specifies offset %zu which is smaller than previous end %zu + alignment = %zu",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/libsystemd/sd-bus/bus-message.c", 3911, __func__, "For type %s with alignment %zu, message specifies offset %zu which is smaller than previous end %zu + alignment = %zu"
, t, align, offset, previous, start) : -abs(_e); })
3911 t, align, offset, previous, start)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/libsystemd/sd-bus/bus-message.c", 3911, __func__, "For type %s with alignment %zu, message specifies offset %zu which is smaller than previous end %zu + alignment = %zu"
, t, align, offset, previous, start) : -abs(_e); })
;
3912 return -EBADMSG74;
3913 }
3914 } else
3915 /* Fixed size */
3916 offset = start + k;
3917 }
3918
3919 previous = (*offsets)[(*n_offsets)++] = offset;
3920 p += n;
3921 }
3922
3923 assert(v == 0)do { if ((__builtin_expect(!!(!(v == 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("v == 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 3923, __PRETTY_FUNCTION__); } while (0)
;
3924 assert(*n_offsets == n_total)do { if ((__builtin_expect(!!(!(*n_offsets == n_total)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("*n_offsets == n_total"), "../src/libsystemd/sd-bus/bus-message.c"
, 3924, __PRETTY_FUNCTION__); } while (0)
;
3925
3926 *item_size = (*offsets)[0] - m->rindex;
3927 return 0;
3928}
3929
3930static int enter_struct_or_dict_entry(
3931 sd_bus_message *m,
3932 struct bus_container *c,
3933 const char *contents,
3934 size_t *item_size,
3935 size_t **offsets,
3936 size_t *n_offsets) {
3937
3938 int r;
3939
3940 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 3940, __PRETTY_FUNCTION__); } while (0)
;
3941 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-message.c"
, 3941, __PRETTY_FUNCTION__); } while (0)
;
3942 assert(contents)do { if ((__builtin_expect(!!(!(contents)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("contents"), "../src/libsystemd/sd-bus/bus-message.c"
, 3942, __PRETTY_FUNCTION__); } while (0)
;
3943 assert(item_size)do { if ((__builtin_expect(!!(!(item_size)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("item_size"), "../src/libsystemd/sd-bus/bus-message.c"
, 3943, __PRETTY_FUNCTION__); } while (0)
;
3944 assert(offsets)do { if ((__builtin_expect(!!(!(offsets)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("offsets"), "../src/libsystemd/sd-bus/bus-message.c"
, 3944, __PRETTY_FUNCTION__); } while (0)
;
3945 assert(n_offsets)do { if ((__builtin_expect(!!(!(n_offsets)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n_offsets"), "../src/libsystemd/sd-bus/bus-message.c"
, 3945, __PRETTY_FUNCTION__); } while (0)
;
3946
3947 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3948
3949 /* dbus1 */
3950 r = message_peek_body(m, &m->rindex, 8, 0, NULL((void*)0));
3951 if (r < 0)
3952 return r;
3953
3954 } else
3955 /* gvariant with contents */
3956 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3957
3958 return 0;
3959}
3960
3961static int bus_message_enter_struct(
3962 sd_bus_message *m,
3963 struct bus_container *c,
3964 const char *contents,
3965 size_t *item_size,
3966 size_t **offsets,
3967 size_t *n_offsets) {
3968
3969 size_t l;
3970 int r;
3971
3972 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 3972, __PRETTY_FUNCTION__); } while (0)
;
3973 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-message.c"
, 3973, __PRETTY_FUNCTION__); } while (0)
;
3974 assert(contents)do { if ((__builtin_expect(!!(!(contents)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("contents"), "../src/libsystemd/sd-bus/bus-message.c"
, 3974, __PRETTY_FUNCTION__); } while (0)
;
3975 assert(item_size)do { if ((__builtin_expect(!!(!(item_size)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("item_size"), "../src/libsystemd/sd-bus/bus-message.c"
, 3975, __PRETTY_FUNCTION__); } while (0)
;
3976 assert(offsets)do { if ((__builtin_expect(!!(!(offsets)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("offsets"), "../src/libsystemd/sd-bus/bus-message.c"
, 3976, __PRETTY_FUNCTION__); } while (0)
;
3977 assert(n_offsets)do { if ((__builtin_expect(!!(!(n_offsets)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n_offsets"), "../src/libsystemd/sd-bus/bus-message.c"
, 3977, __PRETTY_FUNCTION__); } while (0)
;
3978
3979 if (!signature_is_valid(contents, false0))
3980 return -EINVAL22;
3981
3982 if (!c->signature || c->signature[c->index] == 0)
3983 return -ENXIO6;
3984
3985 l = strlen(contents);
3986
3987 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3988 !startswith(c->signature + c->index + 1, contents) ||
3989 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3990 return -ENXIO6;
3991
3992 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3993 if (r < 0)
3994 return r;
3995
3996 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3997 c->index += 1 + l + 1;
3998
3999 return 1;
4000}
4001
4002static int bus_message_enter_dict_entry(
4003 sd_bus_message *m,
4004 struct bus_container *c,
4005 const char *contents,
4006 size_t *item_size,
4007 size_t **offsets,
4008 size_t *n_offsets) {
4009
4010 size_t l;
4011 int r;
4012
4013 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 4013, __PRETTY_FUNCTION__); } while (0)
;
4014 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-message.c"
, 4014, __PRETTY_FUNCTION__); } while (0)
;
4015 assert(contents)do { if ((__builtin_expect(!!(!(contents)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("contents"), "../src/libsystemd/sd-bus/bus-message.c"
, 4015, __PRETTY_FUNCTION__); } while (0)
;
4016
4017 if (!signature_is_pair(contents))
4018 return -EINVAL22;
4019
4020 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4021 return -ENXIO6;
4022
4023 if (!c->signature || c->signature[c->index] == 0)
4024 return 0;
4025
4026 l = strlen(contents);
4027
4028 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4029 !startswith(c->signature + c->index + 1, contents) ||
4030 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4031 return -ENXIO6;
4032
4033 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4034 if (r < 0)
4035 return r;
4036
4037 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4038 c->index += 1 + l + 1;
4039
4040 return 1;
4041}
4042
4043_public___attribute__ ((visibility("default"))) int sd_bus_message_enter_container(sd_bus_message *m,
4044 char type,
4045 const char *contents) {
4046 struct bus_container *c;
4047 uint32_t *array_size = NULL((void*)0);
4048 _cleanup_free___attribute__((cleanup(freep))) char *signature = NULL((void*)0);
4049 size_t before, end;
4050 _cleanup_free___attribute__((cleanup(freep))) size_t *offsets = NULL((void*)0);
4051 size_t n_offsets = 0, item_size = 0;
4052 int r;
4053
4054 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 4054, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
4055 assert_return(m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 4055, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
4056 assert_return(type != 0 || !contents, -EINVAL)do { if (!(((__builtin_expect(!!(type != 0 || !contents),1)))
? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"type != 0 || !contents"), "../src/libsystemd/sd-bus/bus-message.c"
, 4056, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
4057
4058 if (type == 0 || !contents) {
4059 const char *cc;
4060 char tt;
4061
4062 /* Allow entering into anonymous containers */
4063 r = sd_bus_message_peek_type(m, &tt, &cc);
4064 if (r < 0)
4065 return r;
4066
4067 if (type != 0 && type != tt)
4068 return -ENXIO6;
4069
4070 if (contents && !streq(contents, cc)(strcmp((contents),(cc)) == 0))
4071 return -ENXIO6;
4072
4073 type = tt;
4074 contents = cc;
4075 }
4076
4077 /*
4078 * We enforce a global limit on container depth, that is much
4079 * higher than the 32 structs and 32 arrays the specification
4080 * mandates. This is simpler to implement for us, and we need
4081 * this only to ensure our container array doesn't grow
4082 * without bounds. We are happy to return any data from a
4083 * message as long as the data itself is valid, even if the
4084 * overall message might be not.
4085 *
4086 * Note that the message signature is validated when
4087 * parsing the headers, and that validation does check the
4088 * 32/32 limit.
4089 *
4090 * Note that the specification defines no limits on the depth
4091 * of stacked variants, but we do.
4092 */
4093 if (m->n_containers >= BUS_CONTAINER_DEPTH128)
4094 return -EBADMSG74;
4095
4096 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)greedy_realloc((void**) &(m->containers), &(m->
containers_allocated), (m->n_containers + 1), sizeof((m->
containers)[0]))
)
4097 return -ENOMEM12;
4098
4099 if (message_end_of_signature(m))
4100 return -ENXIO6;
4101
4102 if (message_end_of_array(m, m->rindex))
4103 return 0;
4104
4105 c = message_get_last_container(m);
4106
4107 signature = strdup(contents);
4108 if (!signature)
4109 return -ENOMEM12;
4110
4111 c->saved_index = c->index;
4112 before = m->rindex;
4113
4114 if (type == SD_BUS_TYPE_ARRAY)
4115 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4116 else if (type == SD_BUS_TYPE_VARIANT)
4117 r = bus_message_enter_variant(m, c, contents, &item_size);
4118 else if (type == SD_BUS_TYPE_STRUCT)
4119 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4120 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4121 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4122 else
4123 r = -EINVAL22;
4124 if (r <= 0)
4125 return r;
4126
4127 /* OK, let's fill it in */
4128 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4129 type == SD_BUS_TYPE_STRUCT &&
4130 isempty(signature))
4131 end = m->rindex + 0;
4132 else
4133 end = m->rindex + c->item_size;
4134
4135 m->containers[m->n_containers++] = (struct bus_container) {
4136 .enclosing = type,
4137 .signature = TAKE_PTR(signature)({ typeof(signature) _ptr_ = (signature); (signature) = ((void
*)0); _ptr_; })
,
4138
4139 .before = before,
4140 .begin = m->rindex,
4141 /* Unary type has fixed size of 1, but virtual size of 0 */
4142 .end = end,
4143 .array_size = array_size,
4144 .item_size = item_size,
4145 .offsets = TAKE_PTR(offsets)({ typeof(offsets) _ptr_ = (offsets); (offsets) = ((void*)0);
_ptr_; })
,
4146 .n_offsets = n_offsets,
4147 };
4148
4149 return 1;
4150}
4151
4152_public___attribute__ ((visibility("default"))) int sd_bus_message_exit_container(sd_bus_message *m) {
4153 struct bus_container *c;
4154 unsigned saved;
4155 int r;
4156
4157 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 4157, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
4158 assert_return(m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 4158, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
4159 assert_return(m->n_containers > 0, -ENXIO)do { if (!(((__builtin_expect(!!(m->n_containers > 0),1
))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("m->n_containers > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 4159, __PRETTY_FUNCTION__), 0))) return (-6); } while (0)
;
4160
4161 c = message_get_last_container(m);
4162
4163 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4164 if (c->signature && c->signature[c->index] != 0)
4165 return -EBUSY16;
4166 }
4167
4168 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4169 if (m->rindex < c->end)
4170 return -EBUSY16;
4171
4172 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4173 uint32_t l;
4174
4175 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4176 if (c->begin + l != m->rindex)
4177 return -EBUSY16;
4178 }
4179
4180 message_free_last_container(m);
4181
4182 c = message_get_last_container(m);
4183 saved = c->index;
4184 c->index = c->saved_index;
4185 r = container_next_item(m, c, &m->rindex);
4186 c->index = saved;
4187 if (r < 0)
4188 return r;
4189
4190 return 1;
4191}
4192
4193static void message_quit_container(sd_bus_message *m) {
4194 struct bus_container *c;
4195
4196 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 4196, __PRETTY_FUNCTION__); } while (0)
;
4197 assert(m->sealed)do { if ((__builtin_expect(!!(!(m->sealed)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m->sealed"), "../src/libsystemd/sd-bus/bus-message.c"
, 4197, __PRETTY_FUNCTION__); } while (0)
;
4198 assert(m->n_containers > 0)do { if ((__builtin_expect(!!(!(m->n_containers > 0)),0
))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("m->n_containers > 0"
), "../src/libsystemd/sd-bus/bus-message.c", 4198, __PRETTY_FUNCTION__
); } while (0)
;
4199
4200 /* Undo seeks */
4201 c = message_get_last_container(m);
4202 assert(m->rindex >= c->before)do { if ((__builtin_expect(!!(!(m->rindex >= c->before
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("m->rindex >= c->before"
), "../src/libsystemd/sd-bus/bus-message.c", 4202, __PRETTY_FUNCTION__
); } while (0)
;
4203 m->rindex = c->before;
4204
4205 /* Free container */
4206 message_free_last_container(m);
4207
4208 /* Correct index of new top-level container */
4209 c = message_get_last_container(m);
4210 c->index = c->saved_index;
4211}
4212
4213_public___attribute__ ((visibility("default"))) int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4214 struct bus_container *c;
4215 int r;
4216
4217 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 4217, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
4218 assert_return(m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 4218, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
4219
4220 if (message_end_of_signature(m))
4221 goto eof;
4222
4223 if (message_end_of_array(m, m->rindex))
4224 goto eof;
4225
4226 c = message_get_last_container(m);
4227
4228 if (bus_type_is_basic(c->signature[c->index])) {
4229 if (contents)
4230 *contents = NULL((void*)0);
4231 if (type)
4232 *type = c->signature[c->index];
4233 return 1;
4234 }
4235
4236 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4237
4238 if (contents) {
4239 size_t l;
4240
4241 r = signature_element_length(c->signature+c->index+1, &l);
4242 if (r < 0)
4243 return r;
4244
4245 /* signature_element_length does verification internally */
4246
4247 /* The array element must not be empty */
4248 assert(l >= 1)do { if ((__builtin_expect(!!(!(l >= 1)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l >= 1"), "../src/libsystemd/sd-bus/bus-message.c"
, 4248, __PRETTY_FUNCTION__); } while (0)
;
4249 if (free_and_strndup(&c->peeked_signature,
4250 c->signature + c->index + 1, l) < 0)
4251 return -ENOMEM12;
4252
4253 *contents = c->peeked_signature;
4254 }
4255
4256 if (type)
4257 *type = SD_BUS_TYPE_ARRAY;
4258
4259 return 1;
4260 }
4261
4262 if (IN_SET(c->signature[c->index], SD_BUS_TYPE_STRUCT_BEGIN, SD_BUS_TYPE_DICT_ENTRY_BEGIN)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_BUS_TYPE_STRUCT_BEGIN, SD_BUS_TYPE_DICT_ENTRY_BEGIN
})/sizeof(int)]; switch(c->signature[c->index]) { case SD_BUS_TYPE_STRUCT_BEGIN
: case SD_BUS_TYPE_DICT_ENTRY_BEGIN: _found = 1; break; default
: break; } _found; })
) {
4263
4264 if (contents) {
4265 size_t l;
4266
4267 r = signature_element_length(c->signature+c->index, &l);
4268 if (r < 0)
4269 return r;
4270
4271 assert(l >= 3)do { if ((__builtin_expect(!!(!(l >= 3)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l >= 3"), "../src/libsystemd/sd-bus/bus-message.c"
, 4271, __PRETTY_FUNCTION__); } while (0)
;
4272 if (free_and_strndup(&c->peeked_signature,
4273 c->signature + c->index + 1, l - 2) < 0)
4274 return -ENOMEM12;
4275
4276 *contents = c->peeked_signature;
4277 }
4278
4279 if (type)
4280 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4281
4282 return 1;
4283 }
4284
4285 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4286 if (contents) {
4287 void *q;
4288
4289 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4290 size_t k;
4291
4292 if (c->item_size < 2)
4293 return -EBADMSG74;
4294
4295 /* Look for the NUL delimiter that
4296 separates the payload from the
4297 signature. Since the body might be
4298 in a different part that then the
4299 signature we map byte by byte. */
4300
4301 for (k = 2; k <= c->item_size; k++) {
4302 size_t where;
4303
4304 where = m->rindex + c->item_size - k;
4305 r = message_peek_body(m, &where, 1, k, &q);
4306 if (r < 0)
4307 return r;
4308
4309 if (*(char*) q == 0)
4310 break;
4311 }
4312
4313 if (k > c->item_size)
4314 return -EBADMSG74;
4315
4316 if (free_and_strndup(&c->peeked_signature,
4317 (char*) q + 1, k - 1) < 0)
4318 return -ENOMEM12;
4319
4320 if (!signature_is_valid(c->peeked_signature, true1))
4321 return -EBADMSG74;
4322
4323 *contents = c->peeked_signature;
4324 } else {
4325 size_t rindex, l;
4326
4327 rindex = m->rindex;
4328 r = message_peek_body(m, &rindex, 1, 1, &q);
4329 if (r < 0)
4330 return r;
4331
4332 l = *(uint8_t*) q;
4333 if (l == UINT8_MAX(255))
4334 /* avoid overflow right below */
4335 return -EBADMSG74;
4336
4337 r = message_peek_body(m, &rindex, 1, l+1, &q);
4338 if (r < 0)
4339 return r;
4340
4341 if (!validate_signature(q, l))
4342 return -EBADMSG74;
4343
4344 *contents = q;
4345 }
4346 }
4347
4348 if (type)
4349 *type = SD_BUS_TYPE_VARIANT;
4350
4351 return 1;
4352 }
4353
4354 return -EINVAL22;
4355
4356eof:
4357 if (type)
4358 *type = 0;
4359 if (contents)
4360 *contents = NULL((void*)0);
4361 return 0;
4362}
4363
4364_public___attribute__ ((visibility("default"))) int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4365 struct bus_container *c;
4366
4367 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 4367, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
4368 assert_return(m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 4368, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
4369
4370 if (complete) {
4371 message_reset_containers(m);
4372 m->rindex = 0;
4373
4374 c = message_get_last_container(m);
4375 } else {
4376 c = message_get_last_container(m);
4377
4378 c->index = 0;
4379 m->rindex = c->begin;
4380 }
4381
4382 c->offset_index = 0;
4383 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4384
4385 return !isempty(c->signature);
4386}
4387
4388static int message_read_ap(
4389 sd_bus_message *m,
4390 const char *types,
4391 va_list ap) {
4392
4393 unsigned n_array, n_struct;
4394 TypeStack stack[BUS_CONTAINER_DEPTH128];
4395 unsigned stack_ptr = 0;
4396 unsigned n_loop = 0;
4397 int r;
4398
4399 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 4399, __PRETTY_FUNCTION__); } while (0)
;
4400
4401 if (isempty(types))
4402 return 0;
4403
4404 /* Ideally, we'd just call ourselves recursively on every
4405 * complex type. However, the state of a va_list that is
4406 * passed to a function is undefined after that function
4407 * returns. This means we need to decode the va_list linearly
4408 * in a single stackframe. We hence implement our own
4409 * home-grown stack in an array. */
4410
4411 n_array = (unsigned) -1; /* length of current array entries */
4412 n_struct = strlen(types); /* length of current struct contents signature */
4413
4414 for (;;) {
4415 const char *t;
4416
4417 n_loop++;
4418
4419 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4420 r = type_stack_pop(stack, ELEMENTSOF(stack)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(stack), typeof(&*(stack))), sizeof(stack)/sizeof(
(stack)[0]), ((void)0)))
, &stack_ptr, &types, &n_struct, &n_array);
4421 if (r < 0)
4422 return r;
4423 if (r == 0)
4424 break;
4425
4426 r = sd_bus_message_exit_container(m);
4427 if (r < 0)
4428 return r;
4429
4430 continue;
4431 }
4432
4433 t = types;
4434 if (n_array != (unsigned) -1)
4435 n_array--;
4436 else {
4437 types++;
4438 n_struct--;
4439 }
4440
4441 switch (*t) {
4442
4443 case SD_BUS_TYPE_BYTE:
4444 case SD_BUS_TYPE_BOOLEAN:
4445 case SD_BUS_TYPE_INT16:
4446 case SD_BUS_TYPE_UINT16:
4447 case SD_BUS_TYPE_INT32:
4448 case SD_BUS_TYPE_UINT32:
4449 case SD_BUS_TYPE_INT64:
4450 case SD_BUS_TYPE_UINT64:
4451 case SD_BUS_TYPE_DOUBLE:
4452 case SD_BUS_TYPE_STRING:
4453 case SD_BUS_TYPE_OBJECT_PATH:
4454 case SD_BUS_TYPE_SIGNATURE:
4455 case SD_BUS_TYPE_UNIX_FD: {
4456 void *p;
4457
4458 p = va_arg(ap, void*)__builtin_va_arg(ap, void*);
4459 r = sd_bus_message_read_basic(m, *t, p);
4460 if (r < 0)
4461 return r;
4462 if (r == 0) {
4463 if (n_loop <= 1)
4464 return 0;
4465
4466 return -ENXIO6;
4467 }
4468
4469 break;
4470 }
4471
4472 case SD_BUS_TYPE_ARRAY: {
4473 size_t k;
4474
4475 r = signature_element_length(t + 1, &k);
4476 if (r < 0)
4477 return r;
4478
4479 {
4480 char s[k + 1];
4481 memcpy(s, t + 1, k);
4482 s[k] = 0;
4483
4484 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4485 if (r < 0)
4486 return r;
4487 if (r == 0) {
4488 if (n_loop <= 1)
4489 return 0;
4490
4491 return -ENXIO6;
4492 }
4493 }
4494
4495 if (n_array == (unsigned) -1) {
4496 types += k;
4497 n_struct -= k;
4498 }
4499
4500 r = type_stack_push(stack, ELEMENTSOF(stack)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(stack), typeof(&*(stack))), sizeof(stack)/sizeof(
(stack)[0]), ((void)0)))
, &stack_ptr, types, n_struct, n_array);
4501 if (r < 0)
4502 return r;
4503
4504 types = t + 1;
4505 n_struct = k;
4506 n_array = va_arg(ap, unsigned)__builtin_va_arg(ap, unsigned);
4507
4508 break;
4509 }
4510
4511 case SD_BUS_TYPE_VARIANT: {
4512 const char *s;
4513
4514 s = va_arg(ap, const char *)__builtin_va_arg(ap, const char *);
4515 if (!s)
4516 return -EINVAL22;
4517
4518 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4519 if (r < 0)
4520 return r;
4521 if (r == 0) {
4522 if (n_loop <= 1)
4523 return 0;
4524
4525 return -ENXIO6;
4526 }
4527
4528 r = type_stack_push(stack, ELEMENTSOF(stack)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(stack), typeof(&*(stack))), sizeof(stack)/sizeof(
(stack)[0]), ((void)0)))
, &stack_ptr, types, n_struct, n_array);
4529 if (r < 0)
4530 return r;
4531
4532 types = s;
4533 n_struct = strlen(s);
4534 n_array = (unsigned) -1;
4535
4536 break;
4537 }
4538
4539 case SD_BUS_TYPE_STRUCT_BEGIN:
4540 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4541 size_t k;
4542
4543 r = signature_element_length(t, &k);
4544 if (r < 0)
4545 return r;
4546
4547 {
4548 char s[k - 1];
4549 memcpy(s, t + 1, k - 2);
4550 s[k - 2] = 0;
4551
4552 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4553 if (r < 0)
4554 return r;
4555 if (r == 0) {
4556 if (n_loop <= 1)
4557 return 0;
4558 return -ENXIO6;
4559 }
4560 }
4561
4562 if (n_array == (unsigned) -1) {
4563 types += k - 1;
4564 n_struct -= k - 1;
4565 }
4566
4567 r = type_stack_push(stack, ELEMENTSOF(stack)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(stack), typeof(&*(stack))), sizeof(stack)/sizeof(
(stack)[0]), ((void)0)))
, &stack_ptr, types, n_struct, n_array);
4568 if (r < 0)
4569 return r;
4570
4571 types = t + 1;
4572 n_struct = k - 2;
4573 n_array = (unsigned) -1;
4574
4575 break;
4576 }
4577
4578 default:
4579 return -EINVAL22;
4580 }
4581 }
4582
4583 return 1;
4584}
4585
4586_public___attribute__ ((visibility("default"))) int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4587 va_list ap;
4588 int r;
4589
4590 va_start(ap, types)__builtin_va_start(ap, types);
4591 r = message_read_ap(m, types, ap);
4592 va_end(ap)__builtin_va_end(ap);
4593
4594 return r;
4595}
4596
4597_public___attribute__ ((visibility("default"))) int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4598 int r;
4599
4600 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 4600, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
4601 assert_return(m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 4601, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
4602
4603 /* If types is NULL, read exactly one element */
4604 if (!types) {
4605 struct bus_container *c;
4606 size_t l;
4607
4608 if (message_end_of_signature(m))
4609 return -ENXIO6;
4610
4611 if (message_end_of_array(m, m->rindex))
4612 return 0;
4613
4614 c = message_get_last_container(m);
4615
4616 r = signature_element_length(c->signature + c->index, &l);
4617 if (r < 0)
4618 return r;
4619
4620 types = strndupa(c->signature + c->index, l)(__extension__ ({ const char *__old = (c->signature + c->
index); size_t __len = strnlen (__old, (l)); char *__new = (char
*) __builtin_alloca (__len + 1); __new[__len] = '\0'; (char *
) memcpy (__new, __old, __len); }))
;
4621 }
4622
4623 switch (*types) {
4624
4625 case 0: /* Nothing to drop */
4626 return 0;
4627
4628 case SD_BUS_TYPE_BYTE:
4629 case SD_BUS_TYPE_BOOLEAN:
4630 case SD_BUS_TYPE_INT16:
4631 case SD_BUS_TYPE_UINT16:
4632 case SD_BUS_TYPE_INT32:
4633 case SD_BUS_TYPE_UINT32:
4634 case SD_BUS_TYPE_INT64:
4635 case SD_BUS_TYPE_UINT64:
4636 case SD_BUS_TYPE_DOUBLE:
4637 case SD_BUS_TYPE_STRING:
4638 case SD_BUS_TYPE_OBJECT_PATH:
4639 case SD_BUS_TYPE_SIGNATURE:
4640 case SD_BUS_TYPE_UNIX_FD:
4641
4642 r = sd_bus_message_read_basic(m, *types, NULL((void*)0));
4643 if (r <= 0)
4644 return r;
4645
4646 r = sd_bus_message_skip(m, types + 1);
4647 if (r < 0)
4648 return r;
4649
4650 return 1;
4651
4652 case SD_BUS_TYPE_ARRAY: {
4653 size_t k;
4654
4655 r = signature_element_length(types + 1, &k);
4656 if (r < 0)
4657 return r;
4658
4659 {
4660 char s[k+1];
4661 memcpy(s, types+1, k);
4662 s[k] = 0;
4663
4664 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4665 if (r <= 0)
4666 return r;
4667
4668 for (;;) {
4669 r = sd_bus_message_skip(m, s);
4670 if (r < 0)
4671 return r;
4672 if (r == 0)
4673 break;
4674 }
4675
4676 r = sd_bus_message_exit_container(m);
4677 if (r < 0)
4678 return r;
4679 }
4680
4681 r = sd_bus_message_skip(m, types + 1 + k);
4682 if (r < 0)
4683 return r;
4684
4685 return 1;
4686 }
4687
4688 case SD_BUS_TYPE_VARIANT: {
4689 const char *contents;
4690 char x;
4691
4692 r = sd_bus_message_peek_type(m, &x, &contents);
4693 if (r <= 0)
4694 return r;
4695
4696 if (x != SD_BUS_TYPE_VARIANT)
4697 return -ENXIO6;
4698
4699 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4700 if (r <= 0)
4701 return r;
4702
4703 r = sd_bus_message_skip(m, contents);
4704 if (r < 0)
4705 return r;
4706 assert(r != 0)do { if ((__builtin_expect(!!(!(r != 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("r != 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 4706, __PRETTY_FUNCTION__); } while (0)
;
4707
4708 r = sd_bus_message_exit_container(m);
4709 if (r < 0)
4710 return r;
4711
4712 r = sd_bus_message_skip(m, types + 1);
4713 if (r < 0)
4714 return r;
4715
4716 return 1;
4717 }
4718
4719 case SD_BUS_TYPE_STRUCT_BEGIN:
4720 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4721 size_t k;
4722
4723 r = signature_element_length(types, &k);
4724 if (r < 0)
4725 return r;
4726
4727 {
4728 char s[k-1];
4729 memcpy(s, types+1, k-2);
4730 s[k-2] = 0;
4731
4732 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4733 if (r <= 0)
4734 return r;
4735
4736 r = sd_bus_message_skip(m, s);
4737 if (r < 0)
4738 return r;
4739
4740 r = sd_bus_message_exit_container(m);
4741 if (r < 0)
4742 return r;
4743 }
4744
4745 r = sd_bus_message_skip(m, types + k);
4746 if (r < 0)
4747 return r;
4748
4749 return 1;
4750 }
4751
4752 default:
4753 return -EINVAL22;
4754 }
4755}
4756
4757_public___attribute__ ((visibility("default"))) int sd_bus_message_read_array(
4758 sd_bus_message *m,
4759 char type,
4760 const void **ptr,
4761 size_t *size) {
4762
4763 struct bus_container *c;
4764 void *p;
4765 size_t sz;
4766 ssize_t align;
4767 int r;
4768
4769 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 4769, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
4770 assert_return(m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 4770, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
4771 assert_return(bus_type_is_trivial(type), -EINVAL)do { if (!(((__builtin_expect(!!(bus_type_is_trivial(type)),1
))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("bus_type_is_trivial(type)"), "../src/libsystemd/sd-bus/bus-message.c"
, 4771, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
4772 assert_return(ptr, -EINVAL)do { if (!(((__builtin_expect(!!(ptr),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("ptr"), "../src/libsystemd/sd-bus/bus-message.c"
, 4772, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
4773 assert_return(size, -EINVAL)do { if (!(((__builtin_expect(!!(size),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("size"), "../src/libsystemd/sd-bus/bus-message.c"
, 4773, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
4774 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP)do { if (!(((__builtin_expect(!!(!BUS_MESSAGE_NEED_BSWAP(m)),
1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("!BUS_MESSAGE_NEED_BSWAP(m)"), "../src/libsystemd/sd-bus/bus-message.c"
, 4774, __PRETTY_FUNCTION__), 0))) return (-95); } while (0)
;
4775
4776 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type)((char[2]) { type, 0 }));
4777 if (r <= 0)
4778 return r;
4779
4780 c = message_get_last_container(m);
4781
4782 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4783 align = bus_gvariant_get_alignment(CHAR_TO_STR(type)((char[2]) { type, 0 }));
4784 if (align < 0)
4785 return align;
4786
4787 sz = c->end - c->begin;
4788 } else {
4789 align = bus_type_get_alignment(type);
4790 if (align < 0)
4791 return align;
4792
4793 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4794 }
4795
4796 if (sz == 0)
4797 /* Zero length array, let's return some aligned
4798 * pointer that is not NULL */
4799 p = (uint8_t*) align;
4800 else {
4801 r = message_peek_body(m, &m->rindex, align, sz, &p);
4802 if (r < 0)
4803 goto fail;
4804 }
4805
4806 r = sd_bus_message_exit_container(m);
4807 if (r < 0)
4808 goto fail;
4809
4810 *ptr = (const void*) p;
4811 *size = sz;
4812
4813 return 1;
4814
4815fail:
4816 message_quit_container(m);
4817 return r;
4818}
4819
4820static int message_peek_fields(
4821 sd_bus_message *m,
4822 size_t *rindex,
4823 size_t align,
4824 size_t nbytes,
4825 void **ret) {
4826
4827 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 4827, __PRETTY_FUNCTION__); } while (0)
;
4828 assert(rindex)do { if ((__builtin_expect(!!(!(rindex)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rindex"), "../src/libsystemd/sd-bus/bus-message.c"
, 4828, __PRETTY_FUNCTION__); } while (0)
;
4829 assert(align > 0)do { if ((__builtin_expect(!!(!(align > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("align > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 4829, __PRETTY_FUNCTION__); } while (0)
;
4830
4831 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4832}
4833
4834static int message_peek_field_uint32(
4835 sd_bus_message *m,
4836 size_t *ri,
4837 size_t item_size,
4838 uint32_t *ret) {
4839
4840 int r;
4841 void *q;
4842
4843 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 4843, __PRETTY_FUNCTION__); } while (0)
;
4844 assert(ri)do { if ((__builtin_expect(!!(!(ri)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ri"), "../src/libsystemd/sd-bus/bus-message.c"
, 4844, __PRETTY_FUNCTION__); } while (0)
;
4845
4846 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4847 return -EBADMSG74;
4848
4849 /* identical for gvariant and dbus1 */
4850
4851 r = message_peek_fields(m, ri, 4, 4, &q);
4852 if (r < 0)
4853 return r;
4854
4855 if (ret)
4856 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4857
4858 return 0;
4859}
4860
4861static int message_peek_field_uint64(
4862 sd_bus_message *m,
4863 size_t *ri,
4864 size_t item_size,
4865 uint64_t *ret) {
4866
4867 int r;
4868 void *q;
4869
4870 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 4870, __PRETTY_FUNCTION__); } while (0)
;
4871 assert(ri)do { if ((__builtin_expect(!!(!(ri)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ri"), "../src/libsystemd/sd-bus/bus-message.c"
, 4871, __PRETTY_FUNCTION__); } while (0)
;
4872
4873 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4874 return -EBADMSG74;
4875
4876 /* identical for gvariant and dbus1 */
4877
4878 r = message_peek_fields(m, ri, 8, 8, &q);
4879 if (r < 0)
4880 return r;
4881
4882 if (ret)
4883 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4884
4885 return 0;
4886}
4887
4888static int message_peek_field_string(
4889 sd_bus_message *m,
4890 bool_Bool (*validate)(const char *p),
4891 size_t *ri,
4892 size_t item_size,
4893 const char **ret) {
4894
4895 uint32_t l;
4896 int r;
4897 void *q;
4898
4899 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 4899, __PRETTY_FUNCTION__); } while (0)
;
4900 assert(ri)do { if ((__builtin_expect(!!(!(ri)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ri"), "../src/libsystemd/sd-bus/bus-message.c"
, 4900, __PRETTY_FUNCTION__); } while (0)
;
4901
4902 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4903
4904 if (item_size <= 0)
4905 return -EBADMSG74;
4906
4907 r = message_peek_fields(m, ri, 1, item_size, &q);
4908 if (r < 0)
4909 return r;
4910
4911 l = item_size - 1;
4912 } else {
4913 r = message_peek_field_uint32(m, ri, 4, &l);
4914 if (r < 0)
4915 return r;
4916
4917 if (l == UINT32_MAX(4294967295U))
4918 /* avoid overflow right below */
4919 return -EBADMSG74;
4920
4921 r = message_peek_fields(m, ri, 1, l+1, &q);
4922 if (r < 0)
4923 return r;
4924 }
4925
4926 if (validate) {
4927 if (!validate_nul(q, l))
4928 return -EBADMSG74;
4929
4930 if (!validate(q))
4931 return -EBADMSG74;
4932 } else {
4933 if (!validate_string(q, l))
4934 return -EBADMSG74;
4935 }
4936
4937 if (ret)
4938 *ret = q;
4939
4940 return 0;
4941}
4942
4943static int message_peek_field_signature(
4944 sd_bus_message *m,
4945 size_t *ri,
4946 size_t item_size,
4947 const char **ret) {
4948
4949 size_t l;
4950 int r;
4951 void *q;
4952
4953 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 4953, __PRETTY_FUNCTION__); } while (0)
;
4954 assert(ri)do { if ((__builtin_expect(!!(!(ri)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ri"), "../src/libsystemd/sd-bus/bus-message.c"
, 4954, __PRETTY_FUNCTION__); } while (0)
;
4955
4956 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4957
4958 if (item_size <= 0)
4959 return -EBADMSG74;
4960
4961 r = message_peek_fields(m, ri, 1, item_size, &q);
4962 if (r < 0)
4963 return r;
4964
4965 l = item_size - 1;
4966 } else {
4967 r = message_peek_fields(m, ri, 1, 1, &q);
4968 if (r < 0)
4969 return r;
4970
4971 l = *(uint8_t*) q;
4972 if (l == UINT8_MAX(255))
4973 /* avoid overflow right below */
4974 return -EBADMSG74;
4975
4976 r = message_peek_fields(m, ri, 1, l+1, &q);
4977 if (r < 0)
4978 return r;
4979 }
4980
4981 if (!validate_signature(q, l))
4982 return -EBADMSG74;
4983
4984 if (ret)
4985 *ret = q;
4986
4987 return 0;
4988}
4989
4990static int message_skip_fields(
4991 sd_bus_message *m,
4992 size_t *ri,
4993 uint32_t array_size,
4994 const char **signature) {
4995
4996 size_t original_index;
4997 int r;
4998
4999 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 4999, __PRETTY_FUNCTION__); } while (0)
;
5000 assert(ri)do { if ((__builtin_expect(!!(!(ri)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ri"), "../src/libsystemd/sd-bus/bus-message.c"
, 5000, __PRETTY_FUNCTION__); } while (0)
;
5001 assert(signature)do { if ((__builtin_expect(!!(!(signature)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("signature"), "../src/libsystemd/sd-bus/bus-message.c"
, 5001, __PRETTY_FUNCTION__); } while (0)
;
5002 assert(!BUS_MESSAGE_IS_GVARIANT(m))do { if ((__builtin_expect(!!(!(!BUS_MESSAGE_IS_GVARIANT(m)))
,0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!BUS_MESSAGE_IS_GVARIANT(m)"
), "../src/libsystemd/sd-bus/bus-message.c", 5002, __PRETTY_FUNCTION__
); } while (0)
;
5003
5004 original_index = *ri;
5005
5006 for (;;) {
5007 char t;
5008 size_t l;
5009
5010 if (array_size != (uint32_t) -1 &&
5011 array_size <= *ri - original_index)
5012 return 0;
5013
5014 t = **signature;
5015 if (!t)
5016 return 0;
5017
5018 if (t == SD_BUS_TYPE_STRING) {
5019
5020 r = message_peek_field_string(m, NULL((void*)0), ri, 0, NULL((void*)0));
5021 if (r < 0)
5022 return r;
5023
5024 (*signature)++;
5025
5026 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5027
5028 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL((void*)0));
5029 if (r < 0)
5030 return r;
5031
5032 (*signature)++;
5033
5034 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5035
5036 r = message_peek_field_signature(m, ri, 0, NULL((void*)0));
5037 if (r < 0)
5038 return r;
5039
5040 (*signature)++;
5041
5042 } else if (bus_type_is_basic(t)) {
5043 ssize_t align, k;
5044
5045 align = bus_type_get_alignment(t);
5046 k = bus_type_get_size(t);
5047 assert(align > 0 && k > 0)do { if ((__builtin_expect(!!(!(align > 0 && k >
0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("align > 0 && k > 0"
), "../src/libsystemd/sd-bus/bus-message.c", 5047, __PRETTY_FUNCTION__
); } while (0)
;
5048
5049 r = message_peek_fields(m, ri, align, k, NULL((void*)0));
5050 if (r < 0)
5051 return r;
5052
5053 (*signature)++;
5054
5055 } else if (t == SD_BUS_TYPE_ARRAY) {
5056
5057 r = signature_element_length(*signature + 1, &l);
5058 if (r < 0)
5059 return r;
5060
5061 assert(l >= 1)do { if ((__builtin_expect(!!(!(l >= 1)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l >= 1"), "../src/libsystemd/sd-bus/bus-message.c"
, 5061, __PRETTY_FUNCTION__); } while (0)
;
5062 {
5063 char sig[l + 1], *s = sig;
5064 uint32_t nas;
5065 int alignment;
5066
5067 strncpy(sig, *signature + 1, l);
5068 sig[l] = '\0';
5069
5070 alignment = bus_type_get_alignment(sig[0]);
5071 if (alignment < 0)
5072 return alignment;
5073
5074 r = message_peek_field_uint32(m, ri, 0, &nas);
5075 if (r < 0)
5076 return r;
5077 if (nas > BUS_ARRAY_MAX_SIZE67108864)
5078 return -EBADMSG74;
5079
5080 r = message_peek_fields(m, ri, alignment, 0, NULL((void*)0));
5081 if (r < 0)
5082 return r;
5083
5084 r = message_skip_fields(m, ri, nas, (const char**) &s);
5085 if (r < 0)
5086 return r;
5087 }
5088
5089 (*signature) += 1 + l;
5090
5091 } else if (t == SD_BUS_TYPE_VARIANT) {
5092 const char *s;
5093
5094 r = message_peek_field_signature(m, ri, 0, &s);
5095 if (r < 0)
5096 return r;
5097
5098 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5099 if (r < 0)
5100 return r;
5101
5102 (*signature)++;
5103
5104 } else if (IN_SET(t, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY
})/sizeof(int)]; switch(t) { case SD_BUS_TYPE_STRUCT: case SD_BUS_TYPE_DICT_ENTRY
: _found = 1; break; default: break; } _found; })
) {
5105
5106 r = signature_element_length(*signature, &l);
5107 if (r < 0)
5108 return r;
5109
5110 assert(l >= 2)do { if ((__builtin_expect(!!(!(l >= 2)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l >= 2"), "../src/libsystemd/sd-bus/bus-message.c"
, 5110, __PRETTY_FUNCTION__); } while (0)
;
5111 {
5112 char sig[l + 1], *s = sig;
5113 strncpy(sig, *signature + 1, l);
5114 sig[l] = '\0';
5115
5116 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5117 if (r < 0)
5118 return r;
5119 }
5120
5121 *signature += l;
5122 } else
5123 return -EBADMSG74;
5124 }
5125}
5126
5127int bus_message_parse_fields(sd_bus_message *m) {
5128 size_t ri;
5129 int r;
5130 uint32_t unix_fds = 0;
5131 bool_Bool unix_fds_set = false0;
5132 void *offsets = NULL((void*)0);
5133 unsigned n_offsets = 0;
5134 size_t sz = 0;
5135 unsigned i = 0;
5136
5137 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5137, __PRETTY_FUNCTION__); } while (0)
;
5138
5139 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5140 char *p;
5141
5142 /* Read the signature from the end of the body variant first */
5143 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5144 if (m->footer_accessible < 1 + sz)
5145 return -EBADMSG74;
5146
5147 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5148 for (;;) {
5149 if (p < (char*) m->footer)
5150 return -EBADMSG74;
5151
5152 if (*p == 0) {
5153 char *k;
5154 size_t l;
5155
5156 /* We found the beginning of the signature
5157 * string, yay! We require the body to be a
5158 * structure, so verify it and then strip the
5159 * opening/closing brackets. */
5160
5161 l = (char*) m->footer + m->footer_accessible - p - (1 + sz);
5162 if (l < 2 ||
5163 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5164 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5165 return -EBADMSG74;
5166
5167 k = memdup_suffix0(p + 1 + 1, l - 2);
5168 if (!k)
5169 return -ENOMEM12;
5170
5171 free_and_replace(m->root_container.signature, k)({ free(m->root_container.signature); (m->root_container
.signature) = (k); (k) = ((void*)0); 0; })
;
5172 break;
5173 }
5174
5175 p--;
5176 }
5177
5178 /* Calculate the actual user body size, by removing
5179 * the trailing variant signature and struct offset
5180 * table */
5181 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5182
5183 /* Pull out the offset table for the fields array */
5184 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5185 if (sz > 0) {
5186 size_t framing;
5187 void *q;
5188
5189 ri = m->fields_size - sz;
5190 r = message_peek_fields(m, &ri, 1, sz, &q);
5191 if (r < 0)
5192 return r;
5193
5194 framing = bus_gvariant_read_word_le(q, sz);
5195 if (framing >= m->fields_size - sz)
5196 return -EBADMSG74;
5197 if ((m->fields_size - framing) % sz != 0)
5198 return -EBADMSG74;
5199
5200 ri = framing;
5201 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5202 if (r < 0)
5203 return r;
5204
5205 n_offsets = (m->fields_size - framing) / sz;
5206 }
5207 } else
5208 m->user_body_size = m->body_size;
5209
5210 ri = 0;
5211 while (ri < m->fields_size) {
5212 _cleanup_free___attribute__((cleanup(freep))) char *sig = NULL((void*)0);
5213 const char *signature;
5214 uint64_t field_type;
5215 size_t item_size = (size_t) -1;
5216
5217 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5218 uint64_t *u64;
5219
5220 if (i >= n_offsets)
5221 break;
5222
5223 if (i == 0)
5224 ri = 0;
5225 else
5226 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5227
5228 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5229 if (r < 0)
5230 return r;
5231
5232 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5233 } else {
5234 uint8_t *u8;
5235
5236 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5237 if (r < 0)
5238 return r;
5239
5240 field_type = *u8;
5241 }
5242
5243 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5244 size_t where, end;
5245 char *b;
5246 void *q;
5247
5248 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5249
5250 if (end < ri)
5251 return -EBADMSG74;
5252
5253 where = ri = ALIGN_TO(ri, 8);
5254 item_size = end - ri;
5255 r = message_peek_fields(m, &where, 1, item_size, &q);
5256 if (r < 0)
5257 return r;
5258
5259 b = memrchr(q, 0, item_size);
5260 if (!b)
5261 return -EBADMSG74;
5262
5263 sig = strndup(b+1, item_size - (b+1-(char*) q));
5264 if (!sig)
5265 return -ENOMEM12;
5266
5267 signature = sig;
5268 item_size = b - (char*) q;
5269 } else {
5270 r = message_peek_field_signature(m, &ri, 0, &signature);
5271 if (r < 0)
5272 return r;
5273 }
5274
5275 switch (field_type) {
5276
5277 case _BUS_MESSAGE_HEADER_INVALID:
5278 return -EBADMSG74;
5279
5280 case BUS_MESSAGE_HEADER_PATH:
5281
5282 if (m->path)
5283 return -EBADMSG74;
5284
5285 if (!streq(signature, "o")(strcmp((signature),("o")) == 0))
5286 return -EBADMSG74;
5287
5288 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5289 break;
5290
5291 case BUS_MESSAGE_HEADER_INTERFACE:
5292
5293 if (m->interface)
5294 return -EBADMSG74;
5295
5296 if (!streq(signature, "s")(strcmp((signature),("s")) == 0))
5297 return -EBADMSG74;
5298
5299 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5300 break;
5301
5302 case BUS_MESSAGE_HEADER_MEMBER:
5303
5304 if (m->member)
5305 return -EBADMSG74;
5306
5307 if (!streq(signature, "s")(strcmp((signature),("s")) == 0))
5308 return -EBADMSG74;
5309
5310 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5311 break;
5312
5313 case BUS_MESSAGE_HEADER_ERROR_NAME:
5314
5315 if (m->error.name)
5316 return -EBADMSG74;
5317
5318 if (!streq(signature, "s")(strcmp((signature),("s")) == 0))
5319 return -EBADMSG74;
5320
5321 r = message_peek_field_string(m, error_name_is_validinterface_name_is_valid, &ri, item_size, &m->error.name);
5322 if (r >= 0)
5323 m->error._need_free = -1;
5324
5325 break;
5326
5327 case BUS_MESSAGE_HEADER_DESTINATION:
5328
5329 if (m->destination)
5330 return -EBADMSG74;
5331
5332 if (!streq(signature, "s")(strcmp((signature),("s")) == 0))
5333 return -EBADMSG74;
5334
5335 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5336 break;
5337
5338 case BUS_MESSAGE_HEADER_SENDER:
5339
5340 if (m->sender)
5341 return -EBADMSG74;
5342
5343 if (!streq(signature, "s")(strcmp((signature),("s")) == 0))
5344 return -EBADMSG74;
5345
5346 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5347
5348 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client) {
5349 m->creds.unique_name = (char*) m->sender;
5350 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5351 }
5352
5353 break;
5354
5355 case BUS_MESSAGE_HEADER_SIGNATURE: {
5356 const char *s;
5357 char *c;
5358
5359 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5360 return -EBADMSG74;
5361
5362 if (m->root_container.signature)
5363 return -EBADMSG74;
5364
5365 if (!streq(signature, "g")(strcmp((signature),("g")) == 0))
5366 return -EBADMSG74;
5367
5368 r = message_peek_field_signature(m, &ri, item_size, &s);
5369 if (r < 0)
5370 return r;
5371
5372 c = strdup(s);
5373 if (!c)
5374 return -ENOMEM12;
5375
5376 free_and_replace(m->root_container.signature, c)({ free(m->root_container.signature); (m->root_container
.signature) = (c); (c) = ((void*)0); 0; })
;
5377 break;
5378 }
5379
5380 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5381
5382 if (m->reply_cookie != 0)
5383 return -EBADMSG74;
5384
5385 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5386 /* 64bit on dbus2 */
5387
5388 if (!streq(signature, "t")(strcmp((signature),("t")) == 0))
5389 return -EBADMSG74;
5390
5391 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5392 if (r < 0)
5393 return r;
5394 } else {
5395 /* 32bit on dbus1 */
5396 uint32_t serial;
5397
5398 if (!streq(signature, "u")(strcmp((signature),("u")) == 0))
5399 return -EBADMSG74;
5400
5401 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5402 if (r < 0)
5403 return r;
5404
5405 m->reply_cookie = serial;
5406 }
5407
5408 if (m->reply_cookie == 0)
5409 return -EBADMSG74;
5410
5411 break;
5412
5413 case BUS_MESSAGE_HEADER_UNIX_FDS:
5414 if (unix_fds_set)
5415 return -EBADMSG74;
5416
5417 if (!streq(signature, "u")(strcmp((signature),("u")) == 0))
5418 return -EBADMSG74;
5419
5420 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5421 if (r < 0)
5422 return -EBADMSG74;
5423
5424 unix_fds_set = true1;
5425 break;
5426
5427 default:
5428 if (!BUS_MESSAGE_IS_GVARIANT(m))
5429 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5430 }
5431
5432 if (r < 0)
5433 return r;
5434
5435 i++;
5436 }
5437
5438 if (m->n_fds != unix_fds)
5439 return -EBADMSG74;
5440
5441 switch (m->header->type) {
5442
5443 case SD_BUS_MESSAGE_SIGNAL:
5444 if (!m->path || !m->interface || !m->member)
5445 return -EBADMSG74;
5446
5447 if (m->reply_cookie != 0)
5448 return -EBADMSG74;
5449
5450 break;
5451
5452 case SD_BUS_MESSAGE_METHOD_CALL:
5453
5454 if (!m->path || !m->member)
5455 return -EBADMSG74;
5456
5457 if (m->reply_cookie != 0)
5458 return -EBADMSG74;
5459
5460 break;
5461
5462 case SD_BUS_MESSAGE_METHOD_RETURN:
5463
5464 if (m->reply_cookie == 0)
5465 return -EBADMSG74;
5466 break;
5467
5468 case SD_BUS_MESSAGE_METHOD_ERROR:
5469
5470 if (m->reply_cookie == 0 || !m->error.name)
5471 return -EBADMSG74;
5472 break;
5473 }
5474
5475 /* Refuse non-local messages that claim they are local */
5476 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5477 return -EBADMSG74;
5478 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5479 return -EBADMSG74;
5480 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5481 return -EBADMSG74;
5482
5483 m->root_container.end = m->user_body_size;
5484
5485 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5486 r = build_struct_offsets(
5487 m,
5488 m->root_container.signature,
5489 m->user_body_size,
5490 &m->root_container.item_size,
5491 &m->root_container.offsets,
5492 &m->root_container.n_offsets);
5493 if (r == -EINVAL22)
5494 return -EBADMSG74;
5495 if (r < 0)
5496 return r;
5497 }
5498
5499 /* Try to read the error message, but if we can't it's a non-issue */
5500 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5501 (void) sd_bus_message_read(m, "s", &m->error.message);
5502
5503 return 0;
5504}
5505
5506_public___attribute__ ((visibility("default"))) int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5507 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5507, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5508 assert_return(destination, -EINVAL)do { if (!(((__builtin_expect(!!(destination),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("destination"), "../src/libsystemd/sd-bus/bus-message.c"
, 5508, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5509 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 5509, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
5510 assert_return(!m->destination, -EEXIST)do { if (!(((__builtin_expect(!!(!m->destination),1))) ? (
1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->destination"
), "../src/libsystemd/sd-bus/bus-message.c", 5510, __PRETTY_FUNCTION__
), 0))) return (-17); } while (0)
;
5511
5512 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5513}
5514
5515_public___attribute__ ((visibility("default"))) int sd_bus_message_set_sender(sd_bus_message *m, const char *sender) {
5516 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5516, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5517 assert_return(sender, -EINVAL)do { if (!(((__builtin_expect(!!(sender),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("sender"), "../src/libsystemd/sd-bus/bus-message.c"
, 5517, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5518 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 5518, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
5519 assert_return(!m->sender, -EEXIST)do { if (!(((__builtin_expect(!!(!m->sender),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sender"
), "../src/libsystemd/sd-bus/bus-message.c", 5519, __PRETTY_FUNCTION__
), 0))) return (-17); } while (0)
;
5520
5521 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5522}
5523
5524int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5525 size_t total;
5526 void *p, *e;
5527 size_t i;
5528 struct bus_body_part *part;
5529
5530 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5530, __PRETTY_FUNCTION__); } while (0)
;
5531 assert(buffer)do { if ((__builtin_expect(!!(!(buffer)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("buffer"), "../src/libsystemd/sd-bus/bus-message.c"
, 5531, __PRETTY_FUNCTION__); } while (0)
;
5532 assert(sz)do { if ((__builtin_expect(!!(!(sz)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("sz"), "../src/libsystemd/sd-bus/bus-message.c"
, 5532, __PRETTY_FUNCTION__); } while (0)
;
5533
5534 total = BUS_MESSAGE_SIZE(m);
5535
5536 p = malloc(total);
5537 if (!p)
5538 return -ENOMEM12;
5539
5540 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5541 MESSAGE_FOREACH_PART(part, i, m)for ((i) = 0, (part) = &(m)->body; (i) < (m)->n_body_parts
; (i)++, (part) = (part)->next)
5542 e = mempcpy(e, part->data, part->size);
5543
5544 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p))do { if ((__builtin_expect(!!(!(total == (size_t) ((uint8_t*)
e - (uint8_t*) p))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("total == (size_t) ((uint8_t*) e - (uint8_t*) p)"), "../src/libsystemd/sd-bus/bus-message.c"
, 5544, __PRETTY_FUNCTION__); } while (0)
;
5545
5546 *buffer = p;
5547 *sz = total;
5548
5549 return 0;
5550}
5551
5552int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5553 const char *s;
5554 int r;
5555
5556 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5556, __PRETTY_FUNCTION__); } while (0)
;
5557 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/libsystemd/sd-bus/bus-message.c"
, 5557, __PRETTY_FUNCTION__); } while (0)
;
5558
5559 r = sd_bus_message_enter_container(m, 'a', "s");
5560 if (r <= 0)
5561 return r;
5562
5563 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5564 r = strv_extend(l, s);
5565 if (r < 0)
5566 return r;
5567 }
5568 if (r < 0)
5569 return r;
5570
5571 r = sd_bus_message_exit_container(m);
5572 if (r < 0)
5573 return r;
5574
5575 return 1;
5576}
5577
5578_public___attribute__ ((visibility("default"))) int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5579 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **strv = NULL((void*)0);
5580 int r;
5581
5582 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5582, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5583 assert_return(m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 5583, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
5584 assert_return(l, -EINVAL)do { if (!(((__builtin_expect(!!(l),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/libsystemd/sd-bus/bus-message.c"
, 5584, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5585
5586 r = bus_message_read_strv_extend(m, &strv);
5587 if (r <= 0)
5588 return r;
5589
5590 *l = TAKE_PTR(strv)({ typeof(strv) _ptr_ = (strv); (strv) = ((void*)0); _ptr_; }
)
;
5591 return 1;
5592}
5593
5594static int bus_message_get_arg_skip(
5595 sd_bus_message *m,
5596 unsigned i,
5597 char *_type,
5598 const char **_contents) {
5599
5600 unsigned j;
5601 int r;
5602
5603 r = sd_bus_message_rewind(m, true1);
5604 if (r < 0)
5605 return r;
5606
5607 for (j = 0;; j++) {
5608 const char *contents;
5609 char type;
5610
5611 r = sd_bus_message_peek_type(m, &type, &contents);
5612 if (r < 0)
5613 return r;
5614 if (r == 0)
5615 return -ENXIO6;
5616
5617 /* Don't match against arguments after the first one we don't understand */
5618 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE})/sizeof(int)]; switch(type) { case SD_BUS_TYPE_STRING
: case SD_BUS_TYPE_OBJECT_PATH: case SD_BUS_TYPE_SIGNATURE: _found
= 1; break; default: break; } _found; })
&&
5619 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")(!!strv_find((((char**) ((const char*[]) { "s", "o", "g", ((void
*)0) }))), (contents)))
))
5620 return -ENXIO6;
5621
5622 if (j >= i) {
5623 if (_contents)
5624 *_contents = contents;
5625 if (_type)
5626 *_type = type;
5627 return 0;
5628 }
5629
5630 r = sd_bus_message_skip(m, NULL((void*)0));
5631 if (r < 0)
5632 return r;
5633 }
5634
5635}
5636
5637int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5638 char type;
5639 int r;
5640
5641 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5641, __PRETTY_FUNCTION__); } while (0)
;
5642 assert(str)do { if ((__builtin_expect(!!(!(str)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("str"), "../src/libsystemd/sd-bus/bus-message.c"
, 5642, __PRETTY_FUNCTION__); } while (0)
;
5643
5644 r = bus_message_get_arg_skip(m, i, &type, NULL((void*)0));
5645 if (r < 0)
5646 return r;
5647
5648 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE})/sizeof(int)]; switch(type) { case SD_BUS_TYPE_STRING
: case SD_BUS_TYPE_OBJECT_PATH: case SD_BUS_TYPE_SIGNATURE: _found
= 1; break; default: break; } _found; })
)
5649 return -ENXIO6;
5650
5651 return sd_bus_message_read_basic(m, type, str);
5652}
5653
5654int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5655 const char *contents;
5656 char type;
5657 int r;
5658
5659 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5659, __PRETTY_FUNCTION__); } while (0)
;
5660 assert(strv)do { if ((__builtin_expect(!!(!(strv)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("strv"), "../src/libsystemd/sd-bus/bus-message.c"
, 5660, __PRETTY_FUNCTION__); } while (0)
;
5661
5662 r = bus_message_get_arg_skip(m, i, &type, &contents);
5663 if (r < 0)
5664 return r;
5665
5666 if (type != SD_BUS_TYPE_ARRAY)
5667 return -ENXIO6;
5668 if (!STR_IN_SET(contents, "s", "o", "g")(!!strv_find((((char**) ((const char*[]) { "s", "o", "g", ((void
*)0) }))), (contents)))
)
5669 return -ENXIO6;
5670
5671 return sd_bus_message_read_strv(m, strv);
5672}
5673
5674_public___attribute__ ((visibility("default"))) int sd_bus_message_get_errno(sd_bus_message *m) {
5675 assert_return(m, EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5675, __PRETTY_FUNCTION__), 0))) return (22); } while (0)
;
5676
5677 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5678 return 0;
5679
5680 return sd_bus_error_get_errno(&m->error);
5681}
5682
5683_public___attribute__ ((visibility("default"))) const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5684 struct bus_container *c;
5685
5686 assert_return(m, NULL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5686, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
5687
5688 c = complete ? &m->root_container : message_get_last_container(m);
5689 return strempty(c->signature);
5690}
5691
5692_public___attribute__ ((visibility("default"))) int sd_bus_message_is_empty(sd_bus_message *m) {
5693 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5693, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5694
5695 return isempty(m->root_container.signature);
5696}
5697
5698_public___attribute__ ((visibility("default"))) int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5699 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5699, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5700
5701 return streq(strempty(m->root_container.signature), strempty(signature))(strcmp((strempty(m->root_container.signature)),(strempty(
signature))) == 0)
;
5702}
5703
5704_public___attribute__ ((visibility("default"))) int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5705 bool_Bool done_something = false0;
5706 int r;
5707
5708 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5708, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5709 assert_return(source, -EINVAL)do { if (!(((__builtin_expect(!!(source),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("source"), "../src/libsystemd/sd-bus/bus-message.c"
, 5709, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5710 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 5710, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
5711 assert_return(source->sealed, -EPERM)do { if (!(((__builtin_expect(!!(source->sealed),1))) ? (1
) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("source->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 5711, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
5712
5713 do {
5714 const char *contents;
5715 char type;
5716 union {
5717 uint8_t u8;
5718 uint16_t u16;
5719 int16_t s16;
5720 uint32_t u32;
5721 int32_t s32;
5722 uint64_t u64;
5723 int64_t s64;
5724 double d64;
5725 const char *string;
5726 int i;
5727 } basic;
5728
5729 r = sd_bus_message_peek_type(source, &type, &contents);
5730 if (r < 0)
5731 return r;
5732 if (r == 0)
5733 break;
5734
5735 done_something = true1;
5736
5737 if (bus_type_is_container(type) > 0) {
5738
5739 r = sd_bus_message_enter_container(source, type, contents);
5740 if (r < 0)
5741 return r;
5742
5743 r = sd_bus_message_open_container(m, type, contents);
5744 if (r < 0)
5745 return r;
5746
5747 r = sd_bus_message_copy(m, source, true1);
5748 if (r < 0)
5749 return r;
5750
5751 r = sd_bus_message_close_container(m);
5752 if (r < 0)
5753 return r;
5754
5755 r = sd_bus_message_exit_container(source);
5756 if (r < 0)
5757 return r;
5758
5759 continue;
5760 }
5761
5762 r = sd_bus_message_read_basic(source, type, &basic);
5763 if (r < 0)
5764 return r;
5765
5766 assert(r > 0)do { if ((__builtin_expect(!!(!(r > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("r > 0"), "../src/libsystemd/sd-bus/bus-message.c"
, 5766, __PRETTY_FUNCTION__); } while (0)
;
5767
5768 if (IN_SET(type, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE, SD_BUS_TYPE_STRING)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE
, SD_BUS_TYPE_STRING})/sizeof(int)]; switch(type) { case SD_BUS_TYPE_OBJECT_PATH
: case SD_BUS_TYPE_SIGNATURE: case SD_BUS_TYPE_STRING: _found
= 1; break; default: break; } _found; })
)
5769 r = sd_bus_message_append_basic(m, type, basic.string);
5770 else
5771 r = sd_bus_message_append_basic(m, type, &basic);
5772
5773 if (r < 0)
5774 return r;
5775
5776 } while (all);
5777
5778 return done_something;
5779}
5780
5781_public___attribute__ ((visibility("default"))) int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5782 const char *c;
5783 char t;
5784 int r;
5785
5786 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5786, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5787 assert_return(m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 5787, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
5788 assert_return(!type || bus_type_is_valid(type), -EINVAL)do { if (!(((__builtin_expect(!!(!type || bus_type_is_valid(type
)),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("!type || bus_type_is_valid(type)"), "../src/libsystemd/sd-bus/bus-message.c"
, 5788, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5789 assert_return(!contents || signature_is_valid(contents, true), -EINVAL)do { if (!(((__builtin_expect(!!(!contents || signature_is_valid
(contents, 1)),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("!contents || signature_is_valid(contents, true)"), "../src/libsystemd/sd-bus/bus-message.c"
, 5789, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5790 assert_return(type || contents, -EINVAL)do { if (!(((__builtin_expect(!!(type || contents),1))) ? (1)
: (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("type || contents"
), "../src/libsystemd/sd-bus/bus-message.c", 5790, __PRETTY_FUNCTION__
), 0))) return (-22); } while (0)
;
5791 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL)do { if (!(((__builtin_expect(!!(!contents || !type || bus_type_is_container
(type)),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("!contents || !type || bus_type_is_container(type)"), "../src/libsystemd/sd-bus/bus-message.c"
, 5791, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5792
5793 r = sd_bus_message_peek_type(m, &t, &c);
5794 if (r <= 0)
5795 return r;
5796
5797 if (type != 0 && type != t)
5798 return 0;
5799
5800 if (contents && !streq_ptr(contents, c))
5801 return 0;
5802
5803 return 1;
5804}
5805
5806_public___attribute__ ((visibility("default"))) sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5807 assert_return(m, NULL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5807, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while
(0)
;
5808
5809 return m->bus;
5810}
5811
5812int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5813 _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *n = NULL((void*)0);
5814 usec_t timeout;
5815 int r;
5816
5817 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-message.c"
, 5817, __PRETTY_FUNCTION__); } while (0)
;
5818 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5818, __PRETTY_FUNCTION__); } while (0)
;
5819 assert(*m)do { if ((__builtin_expect(!!(!(*m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("*m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5819, __PRETTY_FUNCTION__); } while (0)
;
5820
5821 switch ((*m)->header->type) {
5822
5823 case SD_BUS_MESSAGE_SIGNAL:
5824 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5825 if (r < 0)
5826 return r;
5827
5828 break;
5829
5830 case SD_BUS_MESSAGE_METHOD_CALL:
5831 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5832 if (r < 0)
5833 return r;
5834
5835 break;
5836
5837 case SD_BUS_MESSAGE_METHOD_RETURN:
5838 case SD_BUS_MESSAGE_METHOD_ERROR:
5839
5840 r = sd_bus_message_new(bus, &n, (*m)->header->type);
5841 if (r < 0)
5842 return -ENOMEM12;
5843
5844 assert(n)do { if ((__builtin_expect(!!(!(n)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n"), "../src/libsystemd/sd-bus/bus-message.c"
, 5844, __PRETTY_FUNCTION__); } while (0)
;
5845
5846 n->reply_cookie = (*m)->reply_cookie;
5847
5848 r = message_append_reply_cookie(n, n->reply_cookie);
5849 if (r < 0)
5850 return r;
5851
5852 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5853 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5854 if (r < 0)
5855 return r;
5856
5857 n->error._need_free = -1;
5858 }
5859
5860 break;
5861
5862 default:
5863 return -EINVAL22;
5864 }
5865
5866 if ((*m)->destination && !n->destination) {
5867 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5868 if (r < 0)
5869 return r;
5870 }
5871
5872 if ((*m)->sender && !n->sender) {
5873 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5874 if (r < 0)
5875 return r;
5876 }
5877
5878 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5879
5880 r = sd_bus_message_copy(n, *m, true1);
5881 if (r < 0)
5882 return r;
5883
5884 timeout = (*m)->timeout;
5885 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5886 timeout = BUS_DEFAULT_TIMEOUT((usec_t) (25 * ((usec_t) 1000000ULL)));
5887
5888 r = sd_bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5889 if (r < 0)
5890 return r;
5891
5892 sd_bus_message_unref(*m);
5893 *m = TAKE_PTR(n)({ typeof(n) _ptr_ = (n); (n) = ((void*)0); _ptr_; });
5894
5895 return 0;
5896}
5897
5898int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5899 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5899, __PRETTY_FUNCTION__); } while (0)
;
5900 assert(sender)do { if ((__builtin_expect(!!(!(sender)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("sender"), "../src/libsystemd/sd-bus/bus-message.c"
, 5900, __PRETTY_FUNCTION__); } while (0)
;
5901
5902 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 5902, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
5903 assert_return(!m->sender, -EPERM)do { if (!(((__builtin_expect(!!(!m->sender),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sender"
), "../src/libsystemd/sd-bus/bus-message.c", 5903, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
5904
5905 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5906}
5907
5908_public___attribute__ ((visibility("default"))) int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5909 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5909, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5910 assert_return(priority, -EINVAL)do { if (!(((__builtin_expect(!!(priority),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("priority"), "../src/libsystemd/sd-bus/bus-message.c"
, 5910, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5911
5912 *priority = m->priority;
5913 return 0;
5914}
5915
5916_public___attribute__ ((visibility("default"))) int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5917 assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-message.c"
, 5917, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
5918 assert_return(!m->sealed, -EPERM)do { if (!(((__builtin_expect(!!(!m->sealed),1))) ? (1) : (
log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!m->sealed"
), "../src/libsystemd/sd-bus/bus-message.c", 5918, __PRETTY_FUNCTION__
), 0))) return (-1); } while (0)
;
5919
5920 m->priority = priority;
5921 return 0;
5922}