D-Bus 1.14.8
dbus-marshal-header.c
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 */
23
24#include <config.h>
25#include "dbus/dbus-shared.h"
26#include "dbus-marshal-header.h"
27#include "dbus-marshal-recursive.h"
28#include "dbus-marshal-byteswap.h"
29
37/* Not thread locked, but strictly const/read-only so should be OK
38 */
45
47#define FIELDS_ARRAY_SIGNATURE_OFFSET 6
49#define FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET 7
50
51
53#define BYTE_ORDER_OFFSET 0
55#define TYPE_OFFSET 1
57#define FLAGS_OFFSET 2
59#define VERSION_OFFSET 3
61#define BODY_LENGTH_OFFSET 4
63#define SERIAL_OFFSET 8
65#define FIELDS_ARRAY_LENGTH_OFFSET 12
67#define FIRST_FIELD_OFFSET 16
68
69typedef struct
70{
71 unsigned char code;
72 unsigned char type;
74
75static const HeaderFieldType
76_dbus_header_field_types[DBUS_HEADER_FIELD_LAST+1] = {
88#ifdef HAVE_PDPLINUX
89 ,{ DBUS_HEADER_FIELD_EXEC_SRC, DBUS_TYPE_STRING }
90 ,{ DBUS_HEADER_FIELD_EXEC_DST, DBUS_TYPE_STRING }
91#endif
92};
93
95#define EXPECTED_TYPE_OF_FIELD(field) (_dbus_header_field_types[field].type)
96
98#define MAX_POSSIBLE_HEADER_PADDING 7
99static dbus_bool_t
100reserve_header_padding (DBusHeader *header)
101{
103
104 if (!_dbus_string_lengthen (&header->data,
106 return FALSE;
108 return TRUE;
109}
110
111static void
112correct_header_padding (DBusHeader *header)
113{
114 int unpadded_len;
115
116 _dbus_assert (header->padding == 7);
117
118 _dbus_string_shorten (&header->data, header->padding);
119 unpadded_len = _dbus_string_get_length (&header->data);
120
121 if (!_dbus_string_align_length (&header->data, 8))
122 _dbus_assert_not_reached ("couldn't pad header though enough padding was preallocated");
123
124 header->padding = _dbus_string_get_length (&header->data) - unpadded_len;
125}
126
130#define HEADER_END_BEFORE_PADDING(header) \
131 (_dbus_string_get_length (&(header)->data) - (header)->padding)
132
140static void
141_dbus_header_cache_invalidate_all (DBusHeader *header)
142{
143 int i;
144
145 i = 0;
146 while (i <= DBUS_HEADER_FIELD_LAST)
147 {
148 header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_UNKNOWN;
149 ++i;
150 }
151}
152
160static void
161_dbus_header_cache_one (DBusHeader *header,
162 int field_code,
163 DBusTypeReader *variant_reader)
164{
165 header->fields[field_code].value_pos =
166 _dbus_type_reader_get_value_pos (variant_reader);
167
168#if 0
169 _dbus_verbose ("cached value_pos %d for field %d\n",
170 header->fields[field_code].value_pos, field_code)
171#endif
172}
173
180char
182{
183 _dbus_assert (_dbus_string_get_length (&header->data) > BYTE_ORDER_OFFSET);
184
185 return (char) _dbus_string_get_byte (&header->data, BYTE_ORDER_OFFSET);
186}
187
193static void
194_dbus_header_cache_revalidate (DBusHeader *header)
195{
196 DBusTypeReader array;
197 DBusTypeReader reader;
198 int i;
199
200 i = 0;
201 while (i <= DBUS_HEADER_FIELD_LAST)
202 {
203 header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
204 ++i;
205 }
206
207 _dbus_type_reader_init (&reader,
209 &_dbus_header_signature_str,
211 &header->data,
213
214 _dbus_type_reader_recurse (&reader, &array);
215
217 {
218 DBusTypeReader sub;
219 DBusTypeReader variant;
220 unsigned char field_code;
221
222 _dbus_type_reader_recurse (&array, &sub);
223
225 _dbus_type_reader_read_basic (&sub, &field_code);
226
227 /* Unknown fields should be ignored */
228 if (field_code > DBUS_HEADER_FIELD_LAST)
229 goto next_field;
230
232
234 _dbus_type_reader_recurse (&sub, &variant);
235
236 _dbus_header_cache_one (header, field_code, &variant);
237
238 next_field:
239 _dbus_type_reader_next (&array);
240 }
241}
242
250static dbus_bool_t
251_dbus_header_cache_check (DBusHeader *header,
252 int field)
253{
255
256 if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
257 _dbus_header_cache_revalidate (header);
258
259 if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT)
260 return FALSE;
261
262 return TRUE;
263}
264
273static dbus_bool_t
274_dbus_header_cache_known_nonexistent (DBusHeader *header,
275 int field)
276{
278
279 return (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT);
280}
281
291static dbus_bool_t
292write_basic_field (DBusTypeWriter *writer,
293 int field,
294 int type,
295 const void *value)
296{
297 DBusTypeWriter sub;
298 DBusTypeWriter variant;
299 int start;
300 int padding;
301 unsigned char field_byte;
302 DBusString contained_type;
303 char buf[2];
304
305 start = writer->value_pos;
306 padding = _dbus_string_get_length (writer->value_str) - start;
307
309 NULL, 0, &sub))
310 goto append_failed;
311
312 field_byte = field;
314 &field_byte))
315 goto append_failed;
316
317 buf[0] = type;
318 buf[1] = '\0';
319 _dbus_string_init_const_len (&contained_type, buf, 1);
320
322 &contained_type, 0, &variant))
323 goto append_failed;
324
325 if (!_dbus_type_writer_write_basic (&variant, type, value))
326 goto append_failed;
327
328 if (!_dbus_type_writer_unrecurse (&sub, &variant))
329 goto append_failed;
330
331 if (!_dbus_type_writer_unrecurse (writer, &sub))
332 goto append_failed;
333
334 return TRUE;
335
336 append_failed:
338 start,
339 _dbus_string_get_length (writer->value_str) - start - padding);
340 return FALSE;
341}
342
353static dbus_bool_t
354set_basic_field (DBusTypeReader *reader,
355 int field,
356 int type,
357 const void *value,
358 const DBusTypeReader *realign_root)
359{
360 DBusTypeReader sub;
361 DBusTypeReader variant;
362
363 _dbus_type_reader_recurse (reader, &sub);
364
366#ifndef DBUS_DISABLE_ASSERT
367 {
368 unsigned char v_BYTE;
369 _dbus_type_reader_read_basic (&sub, &v_BYTE);
370 _dbus_assert (((int) v_BYTE) == field);
371 }
372#endif
373
374 if (!_dbus_type_reader_next (&sub))
375 _dbus_assert_not_reached ("no variant field?");
376
377 _dbus_type_reader_recurse (&sub, &variant);
379
380 if (!_dbus_type_reader_set_basic (&variant, value, realign_root))
381 return FALSE;
382
383 return TRUE;
384}
385
392int
394{
395 int type;
396
397 type = _dbus_string_get_byte (&header->data, TYPE_OFFSET);
399
400 return type;
401}
402
410void
412 dbus_uint32_t serial)
413{
414 /* we use this function to set the serial on outgoing
415 * messages, and to reset the serial in dbus_message_copy;
416 * this assertion should catch a double-set on outgoing.
417 */
418 _dbus_assert (_dbus_header_get_serial (header) == 0 ||
419 serial == 0);
420
423 serial,
425}
426
433dbus_uint32_t
435{
436 return _dbus_marshal_read_uint32 (&header->data,
439 NULL);
440}
441
449void
451{
452 _dbus_string_set_length (&header->data, 0);
453
454 header->padding = 0;
455
456 _dbus_header_cache_invalidate_all (header);
457}
458
468{
469 if (!_dbus_string_init_preallocated (&header->data, 32))
470 return FALSE;
471
472 _dbus_header_reinit (header);
473
474 return TRUE;
475}
476
482void
484{
485 _dbus_string_free (&header->data);
486}
487
498 DBusHeader *dest)
499{
500 *dest = *header;
501
503 _dbus_string_get_length (&header->data)))
504 return FALSE;
505
506 if (!_dbus_string_copy (&header->data, 0, &dest->data, 0))
507 {
508 _dbus_string_free (&dest->data);
509 return FALSE;
510 }
511
512 /* Reset the serial */
513 _dbus_header_set_serial (dest, 0);
514
515 return TRUE;
516}
517
536 int byte_order,
537 int message_type,
538 const char *destination,
539 const char *path,
540 const char *interface,
541 const char *member,
542 const char *error_name)
543{
544 unsigned char v_BYTE;
545 dbus_uint32_t v_UINT32;
546 DBusTypeWriter writer;
547 DBusTypeWriter array;
548
549 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
550 byte_order == DBUS_BIG_ENDIAN);
551 _dbus_assert (((interface || message_type != DBUS_MESSAGE_TYPE_SIGNAL) && member) ||
552 (error_name) ||
553 !(interface || member || error_name));
554 _dbus_assert (_dbus_string_get_length (&header->data) == 0);
555
556 if (!reserve_header_padding (header))
557 return FALSE;
558
559 _dbus_type_writer_init_values_only (&writer, byte_order,
560 &_dbus_header_signature_str, 0,
561 &header->data,
563
564 v_BYTE = byte_order;
566 &v_BYTE))
567 goto oom;
568
569 v_BYTE = message_type;
571 &v_BYTE))
572 goto oom;
573
574 v_BYTE = 0; /* flags */
576 &v_BYTE))
577 goto oom;
578
581 &v_BYTE))
582 goto oom;
583
584 v_UINT32 = 0; /* body length */
586 &v_UINT32))
587 goto oom;
588
589 v_UINT32 = 0; /* serial */
591 &v_UINT32))
592 goto oom;
593
595 &_dbus_header_signature_str,
597 &array))
598 goto oom;
599
600 /* Marshal all the fields (Marshall Fields?) */
601
602 if (path != NULL)
603 {
604 if (!write_basic_field (&array,
607 &path))
608 goto oom;
609 }
610
611 if (destination != NULL)
612 {
613 if (!write_basic_field (&array,
616 &destination))
617 goto oom;
618 }
619
620 /* Note that test/message.c relies on this being in the middle of the
621 * message: if you change the order of serialization here (but why
622 * would you?), please find some other way to retain test coverage. */
623 if (interface != NULL)
624 {
625 if (!write_basic_field (&array,
628 &interface))
629 goto oom;
630 }
631
632 if (member != NULL)
633 {
634 if (!write_basic_field (&array,
637 &member))
638 goto oom;
639 }
640
641 if (error_name != NULL)
642 {
643 if (!write_basic_field (&array,
646 &error_name))
647 goto oom;
648 }
649
650 if (!_dbus_type_writer_unrecurse (&writer, &array))
651 goto oom;
652
653 correct_header_padding (header);
654
655 return TRUE;
656
657 oom:
658 _dbus_string_delete (&header->data, 0,
659 _dbus_string_get_length (&header->data) - header->padding);
660 correct_header_padding (header);
661
662 return FALSE;
663}
664
684 DBusValidity *validity,
685 int *byte_order,
686 int *fields_array_len,
687 int *header_len,
688 int *body_len,
689 const DBusString *str,
690 int start,
691 int len)
692
693{
694 dbus_uint32_t header_len_unsigned;
695 dbus_uint32_t fields_array_len_unsigned;
696 dbus_uint32_t body_len_unsigned;
697
698 _dbus_assert (start >= 0);
699 _dbus_assert (start < _DBUS_INT32_MAX / 2);
700 _dbus_assert (len >= 0);
701
702 _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8));
703
704 *byte_order = _dbus_string_get_byte (str, start + BYTE_ORDER_OFFSET);
705
706 if (*byte_order != DBUS_LITTLE_ENDIAN && *byte_order != DBUS_BIG_ENDIAN)
707 {
708 *validity = DBUS_INVALID_BAD_BYTE_ORDER;
709 return FALSE;
710 }
711
713 fields_array_len_unsigned = _dbus_marshal_read_uint32 (str, start + FIELDS_ARRAY_LENGTH_OFFSET,
714 *byte_order, NULL);
715
716 if (fields_array_len_unsigned > (unsigned) max_message_length)
717 {
718 *validity = DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH;
719 return FALSE;
720 }
721
723 body_len_unsigned = _dbus_marshal_read_uint32 (str, start + BODY_LENGTH_OFFSET,
724 *byte_order, NULL);
725
726 if (body_len_unsigned > (unsigned) max_message_length)
727 {
728 *validity = DBUS_INVALID_INSANE_BODY_LENGTH;
729 return FALSE;
730 }
731
732 header_len_unsigned = FIRST_FIELD_OFFSET + fields_array_len_unsigned;
733 header_len_unsigned = _DBUS_ALIGN_VALUE (header_len_unsigned, 8);
734
735 /* overflow should be impossible since the lengths aren't allowed to
736 * be huge.
737 */
738 _dbus_assert (max_message_length < _DBUS_INT32_MAX / 2);
739 if (body_len_unsigned + header_len_unsigned > (unsigned) max_message_length)
740 {
741 *validity = DBUS_INVALID_MESSAGE_TOO_LONG;
742 return FALSE;
743 }
744
745 _dbus_assert (body_len_unsigned < (unsigned) _DBUS_INT32_MAX);
746 _dbus_assert (fields_array_len_unsigned < (unsigned) _DBUS_INT32_MAX);
747 _dbus_assert (header_len_unsigned < (unsigned) _DBUS_INT32_MAX);
748
749 *body_len = body_len_unsigned;
750 *fields_array_len = fields_array_len_unsigned;
751 *header_len = header_len_unsigned;
752
753 *validity = DBUS_VALID;
754
755 _dbus_verbose ("have %d bytes, need body %u + header %u = %u\n",
756 len, body_len_unsigned, header_len_unsigned,
757 body_len_unsigned + header_len_unsigned);
758
759 return (body_len_unsigned + header_len_unsigned) <= (unsigned) len;
760}
761
762static DBusValidity
763check_mandatory_fields (DBusHeader *header)
764{
765#define REQUIRE_FIELD(name) do { if (header->fields[DBUS_HEADER_FIELD_##name].value_pos < 0) return DBUS_INVALID_MISSING_##name; } while (0)
766
767 switch (_dbus_header_get_message_type (header))
768 {
770 REQUIRE_FIELD (INTERFACE);
771 /* FALL THRU - signals also require the path and member */
773 REQUIRE_FIELD (PATH);
774 REQUIRE_FIELD (MEMBER);
775 break;
777 REQUIRE_FIELD (ERROR_NAME);
778 REQUIRE_FIELD (REPLY_SERIAL);
779 break;
781 REQUIRE_FIELD (REPLY_SERIAL);
782 break;
783 default:
784 /* other message types allowed but ignored */
785 break;
786 }
787
788 return DBUS_VALID;
789}
790
791static DBusValidity
792load_and_validate_field (DBusHeader *header,
793 int field,
794 DBusTypeReader *variant_reader)
795{
796 int type;
797 int expected_type;
798 const DBusString *value_str;
799 int value_pos;
800 int str_data_pos;
801 dbus_uint32_t v_UINT32;
802 int bad_string_code;
803 dbus_bool_t (* string_validation_func) (const DBusString *str,
804 int start, int len);
805
806 /* Supposed to have been checked already */
809
810 /* Before we can cache a field, we need to know it has the right type */
811 type = _dbus_type_reader_get_current_type (variant_reader);
812
813 _dbus_assert (_dbus_header_field_types[field].code == field);
814
815 expected_type = EXPECTED_TYPE_OF_FIELD (field);
816 if (type != expected_type)
817 {
818 _dbus_verbose ("Field %d should have type %d but has %d\n",
819 field, expected_type, type);
820 return DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE;
821 }
822
823 /* If the field was provided twice, we aren't happy */
824 if (header->fields[field].value_pos >= 0)
825 {
826 _dbus_verbose ("Header field %d seen a second time\n", field);
827 return DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE;
828 }
829
830 /* Now we can cache and look at the field content */
831 _dbus_verbose ("initially caching field %d\n", field);
832 _dbus_header_cache_one (header, field, variant_reader);
833
834 string_validation_func = NULL;
835
836 /* make compiler happy that all this is initialized */
837 v_UINT32 = 0;
838 value_str = NULL;
839 value_pos = -1;
840 str_data_pos = -1;
841 bad_string_code = DBUS_VALID;
842
843 if (expected_type == DBUS_TYPE_UINT32)
844 {
845 _dbus_header_get_field_basic (header, field, expected_type,
846 &v_UINT32);
847 }
848 else if (expected_type == DBUS_TYPE_STRING ||
849 expected_type == DBUS_TYPE_OBJECT_PATH ||
850 expected_type == DBUS_TYPE_SIGNATURE)
851 {
852 _dbus_header_get_field_raw (header, field,
853 &value_str, &value_pos);
854 str_data_pos = _DBUS_ALIGN_VALUE (value_pos, 4) + 4;
855 }
856 else
857 {
858 _dbus_assert_not_reached ("none of the known fields should have this type");
859 }
860
861 switch (field)
862 {
864 string_validation_func = _dbus_validate_bus_name;
865 bad_string_code = DBUS_INVALID_BAD_DESTINATION;
866 break;
868 string_validation_func = _dbus_validate_interface;
869 bad_string_code = DBUS_INVALID_BAD_INTERFACE;
870
871 if (_dbus_string_equal_substring (&_dbus_local_interface_str,
872 0,
873 _dbus_string_get_length (&_dbus_local_interface_str),
874 value_str, str_data_pos))
875 {
876 _dbus_verbose ("Message is on the local interface\n");
877 return DBUS_INVALID_USES_LOCAL_INTERFACE;
878 }
879 break;
880
882 string_validation_func = _dbus_validate_member;
883 bad_string_code = DBUS_INVALID_BAD_MEMBER;
884 break;
885
887 string_validation_func = _dbus_validate_error_name;
888 bad_string_code = DBUS_INVALID_BAD_ERROR_NAME;
889 break;
890
892 string_validation_func = _dbus_validate_bus_name;
893 bad_string_code = DBUS_INVALID_BAD_SENDER;
894 break;
895
897 /* OBJECT_PATH was validated generically due to its type */
898 string_validation_func = NULL;
899
900 if (_dbus_string_equal_substring (&_dbus_local_path_str,
901 0,
902 _dbus_string_get_length (&_dbus_local_path_str),
903 value_str, str_data_pos))
904 {
905 _dbus_verbose ("Message is from the local path\n");
906 return DBUS_INVALID_USES_LOCAL_PATH;
907 }
908 break;
909
911 /* Can't be 0 */
912 if (v_UINT32 == 0)
913 {
914 return DBUS_INVALID_BAD_SERIAL;
915 }
916 break;
917
919 /* Every value makes sense */
920 break;
921
922#ifdef HAVE_PDPLINUX
923 case DBUS_HEADER_FIELD_EXEC_SRC:
924 /* Every value makes sense */
925 break;
926 case DBUS_HEADER_FIELD_EXEC_DST:
927 /* Every value makes sense */
928 break;
929#endif
930
932 /* SIGNATURE validated generically due to its type */
933 string_validation_func = NULL;
934 break;
935
937 /* OBJECT_PATH was validated generically due to its type */
938 string_validation_func = NULL;
939 break;
940
941 default:
942 _dbus_assert_not_reached ("unknown field shouldn't be seen here");
943 break;
944 }
945
946 if (string_validation_func)
947 {
948 dbus_uint32_t len;
949
950 _dbus_assert (bad_string_code != DBUS_VALID);
951
952 len = _dbus_marshal_read_uint32 (value_str, value_pos,
954 NULL);
955
956#if 0
957 _dbus_verbose ("Validating string header field; code %d if fails\n",
958 bad_string_code);
959#endif
960 if (!(*string_validation_func) (value_str, str_data_pos, len))
961 return bad_string_code;
962 }
963
964 return DBUS_VALID;
965}
966
994 DBusValidity *validity,
995 int byte_order,
996 int fields_array_len,
997 int header_len,
998 int body_len,
999 const DBusString *str)
1000{
1001 int leftover;
1002 DBusValidity v;
1003 DBusTypeReader reader;
1004 DBusTypeReader array_reader;
1005 unsigned char v_byte;
1006 dbus_uint32_t v_uint32;
1007 dbus_uint32_t serial;
1008 int padding_start;
1009 int padding_len;
1010 int i;
1011 int len;
1012
1013 len = _dbus_string_get_length (str);
1014
1015 _dbus_assert (header_len <= len);
1016 _dbus_assert (_dbus_string_get_length (&header->data) == 0);
1017
1018 if (!_dbus_string_copy_len (str, 0, header_len, &header->data, 0))
1019 {
1020 _dbus_verbose ("Failed to copy buffer into new header\n");
1022 return FALSE;
1023 }
1024
1025 if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1026 {
1027 leftover = len - header_len - body_len;
1028 }
1029 else
1030 {
1031 v = _dbus_validate_body_with_reason (&_dbus_header_signature_str, 0,
1032 byte_order,
1033 &leftover,
1034 str, 0, len);
1035
1036 if (v != DBUS_VALID)
1037 {
1038 *validity = v;
1039 goto invalid;
1040 }
1041 }
1042
1043 _dbus_assert (leftover < len);
1044
1045 padding_len = header_len - (FIRST_FIELD_OFFSET + fields_array_len);
1046 padding_start = FIRST_FIELD_OFFSET + fields_array_len;
1047 _dbus_assert (header_len == (int) _DBUS_ALIGN_VALUE (padding_start, 8));
1048 _dbus_assert (header_len == padding_start + padding_len);
1049
1050 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1051 {
1052 if (!_dbus_string_validate_nul (str, padding_start, padding_len))
1053 {
1054 *validity = DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
1055 goto invalid;
1056 }
1057 }
1058
1059 header->padding = padding_len;
1060
1061 if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1062 {
1063 *validity = DBUS_VALID;
1064 return TRUE;
1065 }
1066
1067 /* We now know the data is well-formed, but we have to check that
1068 * it's valid.
1069 */
1070
1071 _dbus_type_reader_init (&reader,
1072 byte_order,
1073 &_dbus_header_signature_str, 0,
1074 str, 0);
1075
1076 /* BYTE ORDER */
1079 _dbus_type_reader_read_basic (&reader, &v_byte);
1080 _dbus_type_reader_next (&reader);
1081
1082 _dbus_assert (v_byte == byte_order);
1083
1084 /* MESSAGE TYPE */
1087 _dbus_type_reader_read_basic (&reader, &v_byte);
1088 _dbus_type_reader_next (&reader);
1089
1090 /* unknown message types are supposed to be ignored, so only validation here is
1091 * that it isn't invalid
1092 */
1093 if (v_byte == DBUS_MESSAGE_TYPE_INVALID)
1094 {
1095 *validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
1096 goto invalid;
1097 }
1098
1099 /* FLAGS */
1102 _dbus_type_reader_read_basic (&reader, &v_byte);
1103 _dbus_type_reader_next (&reader);
1104
1105 /* unknown flags should be ignored */
1106
1107 /* PROTOCOL VERSION */
1110 _dbus_type_reader_read_basic (&reader, &v_byte);
1111 _dbus_type_reader_next (&reader);
1112
1113 if (v_byte != DBUS_MAJOR_PROTOCOL_VERSION)
1114 {
1115 *validity = DBUS_INVALID_BAD_PROTOCOL_VERSION;
1116 goto invalid;
1117 }
1118
1119 /* BODY LENGTH */
1122 _dbus_type_reader_read_basic (&reader, &v_uint32);
1123 _dbus_type_reader_next (&reader);
1124
1125 _dbus_assert (body_len == (signed) v_uint32);
1126
1127 /* SERIAL */
1130 _dbus_type_reader_read_basic (&reader, &serial);
1131 _dbus_type_reader_next (&reader);
1132
1133 if (serial == 0)
1134 {
1135 *validity = DBUS_INVALID_BAD_SERIAL;
1136 goto invalid;
1137 }
1138
1141
1142 _dbus_type_reader_recurse (&reader, &array_reader);
1143 while (_dbus_type_reader_get_current_type (&array_reader) != DBUS_TYPE_INVALID)
1144 {
1145 DBusTypeReader struct_reader;
1146 DBusTypeReader variant_reader;
1147 unsigned char field_code;
1148
1150
1151 _dbus_type_reader_recurse (&array_reader, &struct_reader);
1152
1154 _dbus_type_reader_read_basic (&struct_reader, &field_code);
1155 _dbus_type_reader_next (&struct_reader);
1156
1157 if (field_code == DBUS_HEADER_FIELD_INVALID)
1158 {
1159 _dbus_verbose ("invalid header field code\n");
1160 *validity = DBUS_INVALID_HEADER_FIELD_CODE;
1161 goto invalid;
1162 }
1163
1164 if (field_code > DBUS_HEADER_FIELD_LAST)
1165 {
1166 _dbus_verbose ("unknown header field code %d, skipping\n",
1167 field_code);
1168 goto next_field;
1169 }
1170
1172 _dbus_type_reader_recurse (&struct_reader, &variant_reader);
1173
1174 v = load_and_validate_field (header, field_code, &variant_reader);
1175 if (v != DBUS_VALID)
1176 {
1177 _dbus_verbose ("Field %d was invalid\n", field_code);
1178 *validity = v;
1179 goto invalid;
1180 }
1181
1182 next_field:
1183 _dbus_type_reader_next (&array_reader);
1184 }
1185
1186 /* Anything we didn't fill in is now known not to exist */
1187 i = 0;
1188 while (i <= DBUS_HEADER_FIELD_LAST)
1189 {
1190 if (header->fields[i].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
1191 header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
1192 ++i;
1193 }
1194
1195 v = check_mandatory_fields (header);
1196 if (v != DBUS_VALID)
1197 {
1198 _dbus_verbose ("Mandatory fields were missing, code %d\n", v);
1199 *validity = v;
1200 goto invalid;
1201 }
1202
1203 *validity = DBUS_VALID;
1204 return TRUE;
1205
1206 invalid:
1207 _dbus_string_set_length (&header->data, 0);
1208 return FALSE;
1209}
1210
1217void
1219 int body_len)
1220{
1223 body_len,
1225}
1226
1240static dbus_bool_t
1241find_field_for_modification (DBusHeader *header,
1242 int field,
1243 DBusTypeReader *reader,
1244 DBusTypeReader *realign_root)
1245{
1246 dbus_bool_t retval;
1247
1248 retval = FALSE;
1249
1250 _dbus_type_reader_init (realign_root,
1252 &_dbus_header_signature_str,
1254 &header->data,
1256
1257 _dbus_type_reader_recurse (realign_root, reader);
1258
1260 {
1261 DBusTypeReader sub;
1262 unsigned char field_code;
1263
1264 _dbus_type_reader_recurse (reader, &sub);
1265
1267 _dbus_type_reader_read_basic (&sub, &field_code);
1268
1269 if (field_code == (unsigned) field)
1270 {
1272 retval = TRUE;
1273 goto done;
1274 }
1275
1276 _dbus_type_reader_next (reader);
1277 }
1278
1279 done:
1280 return retval;
1281}
1282
1296 int field,
1297 int type,
1298 const void *value)
1299{
1301
1302 if (!reserve_header_padding (header))
1303 return FALSE;
1304
1305 /* If the field exists we set, otherwise we append */
1306 if (_dbus_header_cache_check (header, field))
1307 {
1308 DBusTypeReader reader;
1309 DBusTypeReader realign_root;
1310
1311 if (!find_field_for_modification (header, field,
1312 &reader, &realign_root))
1313 _dbus_assert_not_reached ("field was marked present in cache but wasn't found");
1314
1315 if (!set_basic_field (&reader, field, type, value, &realign_root))
1316 return FALSE;
1317 }
1318 else
1319 {
1320 DBusTypeWriter writer;
1321 DBusTypeWriter array;
1322
1325 &_dbus_header_signature_str,
1327 &header->data,
1329
1330 /* recurse into array without creating a new length, and jump to
1331 * end of array.
1332 */
1333 if (!_dbus_type_writer_append_array (&writer,
1334 &_dbus_header_signature_str,
1336 &array))
1337 _dbus_assert_not_reached ("recurse into ARRAY should not have used memory");
1338
1340 _dbus_assert (array.u.array.start_pos == FIRST_FIELD_OFFSET);
1342
1343 if (!write_basic_field (&array,
1344 field, type, value))
1345 return FALSE;
1346
1347 if (!_dbus_type_writer_unrecurse (&writer, &array))
1348 _dbus_assert_not_reached ("unrecurse from ARRAY should not have used memory");
1349 }
1350
1351 correct_header_padding (header);
1352
1353 /* We could be smarter about this (only invalidate fields after the
1354 * one we modified, or even only if the one we modified changed
1355 * length). But this hack is a start.
1356 */
1357 _dbus_header_cache_invalidate_all (header);
1358
1359 return TRUE;
1360}
1361
1374 int field,
1375 int type,
1376 void *value)
1377{
1380 _dbus_assert (_dbus_header_field_types[field].code == field);
1381 /* in light of this you might ask why the type is passed in;
1382 * the only rationale I can think of is so the caller has
1383 * to specify its expectation and breaks if we change it
1384 */
1385 _dbus_assert (type == EXPECTED_TYPE_OF_FIELD (field));
1386
1387 if (!_dbus_header_cache_check (header, field))
1388 return FALSE;
1389
1390 _dbus_assert (header->fields[field].value_pos >= 0);
1391
1393 header->fields[field].value_pos,
1394 type, value, _dbus_header_get_byte_order (header),
1395 NULL);
1396
1397 return TRUE;
1398}
1399
1415 int field,
1416 const DBusString **str,
1417 int *pos)
1418{
1419 if (!_dbus_header_cache_check (header, field))
1420 return FALSE;
1421
1422 if (str)
1423 *str = &header->data;
1424 if (pos)
1425 *pos = header->fields[field].value_pos;
1426
1427 return TRUE;
1428}
1429
1439 int field)
1440{
1441 DBusTypeReader reader;
1442 DBusTypeReader realign_root;
1443
1444 if (_dbus_header_cache_known_nonexistent (header, field))
1445 return TRUE; /* nothing to do */
1446
1447 /* Scan to the field we want, delete and realign, reappend
1448 * padding. Field may turn out not to exist.
1449 */
1450 if (!find_field_for_modification (header, field,
1451 &reader, &realign_root))
1452 return TRUE; /* nothing to do */
1453
1454 if (!reserve_header_padding (header))
1455 return FALSE;
1456
1457 if (!_dbus_type_reader_delete (&reader,
1458 &realign_root))
1459 return FALSE;
1460
1461 correct_header_padding (header);
1462
1463 _dbus_header_cache_invalidate_all (header);
1464
1465 _dbus_assert (!_dbus_header_cache_check (header, field)); /* Expensive assertion ... */
1466
1467 return TRUE;
1468}
1469
1478void
1480 dbus_uint32_t flag,
1481 dbus_bool_t value)
1482{
1483 unsigned char *flags_p;
1484
1485 flags_p = _dbus_string_get_udata_len (&header->data, FLAGS_OFFSET, 1);
1486
1487 if (value)
1488 *flags_p |= flag;
1489 else
1490 *flags_p &= ~flag;
1491}
1492
1502 dbus_uint32_t flag)
1503{
1504 const unsigned char *flags_p;
1505
1506 flags_p = _dbus_string_get_const_udata_len (&header->data, FLAGS_OFFSET, 1);
1507
1508 return (*flags_p & flag) != 0;
1509}
1510
1517void
1519 int new_order)
1520{
1521 char byte_order;
1522
1523 byte_order = _dbus_header_get_byte_order (header);
1524
1525 if (byte_order == new_order)
1526 return;
1527
1528 _dbus_marshal_byteswap (&_dbus_header_signature_str,
1529 0, byte_order,
1530 new_order,
1531 &header->data, 0);
1532
1533 _dbus_string_set_byte (&header->data, BYTE_ORDER_OFFSET, new_order);
1534}
1535
1544{
1545 DBusTypeReader array;
1546 DBusTypeReader fields_reader;
1547
1548 _dbus_type_reader_init (&fields_reader,
1550 &_dbus_header_signature_str,
1552 &header->data,
1554
1555 _dbus_type_reader_recurse (&fields_reader, &array);
1556
1558 {
1559 DBusTypeReader sub;
1560 unsigned char field_code;
1561
1562 _dbus_type_reader_recurse (&array, &sub);
1563
1565 _dbus_type_reader_read_basic (&sub, &field_code);
1566
1567 if (field_code > DBUS_HEADER_FIELD_LAST)
1568 {
1569 if (!reserve_header_padding (header))
1570 return FALSE;
1571
1572 if (!_dbus_type_reader_delete (&array, &fields_reader))
1573 return FALSE;
1574
1575 correct_header_padding (header);
1576 _dbus_header_cache_invalidate_all (header);
1577 }
1578 else
1579 {
1580 _dbus_type_reader_next (&array);
1581 }
1582 }
1583
1584 return TRUE;
1585}
1586
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
#define _DBUS_INT32_MAX
Maximum value of type "int32".
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
dbus_bool_t _dbus_type_writer_write_basic(DBusTypeWriter *writer, int type, const void *value)
Writes out a basic type.
void _dbus_type_reader_recurse(DBusTypeReader *reader, DBusTypeReader *sub)
Initialize a new reader pointing to the first type and corresponding value that's a child of the curr...
DBusValidity
This is primarily used in unit testing, so we can verify that each invalid message is invalid for the...
void _dbus_header_update_lengths(DBusHeader *header, int body_len)
Fills in the correct body length.
dbus_bool_t _dbus_header_copy(const DBusHeader *header, DBusHeader *dest)
Initializes dest with a copy of the given header.
#define BODY_LENGTH_OFFSET
Offset to body length from start of header.
void _dbus_type_writer_init_values_only(DBusTypeWriter *writer, int byte_order, const DBusString *type_str, int type_pos, DBusString *value_str, int value_pos)
Like _dbus_type_writer_init(), except the type string passed in should correspond to an existing sign...
int _dbus_type_reader_get_value_pos(const DBusTypeReader *reader)
Gets the current position in the value block.
void _dbus_type_reader_init(DBusTypeReader *reader, int byte_order, const DBusString *type_str, int type_pos, const DBusString *value_str, int value_pos)
Initializes a type reader.
#define EXPECTED_TYPE_OF_FIELD(field)
Macro to look up the correct type for a field.
dbus_bool_t _dbus_validate_error_name(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid error name in the D-Bus protocol.
dbus_bool_t _dbus_header_set_field_basic(DBusHeader *header, int field, int type, const void *value)
Sets the value of a field with basic type.
int _dbus_header_get_message_type(DBusHeader *header)
Gets the type of the message.
dbus_bool_t _dbus_header_get_field_basic(DBusHeader *header, int field, int type, void *value)
Gets the value of a field with basic type.
#define SERIAL_OFFSET
Offset to client serial from start of header.
void _dbus_marshal_set_uint32(DBusString *str, int pos, dbus_uint32_t value, int byte_order)
Sets the 4 bytes at the given offset to a marshaled unsigned integer, replacing anything found there ...
dbus_bool_t _dbus_type_writer_recurse(DBusTypeWriter *writer, int container_type, const DBusString *contained_type, int contained_type_start, DBusTypeWriter *sub)
Opens a new container and writes out the initial information for that container.
#define VERSION_OFFSET
Offset to version from start of header.
dbus_bool_t _dbus_header_get_flag(DBusHeader *header, dbus_uint32_t flag)
Gets a message flag bit, returning TRUE if the bit is set.
void _dbus_marshal_byteswap(const DBusString *signature, int signature_start, int old_byte_order, int new_byte_order, DBusString *value_str, int value_pos)
Byteswaps the marshaled data in the given value_str.
char _dbus_header_get_byte_order(const DBusHeader *header)
Returns the header's byte order.
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)
Given data long enough to contain the length of the message body and the fields array,...
void _dbus_header_reinit(DBusHeader *header)
Re-initializes a header that was previously initialized and never freed.
dbus_uint32_t _dbus_marshal_read_uint32(const DBusString *str, int pos, int byte_order, int *new_pos)
Convenience function to demarshal a 32 bit unsigned integer.
dbus_bool_t _dbus_validate_member(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid member name in the D-Bus protocol.
dbus_bool_t _dbus_type_reader_next(DBusTypeReader *reader)
Skip to the next value on this "level".
dbus_bool_t _dbus_header_delete_field(DBusHeader *header, int field)
Deletes a field, if it exists.
dbus_bool_t _dbus_header_remove_unknown_fields(DBusHeader *header)
Remove every header field not known to this version of dbus.
dbus_uint32_t _dbus_header_get_serial(DBusHeader *header)
See dbus_message_get_serial()
#define FLAGS_OFFSET
Offset to flags from start of header.
#define FIELDS_ARRAY_SIGNATURE_OFFSET
Offset from start of _dbus_header_signature_str to the signature of the fields array.
#define MAX_POSSIBLE_HEADER_PADDING
The most padding we could ever need for a header.
dbus_bool_t _dbus_type_reader_delete(DBusTypeReader *reader, const DBusTypeReader *realign_root)
Recursively deletes any value pointed to by the reader, leaving the reader valid to continue reading.
void _dbus_type_reader_read_basic(const DBusTypeReader *reader, void *value)
Reads a basic-typed value, as with _dbus_marshal_read_basic().
#define BYTE_ORDER_OFFSET
Offset to byte order from start of header.
#define FIRST_FIELD_OFFSET
Offset to first field in header.
dbus_bool_t _dbus_validate_interface(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid interface name in the D-Bus protocol.
dbus_bool_t _dbus_type_reader_set_basic(DBusTypeReader *reader, const void *value, const DBusTypeReader *realign_root)
Sets a new value for the basic type value pointed to by the reader, leaving the reader valid to conti...
DBusValidity _dbus_validate_body_with_reason(const DBusString *expected_signature, int expected_signature_start, int byte_order, int *bytes_remaining, const DBusString *value_str, int value_pos, int len)
Verifies that the range of value_str from value_pos to value_end is a legitimate value of type expect...
void _dbus_marshal_read_basic(const DBusString *str, int pos, int type, void *value, int byte_order, int *new_pos)
Demarshals a basic-typed value.
_DBUS_STRING_DEFINE_STATIC(_dbus_header_signature_str, DBUS_HEADER_SIGNATURE)
Static DBusString containing the signature of a message header.
int _dbus_type_reader_get_current_type(const DBusTypeReader *reader)
Gets the type of the value the reader is currently pointing to; or for a types-only reader gets the t...
void _dbus_header_free(DBusHeader *header)
Frees a header.
dbus_bool_t _dbus_validate_bus_name(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid bus name in the D-Bus protocol.
dbus_bool_t _dbus_header_init(DBusHeader *header)
Initializes a header, but doesn't prepare it for use; to make the header valid, you have to call _dbu...
dbus_bool_t _dbus_header_create(DBusHeader *header, int byte_order, int message_type, const char *destination, const char *path, const char *interface, const char *member, const char *error_name)
Fills in the primary fields of the header, so the header is ready for use.
#define FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET
Offset from start of _dbus_header_signature_str to the signature of an element of the fields array.
dbus_bool_t _dbus_type_writer_unrecurse(DBusTypeWriter *writer, DBusTypeWriter *sub)
Closes a container created by _dbus_type_writer_recurse() and writes any additional information to th...
dbus_bool_t _dbus_type_writer_append_array(DBusTypeWriter *writer, const DBusString *contained_type, int contained_type_start, DBusTypeWriter *sub)
Append to an existing array.
void _dbus_header_toggle_flag(DBusHeader *header, dbus_uint32_t flag, dbus_bool_t value)
Toggles a message flag bit, turning on the bit if value = TRUE and flipping it off if value = FALSE.
void _dbus_header_set_serial(DBusHeader *header, dbus_uint32_t serial)
Sets the serial number of a header.
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)
Creates a message header from potentially-untrusted data.
void _dbus_header_byteswap(DBusHeader *header, int new_order)
Swaps the header into the given order if required.
#define FIELDS_ARRAY_LENGTH_OFFSET
Offset to fields array length from start of header.
#define HEADER_END_BEFORE_PADDING(header)
Compute the end of the header, ignoring padding.
dbus_bool_t _dbus_header_get_field_raw(DBusHeader *header, int field, const DBusString **str, int *pos)
Gets the raw marshaled data for a field.
#define TYPE_OFFSET
Offset to type from start of header.
DBusValidationMode
This is used rather than a bool for high visibility.
@ DBUS_VALIDITY_UNKNOWN_OOM_ERROR
can't determine validity due to OOM
@ DBUS_VALID
the data is valid
#define DBUS_HEADER_FIELD_UNIX_FDS
Header field code for the number of unix file descriptors associated with this message.
#define DBUS_HEADER_FIELD_INVALID
Not equal to any valid header field code.
#define DBUS_MESSAGE_TYPE_METHOD_CALL
Message type of a method call message, see dbus_message_get_type()
#define DBUS_HEADER_FIELD_PATH
Header field code for the path - the path is the object emitting a signal or the object receiving a m...
#define DBUS_HEADER_FIELD_REPLY_SERIAL
Header field code for a reply serial, used to match a DBUS_MESSAGE_TYPE_METHOD_RETURN message with th...
#define DBUS_HEADER_FIELD_CONTAINER_INSTANCE
Header field code for the container instance that sent this message.
#define DBUS_TYPE_SIGNATURE
Type code marking a D-Bus type signature.
#define DBUS_HEADER_FIELD_INTERFACE
Header field code for the interface containing a member (method or signal).
#define DBUS_HEADER_FIELD_MEMBER
Header field code for a member (method or signal).
#define DBUS_MESSAGE_TYPE_ERROR
Message type of an error reply message, see dbus_message_get_type()
#define DBUS_TYPE_OBJECT_PATH
Type code marking a D-Bus object path.
#define DBUS_TYPE_BYTE
Type code marking an 8-bit unsigned integer.
Definition: dbus-protocol.h:66
#define DBUS_HEADER_FIELD_SENDER
Header field code for the sender of a message; usually initialized by the message bus.
#define DBUS_HEADER_FIELD_SIGNATURE
Header field code for the type signature of a message.
#define DBUS_MESSAGE_TYPE_METHOD_RETURN
Message type of a method return message, see dbus_message_get_type()
#define DBUS_TYPE_VARIANT
Type code marking a D-Bus variant type.
#define DBUS_MESSAGE_TYPE_SIGNAL
Message type of a signal message, see dbus_message_get_type()
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
#define DBUS_HEADER_SIGNATURE
Header format is defined as a signature: byte byte order byte message type ID byte flags byte protoco...
#define DBUS_TYPE_ARRAY
Type code marking a D-Bus array type.
#define DBUS_HEADER_FIELD_LAST
Value of the highest-numbered header field code, can be used to determine the size of an array indexe...
#define DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
Definition: dbus-protocol.h:60
#define DBUS_LITTLE_ENDIAN
Code marking LSB-first byte order in the wire protocol.
Definition: dbus-protocol.h:53
#define DBUS_HEADER_FIELD_ERROR_NAME
Header field code for an error name (found in DBUS_MESSAGE_TYPE_ERROR messages).
#define DBUS_MESSAGE_TYPE_INVALID
This value is never a valid message type, see dbus_message_get_type()
#define DBUS_HEADER_FIELD_DESTINATION
Header field code for the destination bus name of a message.
#define DBUS_MAJOR_PROTOCOL_VERSION
Protocol version.
Definition: dbus-protocol.h:57
#define DBUS_TYPE_STRUCT
STRUCT and DICT_ENTRY are sort of special since their codes can't appear in a type string,...
#define DBUS_BIG_ENDIAN
Code marking MSB-first byte order in the wire protocol.
Definition: dbus-protocol.h:54
#define DBUS_TYPE_UINT32
Type code marking a 32-bit unsigned integer.
Definition: dbus-protocol.h:86
#define DBUS_PATH_LOCAL
The object path used in local/in-process-generated messages.
Definition: dbus-shared.h:82
#define DBUS_INTERFACE_LOCAL
This is a special interface whose methods can only be invoked by the local implementation (messages f...
Definition: dbus-shared.h:105
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition: dbus-string.c:833
dbus_bool_t _dbus_string_validate_nul(const DBusString *str, int start, int len)
Checks that the given range of the string is all nul bytes.
Definition: dbus-string.c:2739
dbus_bool_t _dbus_string_equal_substring(const DBusString *a, int a_start, int a_len, const DBusString *b, int b_start)
Tests two sub-parts of two DBusString for equality.
Definition: dbus-string.c:2164
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
Definition: dbus-string.c:1343
dbus_bool_t _dbus_string_init_preallocated(DBusString *str, int allocate_size)
Initializes a string that can be up to the given allocation size before it has to realloc.
Definition: dbus-string.c:139
void _dbus_string_init_const_len(DBusString *str, const char *value, int len)
Initializes a constant string with a length.
Definition: dbus-string.c:217
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as #_DBUS_STRING_I...
Definition: dbus-string.c:278
void _dbus_string_shorten(DBusString *str, int length_to_remove)
Makes a string shorter by the given number of bytes.
Definition: dbus-string.c:811
void _dbus_string_delete(DBusString *str, int start, int len)
Deletes a segment of a DBusString with length len starting at start.
Definition: dbus-string.c:1253
dbus_bool_t _dbus_string_lengthen(DBusString *str, int additional_length)
Makes a string longer by the given number of bytes.
Definition: dbus-string.c:791
dbus_bool_t _dbus_string_align_length(DBusString *str, int alignment)
Align the length of a string to a specific alignment (typically 4 or 8) by appending nul bytes to the...
Definition: dbus-string.c:914
dbus_bool_t _dbus_string_copy_len(const DBusString *source, int start, int len, DBusString *dest, int insert_at)
Like _dbus_string_copy(), but can copy a segment from the middle of the source string.
Definition: dbus-string.c:1435
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
int value_pos
Position of field value, or -1/-2.
Message header data and some cached details of it.
DBusString data
Header network data, stored separately from body so we can independently realloc it.
dbus_uint32_t padding
0-7 bytes of alignment in header, the distance from [B] to [C]
DBusHeaderField fields[DBUS_HEADER_FIELD_LAST+1]
Track the location of each field in header.
The type reader is an iterator for reading values from a block of values.
The type writer is an iterator for writing to a block of values.
int start_pos
position of first element in the array
int value_pos
next position to write
union DBusTypeWriter::@3 u
class-specific data
int len_pos
position of length of the array
DBusString * value_str
where to write values
unsigned char type
the value type
unsigned char code
the field code