1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-marshal-header.c Managing marshaling/demarshaling of message headers
3 *
4 * Copyright (C) 2005 Red Hat, Inc.
5 *
6 * Licensed under the Academic Free License version 2.1
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24 #include "dbus/dbus-shared.h"
25 #include "dbus-marshal-header.h"
26 #include "dbus-marshal-recursive.h"
27 #include "dbus-marshal-byteswap.h"
28
29 /**
30 * @addtogroup DBusMarshal
31 *
32 * @{
33 */
34
35
36 /* Not thread locked, but strictly const/read-only so should be OK
37 */
38 /** Static #DBusString containing the signature of a message header */
39 _DBUS_STRING_DEFINE_STATIC(_dbus_header_signature_str, DBUS_HEADER_SIGNATURE);
40 /** Static #DBusString containing the local interface */
41 _DBUS_STRING_DEFINE_STATIC(_dbus_local_interface_str, DBUS_INTERFACE_LOCAL);
42 /** Static #DBusString containing the local path */
43 _DBUS_STRING_DEFINE_STATIC(_dbus_local_path_str, DBUS_PATH_LOCAL);
44
45 /** Offset from start of _dbus_header_signature_str to the signature of the fields array */
46 #define FIELDS_ARRAY_SIGNATURE_OFFSET 6
47 /** Offset from start of _dbus_header_signature_str to the signature of an element of the fields array */
48 #define FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET 7
49
50
51 /** Offset to byte order from start of header */
52 #define BYTE_ORDER_OFFSET 0
53 /** Offset to type from start of header */
54 #define TYPE_OFFSET 1
55 /** Offset to flags from start of header */
56 #define FLAGS_OFFSET 2
57 /** Offset to version from start of header */
58 #define VERSION_OFFSET 3
59 /** Offset to body length from start of header */
60 #define BODY_LENGTH_OFFSET 4
61 /** Offset to client serial from start of header */
62 #define SERIAL_OFFSET 8
63 /** Offset to fields array length from start of header */
64 #define FIELDS_ARRAY_LENGTH_OFFSET 12
65 /** Offset to first field in header */
66 #define FIRST_FIELD_OFFSET 16
67
68 typedef struct
69 {
70 unsigned char code; /**< the field code */
71 unsigned char type; /**< the value type */
72 } HeaderFieldType;
73
74 static const HeaderFieldType
75 _dbus_header_field_types[DBUS_HEADER_FIELD_LAST+1] = {
76 { DBUS_HEADER_FIELD_INVALID, DBUS_TYPE_INVALID },
77 { DBUS_HEADER_FIELD_PATH, DBUS_TYPE_OBJECT_PATH },
78 { DBUS_HEADER_FIELD_INTERFACE, DBUS_TYPE_STRING },
79 { DBUS_HEADER_FIELD_MEMBER, DBUS_TYPE_STRING },
80 { DBUS_HEADER_FIELD_ERROR_NAME, DBUS_TYPE_STRING },
81 { DBUS_HEADER_FIELD_REPLY_SERIAL, DBUS_TYPE_UINT32 },
82 { DBUS_HEADER_FIELD_DESTINATION, DBUS_TYPE_STRING },
83 { DBUS_HEADER_FIELD_SENDER, DBUS_TYPE_STRING },
84 { DBUS_HEADER_FIELD_SIGNATURE, DBUS_TYPE_SIGNATURE }
85 };
86
87 /** Macro to look up the correct type for a field */
88 #define EXPECTED_TYPE_OF_FIELD(field) (_dbus_header_field_types[field].type)
89
90 /** The most padding we could ever need for a header */
91 #define MAX_POSSIBLE_HEADER_PADDING 7
92 static dbus_bool_t
reserve_header_padding(DBusHeader * header)93 reserve_header_padding (DBusHeader *header)
94 {
95 _dbus_assert (header->padding <= MAX_POSSIBLE_HEADER_PADDING);
96
97 if (!_dbus_string_lengthen (&header->data,
98 MAX_POSSIBLE_HEADER_PADDING - header->padding))
99 return FALSE;
100 header->padding = MAX_POSSIBLE_HEADER_PADDING;
101 return TRUE;
102 }
103
104 static void
correct_header_padding(DBusHeader * header)105 correct_header_padding (DBusHeader *header)
106 {
107 int unpadded_len;
108
109 _dbus_assert (header->padding == 7);
110
111 _dbus_string_shorten (&header->data, header->padding);
112 unpadded_len = _dbus_string_get_length (&header->data);
113
114 if (!_dbus_string_align_length (&header->data, 8))
115 _dbus_assert_not_reached ("couldn't pad header though enough padding was preallocated");
116
117 header->padding = _dbus_string_get_length (&header->data) - unpadded_len;
118 }
119
120 /** Compute the end of the header, ignoring padding */
121 #define HEADER_END_BEFORE_PADDING(header) \
122 (_dbus_string_get_length (&(header)->data) - (header)->padding)
123
124 /**
125 * Invalidates all fields in the cache. This may be used when the
126 * cache is totally uninitialized (contains junk) so should not
127 * look at what's in there now.
128 *
129 * @param header the header
130 */
131 static void
_dbus_header_cache_invalidate_all(DBusHeader * header)132 _dbus_header_cache_invalidate_all (DBusHeader *header)
133 {
134 int i;
135
136 i = 0;
137 while (i <= DBUS_HEADER_FIELD_LAST)
138 {
139 header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_UNKNOWN;
140 ++i;
141 }
142 }
143
144 /**
145 * Caches one field
146 *
147 * @param header the header
148 * @param field_code the field
149 * @param variant_reader the reader for the variant in the field
150 */
151 static void
_dbus_header_cache_one(DBusHeader * header,int field_code,DBusTypeReader * variant_reader)152 _dbus_header_cache_one (DBusHeader *header,
153 int field_code,
154 DBusTypeReader *variant_reader)
155 {
156 header->fields[field_code].value_pos =
157 _dbus_type_reader_get_value_pos (variant_reader);
158
159 #if 0
160 _dbus_verbose ("cached value_pos %d for field %d\n",
161 header->fields[field_code].value_pos, field_code)
162 #endif
163 }
164
165 /**
166 * Revalidates the fields cache
167 *
168 * @param header the header
169 */
170 static void
_dbus_header_cache_revalidate(DBusHeader * header)171 _dbus_header_cache_revalidate (DBusHeader *header)
172 {
173 DBusTypeReader array;
174 DBusTypeReader reader;
175 int i;
176
177 i = 0;
178 while (i <= DBUS_HEADER_FIELD_LAST)
179 {
180 header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
181 ++i;
182 }
183
184 _dbus_type_reader_init (&reader,
185 header->byte_order,
186 &_dbus_header_signature_str,
187 FIELDS_ARRAY_SIGNATURE_OFFSET,
188 &header->data,
189 FIELDS_ARRAY_LENGTH_OFFSET);
190
191 _dbus_type_reader_recurse (&reader, &array);
192
193 while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
194 {
195 DBusTypeReader sub;
196 DBusTypeReader variant;
197 unsigned char field_code;
198
199 _dbus_type_reader_recurse (&array, &sub);
200
201 _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
202 _dbus_type_reader_read_basic (&sub, &field_code);
203
204 /* Unknown fields should be ignored */
205 if (field_code > DBUS_HEADER_FIELD_LAST)
206 goto next_field;
207
208 _dbus_type_reader_next (&sub);
209
210 _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_VARIANT);
211 _dbus_type_reader_recurse (&sub, &variant);
212
213 _dbus_header_cache_one (header, field_code, &variant);
214
215 next_field:
216 _dbus_type_reader_next (&array);
217 }
218 }
219
220 /**
221 * Checks for a field, updating the cache if required.
222 *
223 * @param header the header
224 * @param field the field to check
225 * @returns #FALSE if the field doesn't exist
226 */
227 static dbus_bool_t
_dbus_header_cache_check(DBusHeader * header,int field)228 _dbus_header_cache_check (DBusHeader *header,
229 int field)
230 {
231 _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
232
233 if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
234 _dbus_header_cache_revalidate (header);
235
236 if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT)
237 return FALSE;
238
239 return TRUE;
240 }
241
242 /**
243 * Checks whether a field is known not to exist. It may exist
244 * even if it's not known to exist.
245 *
246 * @param header the header
247 * @param field the field to check
248 * @returns #FALSE if the field definitely doesn't exist
249 */
250 static dbus_bool_t
_dbus_header_cache_known_nonexistent(DBusHeader * header,int field)251 _dbus_header_cache_known_nonexistent (DBusHeader *header,
252 int field)
253 {
254 _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
255
256 return (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT);
257 }
258
259 /**
260 * Writes a struct of { byte, variant } with the given basic type.
261 *
262 * @param writer the writer (should be ready to write a struct)
263 * @param type the type of the value
264 * @param value the value as for _dbus_marshal_set_basic()
265 * @returns #FALSE if no memory
266 */
267 static dbus_bool_t
write_basic_field(DBusTypeWriter * writer,int field,int type,const void * value)268 write_basic_field (DBusTypeWriter *writer,
269 int field,
270 int type,
271 const void *value)
272 {
273 DBusTypeWriter sub;
274 DBusTypeWriter variant;
275 int start;
276 int padding;
277 unsigned char field_byte;
278 DBusString contained_type;
279 char buf[2];
280
281 start = writer->value_pos;
282 padding = _dbus_string_get_length (writer->value_str) - start;
283
284 if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT,
285 NULL, 0, &sub))
286 goto append_failed;
287
288 field_byte = field;
289 if (!_dbus_type_writer_write_basic (&sub, DBUS_TYPE_BYTE,
290 &field_byte))
291 goto append_failed;
292
293 buf[0] = type;
294 buf[1] = '\0';
295 _dbus_string_init_const_len (&contained_type, buf, 1);
296
297 if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_VARIANT,
298 &contained_type, 0, &variant))
299 goto append_failed;
300
301 if (!_dbus_type_writer_write_basic (&variant, type, value))
302 goto append_failed;
303
304 if (!_dbus_type_writer_unrecurse (&sub, &variant))
305 goto append_failed;
306
307 if (!_dbus_type_writer_unrecurse (writer, &sub))
308 goto append_failed;
309
310 return TRUE;
311
312 append_failed:
313 _dbus_string_delete (writer->value_str,
314 start,
315 _dbus_string_get_length (writer->value_str) - start - padding);
316 return FALSE;
317 }
318
319 /**
320 * Sets a struct of { byte, variant } with the given basic type.
321 *
322 * @param reader the reader (should be iterating over the array pointing at the field to set)
323 * @param type the type of the value
324 * @param value the value as for _dbus_marshal_set_basic()
325 * @param realign_root where to realign from
326 * @returns #FALSE if no memory
327 */
328 static dbus_bool_t
set_basic_field(DBusTypeReader * reader,int field,int type,const void * value,const DBusTypeReader * realign_root)329 set_basic_field (DBusTypeReader *reader,
330 int field,
331 int type,
332 const void *value,
333 const DBusTypeReader *realign_root)
334 {
335 DBusTypeReader sub;
336 DBusTypeReader variant;
337
338 _dbus_type_reader_recurse (reader, &sub);
339
340 _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
341 #ifndef DBUS_DISABLE_ASSERT
342 {
343 unsigned char v_BYTE;
344 _dbus_type_reader_read_basic (&sub, &v_BYTE);
345 _dbus_assert (((int) v_BYTE) == field);
346 }
347 #endif
348
349 if (!_dbus_type_reader_next (&sub))
350 _dbus_assert_not_reached ("no variant field?");
351
352 _dbus_type_reader_recurse (&sub, &variant);
353 _dbus_assert (_dbus_type_reader_get_current_type (&variant) == type);
354
355 if (!_dbus_type_reader_set_basic (&variant, value, realign_root))
356 return FALSE;
357
358 return TRUE;
359 }
360
361 /**
362 * Gets the type of the message.
363 *
364 * @param header the header
365 * @returns the type
366 */
367 int
_dbus_header_get_message_type(DBusHeader * header)368 _dbus_header_get_message_type (DBusHeader *header)
369 {
370 int type;
371
372 type = _dbus_string_get_byte (&header->data, TYPE_OFFSET);
373 _dbus_assert (type != DBUS_MESSAGE_TYPE_INVALID);
374
375 return type;
376 }
377
378 /**
379 * Sets the serial number of a header. This can only be done once on
380 * a header.
381 *
382 * @param header the header
383 * @param serial the serial
384 */
385 void
_dbus_header_set_serial(DBusHeader * header,dbus_uint32_t serial)386 _dbus_header_set_serial (DBusHeader *header,
387 dbus_uint32_t serial)
388 {
389 /* we use this function to set the serial on outgoing
390 * messages, and to reset the serial in dbus_message_copy;
391 * this assertion should catch a double-set on outgoing.
392 */
393 _dbus_assert (_dbus_header_get_serial (header) == 0 ||
394 serial == 0);
395
396 _dbus_marshal_set_uint32 (&header->data,
397 SERIAL_OFFSET,
398 serial,
399 header->byte_order);
400 }
401
402 /**
403 * See dbus_message_get_serial()
404 *
405 * @param header the header
406 * @returns the client serial
407 */
408 dbus_uint32_t
_dbus_header_get_serial(DBusHeader * header)409 _dbus_header_get_serial (DBusHeader *header)
410 {
411 return _dbus_marshal_read_uint32 (&header->data,
412 SERIAL_OFFSET,
413 header->byte_order,
414 NULL);
415 }
416
417 /**
418 * Re-initializes a header that was previously initialized and never
419 * freed. After this, to make the header valid you have to call
420 * _dbus_header_create().
421 *
422 * @param header header to re-initialize
423 * @param byte_order byte order of the header
424 */
425 void
_dbus_header_reinit(DBusHeader * header,int byte_order)426 _dbus_header_reinit (DBusHeader *header,
427 int byte_order)
428 {
429 _dbus_string_set_length (&header->data, 0);
430
431 header->byte_order = byte_order;
432 header->padding = 0;
433
434 _dbus_header_cache_invalidate_all (header);
435 }
436
437 /**
438 * Initializes a header, but doesn't prepare it for use;
439 * to make the header valid, you have to call _dbus_header_create().
440 *
441 * @param header header to initialize
442 * @param byte_order byte order of the header
443 * @returns #FALSE if not enough memory
444 */
445 dbus_bool_t
_dbus_header_init(DBusHeader * header,int byte_order)446 _dbus_header_init (DBusHeader *header,
447 int byte_order)
448 {
449 if (!_dbus_string_init_preallocated (&header->data, 32))
450 return FALSE;
451
452 _dbus_header_reinit (header, byte_order);
453
454 return TRUE;
455 }
456
457 /**
458 * Frees a header.
459 *
460 * @param header the header
461 */
462 void
_dbus_header_free(DBusHeader * header)463 _dbus_header_free (DBusHeader *header)
464 {
465 _dbus_string_free (&header->data);
466 }
467
468 /**
469 * Initializes dest with a copy of the given header.
470 * Resets the message serial to 0 on the copy.
471 *
472 * @param header header to copy
473 * @param dest destination for copy
474 * @returns #FALSE if not enough memory
475 */
476 dbus_bool_t
_dbus_header_copy(const DBusHeader * header,DBusHeader * dest)477 _dbus_header_copy (const DBusHeader *header,
478 DBusHeader *dest)
479 {
480 *dest = *header;
481
482 if (!_dbus_string_init_preallocated (&dest->data,
483 _dbus_string_get_length (&header->data)))
484 return FALSE;
485
486 if (!_dbus_string_copy (&header->data, 0, &dest->data, 0))
487 {
488 _dbus_string_free (&dest->data);
489 return FALSE;
490 }
491
492 /* Reset the serial */
493 _dbus_header_set_serial (dest, 0);
494
495 return TRUE;
496 }
497
498 /**
499 * Fills in the primary fields of the header, so the header is ready
500 * for use. #NULL may be specified for some or all of the fields to
501 * avoid adding those fields. Some combinations of fields don't make
502 * sense, and passing them in will trigger an assertion failure.
503 *
504 * @param header the header
505 * @param message_type the message type
506 * @param destination destination field or #NULL
507 * @param path path field or #NULL
508 * @param interface interface field or #NULL
509 * @param member member field or #NULL
510 * @param error_name error name or #NULL
511 * @returns #FALSE if not enough memory
512 */
513 dbus_bool_t
_dbus_header_create(DBusHeader * header,int message_type,const char * destination,const char * path,const char * interface,const char * member,const char * error_name)514 _dbus_header_create (DBusHeader *header,
515 int message_type,
516 const char *destination,
517 const char *path,
518 const char *interface,
519 const char *member,
520 const char *error_name)
521 {
522 unsigned char v_BYTE;
523 dbus_uint32_t v_UINT32;
524 DBusTypeWriter writer;
525 DBusTypeWriter array;
526
527 _dbus_assert (((interface || message_type != DBUS_MESSAGE_TYPE_SIGNAL) && member) ||
528 (error_name) ||
529 !(interface || member || error_name));
530 _dbus_assert (_dbus_string_get_length (&header->data) == 0);
531
532 if (!reserve_header_padding (header))
533 return FALSE;
534
535 _dbus_type_writer_init_values_only (&writer, header->byte_order,
536 &_dbus_header_signature_str, 0,
537 &header->data,
538 HEADER_END_BEFORE_PADDING (header));
539
540 v_BYTE = header->byte_order;
541 if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
542 &v_BYTE))
543 goto oom;
544
545 v_BYTE = message_type;
546 if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
547 &v_BYTE))
548 goto oom;
549
550 v_BYTE = 0; /* flags */
551 if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
552 &v_BYTE))
553 goto oom;
554
555 v_BYTE = DBUS_MAJOR_PROTOCOL_VERSION;
556 if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
557 &v_BYTE))
558 goto oom;
559
560 v_UINT32 = 0; /* body length */
561 if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32,
562 &v_UINT32))
563 goto oom;
564
565 v_UINT32 = 0; /* serial */
566 if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32,
567 &v_UINT32))
568 goto oom;
569
570 if (!_dbus_type_writer_recurse (&writer, DBUS_TYPE_ARRAY,
571 &_dbus_header_signature_str,
572 FIELDS_ARRAY_SIGNATURE_OFFSET,
573 &array))
574 goto oom;
575
576 /* Marshal all the fields (Marshall Fields?) */
577
578 if (path != NULL)
579 {
580 if (!write_basic_field (&array,
581 DBUS_HEADER_FIELD_PATH,
582 DBUS_TYPE_OBJECT_PATH,
583 &path))
584 goto oom;
585 }
586
587 if (destination != NULL)
588 {
589 if (!write_basic_field (&array,
590 DBUS_HEADER_FIELD_DESTINATION,
591 DBUS_TYPE_STRING,
592 &destination))
593 goto oom;
594 }
595
596 if (interface != NULL)
597 {
598 if (!write_basic_field (&array,
599 DBUS_HEADER_FIELD_INTERFACE,
600 DBUS_TYPE_STRING,
601 &interface))
602 goto oom;
603 }
604
605 if (member != NULL)
606 {
607 if (!write_basic_field (&array,
608 DBUS_HEADER_FIELD_MEMBER,
609 DBUS_TYPE_STRING,
610 &member))
611 goto oom;
612 }
613
614 if (error_name != NULL)
615 {
616 if (!write_basic_field (&array,
617 DBUS_HEADER_FIELD_ERROR_NAME,
618 DBUS_TYPE_STRING,
619 &error_name))
620 goto oom;
621 }
622
623 if (!_dbus_type_writer_unrecurse (&writer, &array))
624 goto oom;
625
626 correct_header_padding (header);
627
628 return TRUE;
629
630 oom:
631 _dbus_string_delete (&header->data, 0,
632 _dbus_string_get_length (&header->data) - header->padding);
633 correct_header_padding (header);
634
635 return FALSE;
636 }
637
638 /**
639 * Given data long enough to contain the length of the message body
640 * and the fields array, check whether the data is long enough to
641 * contain the entire message (assuming the claimed lengths are
642 * accurate). Also checks that the lengths are in sanity parameters.
643 *
644 * @param max_message_length maximum length of a valid message
645 * @param validity return location for why the data is invalid if it is
646 * @param byte_order return location for byte order
647 * @param fields_array_len return location for claimed fields array length
648 * @param header_len return location for claimed header length
649 * @param body_len return location for claimed body length
650 * @param str the data
651 * @param start start of data, 8-aligned
652 * @param len length of data
653 * @returns #TRUE if the data is long enough for the claimed length, and the lengths were valid
654 */
655 dbus_bool_t
_dbus_header_have_message_untrusted(int max_message_length,DBusValidity * validity,int * byte_order,int * fields_array_len,int * header_len,int * body_len,const DBusString * str,int start,int len)656 _dbus_header_have_message_untrusted (int max_message_length,
657 DBusValidity *validity,
658 int *byte_order,
659 int *fields_array_len,
660 int *header_len,
661 int *body_len,
662 const DBusString *str,
663 int start,
664 int len)
665
666 {
667 dbus_uint32_t header_len_unsigned;
668 dbus_uint32_t fields_array_len_unsigned;
669 dbus_uint32_t body_len_unsigned;
670
671 _dbus_assert (start >= 0);
672 _dbus_assert (start < _DBUS_INT32_MAX / 2);
673 _dbus_assert (len >= 0);
674
675 _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8));
676
677 *byte_order = _dbus_string_get_byte (str, start + BYTE_ORDER_OFFSET);
678
679 if (*byte_order != DBUS_LITTLE_ENDIAN && *byte_order != DBUS_BIG_ENDIAN)
680 {
681 *validity = DBUS_INVALID_BAD_BYTE_ORDER;
682 return FALSE;
683 }
684
685 _dbus_assert (FIELDS_ARRAY_LENGTH_OFFSET + 4 <= len);
686 fields_array_len_unsigned = _dbus_marshal_read_uint32 (str, start + FIELDS_ARRAY_LENGTH_OFFSET,
687 *byte_order, NULL);
688
689 if (fields_array_len_unsigned > (unsigned) max_message_length)
690 {
691 *validity = DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH;
692 return FALSE;
693 }
694
695 _dbus_assert (BODY_LENGTH_OFFSET + 4 < len);
696 body_len_unsigned = _dbus_marshal_read_uint32 (str, start + BODY_LENGTH_OFFSET,
697 *byte_order, NULL);
698
699 if (body_len_unsigned > (unsigned) max_message_length)
700 {
701 *validity = DBUS_INVALID_INSANE_BODY_LENGTH;
702 return FALSE;
703 }
704
705 header_len_unsigned = FIRST_FIELD_OFFSET + fields_array_len_unsigned;
706 header_len_unsigned = _DBUS_ALIGN_VALUE (header_len_unsigned, 8);
707
708 /* overflow should be impossible since the lengths aren't allowed to
709 * be huge.
710 */
711 _dbus_assert (max_message_length < _DBUS_INT32_MAX / 2);
712 if (body_len_unsigned + header_len_unsigned > (unsigned) max_message_length)
713 {
714 *validity = DBUS_INVALID_MESSAGE_TOO_LONG;
715 return FALSE;
716 }
717
718 _dbus_assert (body_len_unsigned < (unsigned) _DBUS_INT32_MAX);
719 _dbus_assert (fields_array_len_unsigned < (unsigned) _DBUS_INT32_MAX);
720 _dbus_assert (header_len_unsigned < (unsigned) _DBUS_INT32_MAX);
721
722 *body_len = body_len_unsigned;
723 *fields_array_len = fields_array_len_unsigned;
724 *header_len = header_len_unsigned;
725
726 *validity = DBUS_VALID;
727
728 _dbus_verbose ("have %d bytes, need body %u + header %u = %u\n",
729 len, body_len_unsigned, header_len_unsigned,
730 body_len_unsigned + header_len_unsigned);
731
732 return (body_len_unsigned + header_len_unsigned) <= (unsigned) len;
733 }
734
735 static DBusValidity
check_mandatory_fields(DBusHeader * header)736 check_mandatory_fields (DBusHeader *header)
737 {
738 #define REQUIRE_FIELD(name) do { if (header->fields[DBUS_HEADER_FIELD_##name].value_pos < 0) return DBUS_INVALID_MISSING_##name; } while (0)
739
740 switch (_dbus_header_get_message_type (header))
741 {
742 case DBUS_MESSAGE_TYPE_SIGNAL:
743 REQUIRE_FIELD (INTERFACE);
744 /* FALL THRU - signals also require the path and member */
745 case DBUS_MESSAGE_TYPE_METHOD_CALL:
746 REQUIRE_FIELD (PATH);
747 REQUIRE_FIELD (MEMBER);
748 break;
749 case DBUS_MESSAGE_TYPE_ERROR:
750 REQUIRE_FIELD (ERROR_NAME);
751 REQUIRE_FIELD (REPLY_SERIAL);
752 break;
753 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
754 REQUIRE_FIELD (REPLY_SERIAL);
755 break;
756 default:
757 /* other message types allowed but ignored */
758 break;
759 }
760
761 return DBUS_VALID;
762 }
763
764 static DBusValidity
load_and_validate_field(DBusHeader * header,int field,DBusTypeReader * variant_reader)765 load_and_validate_field (DBusHeader *header,
766 int field,
767 DBusTypeReader *variant_reader)
768 {
769 int type;
770 int expected_type;
771 const DBusString *value_str;
772 int value_pos;
773 int str_data_pos;
774 dbus_uint32_t v_UINT32;
775 int bad_string_code;
776 dbus_bool_t (* string_validation_func) (const DBusString *str,
777 int start, int len);
778
779 /* Supposed to have been checked already */
780 _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
781 _dbus_assert (field != DBUS_HEADER_FIELD_INVALID);
782
783 /* Before we can cache a field, we need to know it has the right type */
784 type = _dbus_type_reader_get_current_type (variant_reader);
785
786 _dbus_assert (_dbus_header_field_types[field].code == field);
787
788 expected_type = EXPECTED_TYPE_OF_FIELD (field);
789 if (type != expected_type)
790 {
791 _dbus_verbose ("Field %d should have type %d but has %d\n",
792 field, expected_type, type);
793 return DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE;
794 }
795
796 /* If the field was provided twice, we aren't happy */
797 if (header->fields[field].value_pos >= 0)
798 {
799 _dbus_verbose ("Header field %d seen a second time\n", field);
800 return DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE;
801 }
802
803 /* Now we can cache and look at the field content */
804 _dbus_verbose ("initially caching field %d\n", field);
805 _dbus_header_cache_one (header, field, variant_reader);
806
807 string_validation_func = NULL;
808
809 /* make compiler happy that all this is initialized */
810 v_UINT32 = 0;
811 value_str = NULL;
812 value_pos = -1;
813 str_data_pos = -1;
814 bad_string_code = DBUS_VALID;
815
816 if (expected_type == DBUS_TYPE_UINT32)
817 {
818 _dbus_header_get_field_basic (header, field, expected_type,
819 &v_UINT32);
820 }
821 else if (expected_type == DBUS_TYPE_STRING ||
822 expected_type == DBUS_TYPE_OBJECT_PATH ||
823 expected_type == DBUS_TYPE_SIGNATURE)
824 {
825 _dbus_header_get_field_raw (header, field,
826 &value_str, &value_pos);
827 str_data_pos = _DBUS_ALIGN_VALUE (value_pos, 4) + 4;
828 }
829 else
830 {
831 _dbus_assert_not_reached ("none of the known fields should have this type");
832 }
833
834 switch (field)
835 {
836 case DBUS_HEADER_FIELD_DESTINATION:
837 string_validation_func = _dbus_validate_bus_name;
838 bad_string_code = DBUS_INVALID_BAD_DESTINATION;
839 break;
840 case DBUS_HEADER_FIELD_INTERFACE:
841 string_validation_func = _dbus_validate_interface;
842 bad_string_code = DBUS_INVALID_BAD_INTERFACE;
843
844 if (_dbus_string_equal_substring (&_dbus_local_interface_str,
845 0,
846 _dbus_string_get_length (&_dbus_local_interface_str),
847 value_str, str_data_pos))
848 {
849 _dbus_verbose ("Message is on the local interface\n");
850 return DBUS_INVALID_USES_LOCAL_INTERFACE;
851 }
852 break;
853
854 case DBUS_HEADER_FIELD_MEMBER:
855 string_validation_func = _dbus_validate_member;
856 bad_string_code = DBUS_INVALID_BAD_MEMBER;
857 break;
858
859 case DBUS_HEADER_FIELD_ERROR_NAME:
860 string_validation_func = _dbus_validate_error_name;
861 bad_string_code = DBUS_INVALID_BAD_ERROR_NAME;
862 break;
863
864 case DBUS_HEADER_FIELD_SENDER:
865 string_validation_func = _dbus_validate_bus_name;
866 bad_string_code = DBUS_INVALID_BAD_SENDER;
867 break;
868
869 case DBUS_HEADER_FIELD_PATH:
870 /* OBJECT_PATH was validated generically due to its type */
871 string_validation_func = NULL;
872
873 if (_dbus_string_equal_substring (&_dbus_local_path_str,
874 0,
875 _dbus_string_get_length (&_dbus_local_path_str),
876 value_str, str_data_pos))
877 {
878 _dbus_verbose ("Message is from the local path\n");
879 return DBUS_INVALID_USES_LOCAL_PATH;
880 }
881 break;
882
883 case DBUS_HEADER_FIELD_REPLY_SERIAL:
884 /* Can't be 0 */
885 if (v_UINT32 == 0)
886 {
887 return DBUS_INVALID_BAD_SERIAL;
888 }
889 break;
890
891 case DBUS_HEADER_FIELD_SIGNATURE:
892 /* SIGNATURE validated generically due to its type */
893 string_validation_func = NULL;
894 break;
895
896 default:
897 _dbus_assert_not_reached ("unknown field shouldn't be seen here");
898 break;
899 }
900
901 if (string_validation_func)
902 {
903 dbus_uint32_t len;
904
905 _dbus_assert (bad_string_code != DBUS_VALID);
906
907 len = _dbus_marshal_read_uint32 (value_str, value_pos,
908 header->byte_order, NULL);
909
910 #if 0
911 _dbus_verbose ("Validating string header field; code %d if fails\n",
912 bad_string_code);
913 #endif
914 if (!(*string_validation_func) (value_str, str_data_pos, len))
915 return bad_string_code;
916 }
917
918 return DBUS_VALID;
919 }
920
921 /**
922 * Creates a message header from potentially-untrusted data. The
923 * return value is #TRUE if there was enough memory and the data was
924 * valid. If it returns #TRUE, the header will be created. If it
925 * returns #FALSE and *validity == #DBUS_VALIDITY_UNKNOWN_OOM_ERROR,
926 * then there wasn't enough memory. If it returns #FALSE
927 * and *validity != #DBUS_VALIDITY_UNKNOWN_OOM_ERROR then the data was
928 * invalid.
929 *
930 * The byte_order, fields_array_len, and body_len args should be from
931 * _dbus_header_have_message_untrusted(). Validation performed in
932 * _dbus_header_have_message_untrusted() is assumed to have been
933 * already done.
934 *
935 * @param header the header (must be initialized)
936 * @param mode whether to do validation
937 * @param validity return location for invalidity reason
938 * @param byte_order byte order from header
939 * @param fields_array_len claimed length of fields array
940 * @param body_len claimed length of body
941 * @param header_len claimed length of header
942 * @param str a string
943 * @param start start of header, 8-aligned
944 * @param len length of string to look at
945 * @returns #FALSE if no memory or data was invalid, #TRUE otherwise
946 */
947 dbus_bool_t
_dbus_header_load(DBusHeader * header,DBusValidationMode mode,DBusValidity * validity,int byte_order,int fields_array_len,int header_len,int body_len,const DBusString * str,int start,int len)948 _dbus_header_load (DBusHeader *header,
949 DBusValidationMode mode,
950 DBusValidity *validity,
951 int byte_order,
952 int fields_array_len,
953 int header_len,
954 int body_len,
955 const DBusString *str,
956 int start,
957 int len)
958 {
959 int leftover;
960 DBusValidity v;
961 DBusTypeReader reader;
962 DBusTypeReader array_reader;
963 unsigned char v_byte;
964 dbus_uint32_t v_uint32;
965 dbus_uint32_t serial;
966 int padding_start;
967 int padding_len;
968 int i;
969
970 _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8));
971 _dbus_assert (header_len <= len);
972 _dbus_assert (_dbus_string_get_length (&header->data) == 0);
973
974 if (!_dbus_string_copy_len (str, start, header_len, &header->data, 0))
975 {
976 _dbus_verbose ("Failed to copy buffer into new header\n");
977 *validity = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
978 return FALSE;
979 }
980
981 if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
982 {
983 leftover = len - header_len - body_len - start;
984 }
985 else
986 {
987 v = _dbus_validate_body_with_reason (&_dbus_header_signature_str, 0,
988 byte_order,
989 &leftover,
990 str, start, len);
991
992 if (v != DBUS_VALID)
993 {
994 *validity = v;
995 goto invalid;
996 }
997 }
998
999 _dbus_assert (leftover < len);
1000
1001 padding_len = header_len - (FIRST_FIELD_OFFSET + fields_array_len);
1002 padding_start = start + FIRST_FIELD_OFFSET + fields_array_len;
1003 _dbus_assert (start + header_len == (int) _DBUS_ALIGN_VALUE (padding_start, 8));
1004 _dbus_assert (start + header_len == padding_start + padding_len);
1005
1006 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1007 {
1008 if (!_dbus_string_validate_nul (str, padding_start, padding_len))
1009 {
1010 *validity = DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
1011 goto invalid;
1012 }
1013 }
1014
1015 header->padding = padding_len;
1016
1017 if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1018 {
1019 *validity = DBUS_VALID;
1020 return TRUE;
1021 }
1022
1023 /* We now know the data is well-formed, but we have to check that
1024 * it's valid.
1025 */
1026
1027 _dbus_type_reader_init (&reader,
1028 byte_order,
1029 &_dbus_header_signature_str, 0,
1030 str, start);
1031
1032 /* BYTE ORDER */
1033 _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
1034 _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == BYTE_ORDER_OFFSET);
1035 _dbus_type_reader_read_basic (&reader, &v_byte);
1036 _dbus_type_reader_next (&reader);
1037
1038 _dbus_assert (v_byte == byte_order);
1039 header->byte_order = byte_order;
1040
1041 /* MESSAGE TYPE */
1042 _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
1043 _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == TYPE_OFFSET);
1044 _dbus_type_reader_read_basic (&reader, &v_byte);
1045 _dbus_type_reader_next (&reader);
1046
1047 /* unknown message types are supposed to be ignored, so only validation here is
1048 * that it isn't invalid
1049 */
1050 if (v_byte == DBUS_MESSAGE_TYPE_INVALID)
1051 {
1052 *validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
1053 goto invalid;
1054 }
1055
1056 /* FLAGS */
1057 _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
1058 _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FLAGS_OFFSET);
1059 _dbus_type_reader_read_basic (&reader, &v_byte);
1060 _dbus_type_reader_next (&reader);
1061
1062 /* unknown flags should be ignored */
1063
1064 /* PROTOCOL VERSION */
1065 _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
1066 _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == VERSION_OFFSET);
1067 _dbus_type_reader_read_basic (&reader, &v_byte);
1068 _dbus_type_reader_next (&reader);
1069
1070 if (v_byte != DBUS_MAJOR_PROTOCOL_VERSION)
1071 {
1072 *validity = DBUS_INVALID_BAD_PROTOCOL_VERSION;
1073 goto invalid;
1074 }
1075
1076 /* BODY LENGTH */
1077 _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_UINT32);
1078 _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == BODY_LENGTH_OFFSET);
1079 _dbus_type_reader_read_basic (&reader, &v_uint32);
1080 _dbus_type_reader_next (&reader);
1081
1082 _dbus_assert (body_len == (signed) v_uint32);
1083
1084 /* SERIAL */
1085 _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_UINT32);
1086 _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == SERIAL_OFFSET);
1087 _dbus_type_reader_read_basic (&reader, &serial);
1088 _dbus_type_reader_next (&reader);
1089
1090 if (serial == 0)
1091 {
1092 *validity = DBUS_INVALID_BAD_SERIAL;
1093 goto invalid;
1094 }
1095
1096 _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_ARRAY);
1097 _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FIELDS_ARRAY_LENGTH_OFFSET);
1098
1099 _dbus_type_reader_recurse (&reader, &array_reader);
1100 while (_dbus_type_reader_get_current_type (&array_reader) != DBUS_TYPE_INVALID)
1101 {
1102 DBusTypeReader struct_reader;
1103 DBusTypeReader variant_reader;
1104 unsigned char field_code;
1105
1106 _dbus_assert (_dbus_type_reader_get_current_type (&array_reader) == DBUS_TYPE_STRUCT);
1107
1108 _dbus_type_reader_recurse (&array_reader, &struct_reader);
1109
1110 _dbus_assert (_dbus_type_reader_get_current_type (&struct_reader) == DBUS_TYPE_BYTE);
1111 _dbus_type_reader_read_basic (&struct_reader, &field_code);
1112 _dbus_type_reader_next (&struct_reader);
1113
1114 if (field_code == DBUS_HEADER_FIELD_INVALID)
1115 {
1116 _dbus_verbose ("invalid header field code\n");
1117 *validity = DBUS_INVALID_HEADER_FIELD_CODE;
1118 goto invalid;
1119 }
1120
1121 if (field_code > DBUS_HEADER_FIELD_LAST)
1122 {
1123 _dbus_verbose ("unknown header field code %d, skipping\n",
1124 field_code);
1125 goto next_field;
1126 }
1127
1128 _dbus_assert (_dbus_type_reader_get_current_type (&struct_reader) == DBUS_TYPE_VARIANT);
1129 _dbus_type_reader_recurse (&struct_reader, &variant_reader);
1130
1131 v = load_and_validate_field (header, field_code, &variant_reader);
1132 if (v != DBUS_VALID)
1133 {
1134 _dbus_verbose ("Field %d was invalid\n", field_code);
1135 *validity = v;
1136 goto invalid;
1137 }
1138
1139 next_field:
1140 _dbus_type_reader_next (&array_reader);
1141 }
1142
1143 /* Anything we didn't fill in is now known not to exist */
1144 i = 0;
1145 while (i <= DBUS_HEADER_FIELD_LAST)
1146 {
1147 if (header->fields[i].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
1148 header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
1149 ++i;
1150 }
1151
1152 v = check_mandatory_fields (header);
1153 if (v != DBUS_VALID)
1154 {
1155 _dbus_verbose ("Mandatory fields were missing, code %d\n", v);
1156 *validity = v;
1157 goto invalid;
1158 }
1159
1160 *validity = DBUS_VALID;
1161 return TRUE;
1162
1163 invalid:
1164 _dbus_string_set_length (&header->data, 0);
1165 return FALSE;
1166 }
1167
1168 /**
1169 * Fills in the correct body length.
1170 *
1171 * @param header the header
1172 * @param body_len the length of the body
1173 */
1174 void
_dbus_header_update_lengths(DBusHeader * header,int body_len)1175 _dbus_header_update_lengths (DBusHeader *header,
1176 int body_len)
1177 {
1178 _dbus_marshal_set_uint32 (&header->data,
1179 BODY_LENGTH_OFFSET,
1180 body_len,
1181 header->byte_order);
1182 }
1183
1184 static dbus_bool_t
find_field_for_modification(DBusHeader * header,int field,DBusTypeReader * reader,DBusTypeReader * realign_root)1185 find_field_for_modification (DBusHeader *header,
1186 int field,
1187 DBusTypeReader *reader,
1188 DBusTypeReader *realign_root)
1189 {
1190 dbus_bool_t retval;
1191
1192 retval = FALSE;
1193
1194 _dbus_type_reader_init (realign_root,
1195 header->byte_order,
1196 &_dbus_header_signature_str,
1197 FIELDS_ARRAY_SIGNATURE_OFFSET,
1198 &header->data,
1199 FIELDS_ARRAY_LENGTH_OFFSET);
1200
1201 _dbus_type_reader_recurse (realign_root, reader);
1202
1203 while (_dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID)
1204 {
1205 DBusTypeReader sub;
1206 unsigned char field_code;
1207
1208 _dbus_type_reader_recurse (reader, &sub);
1209
1210 _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
1211 _dbus_type_reader_read_basic (&sub, &field_code);
1212
1213 if (field_code == (unsigned) field)
1214 {
1215 _dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_STRUCT);
1216 retval = TRUE;
1217 goto done;
1218 }
1219
1220 _dbus_type_reader_next (reader);
1221 }
1222
1223 done:
1224 return retval;
1225 }
1226
1227 /**
1228 * Sets the value of a field with basic type. If the value is a string
1229 * value, it isn't allowed to be #NULL. If the field doesn't exist,
1230 * it will be created.
1231 *
1232 * @param header the header
1233 * @param field the field to set
1234 * @param type the type of the value
1235 * @param value the value as for _dbus_marshal_set_basic()
1236 * @returns #FALSE if no memory
1237 */
1238 dbus_bool_t
_dbus_header_set_field_basic(DBusHeader * header,int field,int type,const void * value)1239 _dbus_header_set_field_basic (DBusHeader *header,
1240 int field,
1241 int type,
1242 const void *value)
1243 {
1244 _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
1245
1246 if (!reserve_header_padding (header))
1247 return FALSE;
1248
1249 /* If the field exists we set, otherwise we append */
1250 if (_dbus_header_cache_check (header, field))
1251 {
1252 DBusTypeReader reader;
1253 DBusTypeReader realign_root;
1254
1255 if (!find_field_for_modification (header, field,
1256 &reader, &realign_root))
1257 _dbus_assert_not_reached ("field was marked present in cache but wasn't found");
1258
1259 if (!set_basic_field (&reader, field, type, value, &realign_root))
1260 return FALSE;
1261 }
1262 else
1263 {
1264 DBusTypeWriter writer;
1265 DBusTypeWriter array;
1266
1267 _dbus_type_writer_init_values_only (&writer,
1268 header->byte_order,
1269 &_dbus_header_signature_str,
1270 FIELDS_ARRAY_SIGNATURE_OFFSET,
1271 &header->data,
1272 FIELDS_ARRAY_LENGTH_OFFSET);
1273
1274 /* recurse into array without creating a new length, and jump to
1275 * end of array.
1276 */
1277 if (!_dbus_type_writer_append_array (&writer,
1278 &_dbus_header_signature_str,
1279 FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET,
1280 &array))
1281 _dbus_assert_not_reached ("recurse into ARRAY should not have used memory");
1282
1283 _dbus_assert (array.u.array.len_pos == FIELDS_ARRAY_LENGTH_OFFSET);
1284 _dbus_assert (array.u.array.start_pos == FIRST_FIELD_OFFSET);
1285 _dbus_assert (array.value_pos == HEADER_END_BEFORE_PADDING (header));
1286
1287 if (!write_basic_field (&array,
1288 field, type, value))
1289 return FALSE;
1290
1291 if (!_dbus_type_writer_unrecurse (&writer, &array))
1292 _dbus_assert_not_reached ("unrecurse from ARRAY should not have used memory");
1293 }
1294
1295 correct_header_padding (header);
1296
1297 /* We could be smarter about this (only invalidate fields after the
1298 * one we modified, or even only if the one we modified changed
1299 * length). But this hack is a start.
1300 */
1301 _dbus_header_cache_invalidate_all (header);
1302
1303 return TRUE;
1304 }
1305
1306 /**
1307 * Gets the value of a field with basic type. If the field
1308 * doesn't exist, returns #FALSE, otherwise returns #TRUE.
1309 *
1310 * @param header the header
1311 * @param field the field to get
1312 * @param type the type of the value
1313 * @param value the value as for _dbus_marshal_read_basic()
1314 * @returns #FALSE if the field doesn't exist
1315 */
1316 dbus_bool_t
_dbus_header_get_field_basic(DBusHeader * header,int field,int type,void * value)1317 _dbus_header_get_field_basic (DBusHeader *header,
1318 int field,
1319 int type,
1320 void *value)
1321 {
1322 _dbus_assert (field != DBUS_HEADER_FIELD_INVALID);
1323 _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
1324 _dbus_assert (_dbus_header_field_types[field].code == field);
1325 /* in light of this you might ask why the type is passed in;
1326 * the only rationale I can think of is so the caller has
1327 * to specify its expectation and breaks if we change it
1328 */
1329 _dbus_assert (type == EXPECTED_TYPE_OF_FIELD (field));
1330
1331 if (!_dbus_header_cache_check (header, field))
1332 return FALSE;
1333
1334 _dbus_assert (header->fields[field].value_pos >= 0);
1335
1336 _dbus_marshal_read_basic (&header->data,
1337 header->fields[field].value_pos,
1338 type, value, header->byte_order,
1339 NULL);
1340
1341 return TRUE;
1342 }
1343
1344 /**
1345 * Gets the raw marshaled data for a field. If the field doesn't
1346 * exist, returns #FALSE, otherwise returns #TRUE. Returns the start
1347 * of the marshaled data, i.e. usually the byte where the length
1348 * starts (for strings and arrays) or for basic types just the value
1349 * itself.
1350 *
1351 * @param header the header
1352 * @param field the field to get
1353 * @param str return location for the data string
1354 * @param pos return location for start of field value
1355 * @returns #FALSE if the field doesn't exist
1356 */
1357 dbus_bool_t
_dbus_header_get_field_raw(DBusHeader * header,int field,const DBusString ** str,int * pos)1358 _dbus_header_get_field_raw (DBusHeader *header,
1359 int field,
1360 const DBusString **str,
1361 int *pos)
1362 {
1363 if (!_dbus_header_cache_check (header, field))
1364 return FALSE;
1365
1366 if (str)
1367 *str = &header->data;
1368 if (pos)
1369 *pos = header->fields[field].value_pos;
1370
1371 return TRUE;
1372 }
1373
1374 /**
1375 * Deletes a field, if it exists.
1376 *
1377 * @param header the header
1378 * @param field the field to delete
1379 * @returns #FALSE if no memory
1380 */
1381 dbus_bool_t
_dbus_header_delete_field(DBusHeader * header,int field)1382 _dbus_header_delete_field (DBusHeader *header,
1383 int field)
1384 {
1385 DBusTypeReader reader;
1386 DBusTypeReader realign_root;
1387
1388 if (_dbus_header_cache_known_nonexistent (header, field))
1389 return TRUE; /* nothing to do */
1390
1391 /* Scan to the field we want, delete and realign, reappend
1392 * padding. Field may turn out not to exist.
1393 */
1394 if (!find_field_for_modification (header, field,
1395 &reader, &realign_root))
1396 return TRUE; /* nothing to do */
1397
1398 if (!reserve_header_padding (header))
1399 return FALSE;
1400
1401 if (!_dbus_type_reader_delete (&reader,
1402 &realign_root))
1403 return FALSE;
1404
1405 correct_header_padding (header);
1406
1407 _dbus_header_cache_invalidate_all (header);
1408
1409 _dbus_assert (!_dbus_header_cache_check (header, field)); /* Expensive assertion ... */
1410
1411 return TRUE;
1412 }
1413
1414 /**
1415 * Toggles a message flag bit, turning on the bit if value = TRUE and
1416 * flipping it off if value = FALSE.
1417 *
1418 * @param header the header
1419 * @param flag the message flag to toggle
1420 * @param value toggle on or off
1421 */
1422 void
_dbus_header_toggle_flag(DBusHeader * header,dbus_uint32_t flag,dbus_bool_t value)1423 _dbus_header_toggle_flag (DBusHeader *header,
1424 dbus_uint32_t flag,
1425 dbus_bool_t value)
1426 {
1427 unsigned char *flags_p;
1428
1429 flags_p = _dbus_string_get_data_len (&header->data, FLAGS_OFFSET, 1);
1430
1431 if (value)
1432 *flags_p |= flag;
1433 else
1434 *flags_p &= ~flag;
1435 }
1436
1437 /**
1438 * Gets a message flag bit, returning TRUE if the bit is set.
1439 *
1440 * @param header the header
1441 * @param flag the message flag to get
1442 * @returns #TRUE if the flag is set
1443 */
1444 dbus_bool_t
_dbus_header_get_flag(DBusHeader * header,dbus_uint32_t flag)1445 _dbus_header_get_flag (DBusHeader *header,
1446 dbus_uint32_t flag)
1447 {
1448 const unsigned char *flags_p;
1449
1450 flags_p = _dbus_string_get_const_data_len (&header->data, FLAGS_OFFSET, 1);
1451
1452 return (*flags_p & flag) != 0;
1453 }
1454
1455 /**
1456 * Swaps the header into the given order if required.
1457 *
1458 * @param header the header
1459 * @param new_order the new byte order
1460 */
1461 void
_dbus_header_byteswap(DBusHeader * header,int new_order)1462 _dbus_header_byteswap (DBusHeader *header,
1463 int new_order)
1464 {
1465 if (header->byte_order == new_order)
1466 return;
1467
1468 _dbus_marshal_byteswap (&_dbus_header_signature_str,
1469 0, header->byte_order,
1470 new_order,
1471 &header->data, 0);
1472
1473 header->byte_order = new_order;
1474 }
1475
1476 /** @} */
1477
1478 #ifdef DBUS_BUILD_TESTS
1479 #include "dbus-test.h"
1480 #include <stdio.h>
1481
1482 dbus_bool_t
_dbus_marshal_header_test(void)1483 _dbus_marshal_header_test (void)
1484 {
1485
1486 return TRUE;
1487 }
1488
1489 #endif /* DBUS_BUILD_TESTS */
1490