25 #include "dbus-marshal-recursive.h"
26 #include "dbus-marshal-basic.h"
27 #include "dbus-signature.h"
28 #include "dbus-internals.h"
36 #define RECURSIVE_MARSHAL_READ_TRACE 0
39 #define RECURSIVE_MARSHAL_WRITE_TRACE 0
63 apply_and_free_fixups (
DBusList **fixups,
68 #if RECURSIVE_MARSHAL_WRITE_TRACE
70 _dbus_verbose (
" %d FIXUPS to apply\n",
87 #if RECURSIVE_MARSHAL_WRITE_TRACE
88 _dbus_verbose (
" applying FIXUP to reader %p at pos %d new_len = %d old len %d\n",
126 element_type_get_alignment (
const DBusString *str,
162 struct_or_dict_entry_types_only_reader_recurse (
DBusTypeReader *sub,
165 base_reader_recurse (sub, parent);
179 struct_or_dict_entry_types_only_reader_recurse (sub, parent);
189 base_reader_recurse (sub, parent);
201 #define ARRAY_READER_LEN_POS(reader) \
202 ((reader)->u.array.start_pos - ((int)(reader)->array_len_offset) - 4)
212 _dbus_assert (_DBUS_ALIGN_VALUE (len_pos, 4) == (
unsigned) len_pos);
216 #if RECURSIVE_MARSHAL_READ_TRACE
217 _dbus_verbose (
" reader %p len_pos %d array len %u len_offset %d\n",
233 array_types_only_reader_recurse (sub, parent);
241 alignment = element_type_get_alignment (sub->
type_str,
250 #if RECURSIVE_MARSHAL_READ_TRACE
251 _dbus_verbose (
" type reader %p array start = %d len_offset = %d array len = %d array element type = %s\n",
253 sub->
u.array.start_pos,
255 array_reader_get_array_len (sub),
266 int contained_alignment;
268 base_reader_recurse (sub, parent);
286 #if RECURSIVE_MARSHAL_READ_TRACE
287 _dbus_verbose (
" type reader %p variant containing '%s'\n",
303 end_pos = reader->
u.array.start_pos + array_reader_get_array_len (reader);
312 skip_one_complete_type (
const DBusString *type_str,
331 const unsigned char *p;
332 const unsigned char *start;
338 p = start + *type_pos;
408 *type_pos = (int) (p - start);
412 find_len_of_complete_type (
const DBusString *type_str,
419 skip_one_complete_type (type_str, &end);
421 return end - type_pos;
428 switch (current_type)
495 base_reader_next (reader, current_type);
516 base_reader_next (reader, current_type);
550 end_pos = reader->
u.array.start_pos + array_reader_get_array_len (reader);
552 #if RECURSIVE_MARSHAL_READ_TRACE
553 _dbus_verbose (
" reader %p array next START start_pos = %d end_pos = %d value_pos = %d current_type = %s\n",
555 reader->
u.array.start_pos,
605 #if RECURSIVE_MARSHAL_READ_TRACE
606 _dbus_verbose (
" reader %p array next END start_pos = %d end_pos = %d value_pos = %d current_type = %s\n",
608 reader->
u.array.start_pos,
617 skip_one_complete_type (reader->
type_str,
641 struct_or_dict_entry_reader_recurse,
649 struct_or_dict_entry_types_only_reader_recurse,
657 struct_or_dict_entry_reader_recurse,
659 dict_entry_reader_next
663 "dict_entry types", 5,
665 struct_or_dict_entry_types_only_reader_recurse,
667 dict_entry_reader_next
673 array_reader_recurse,
674 array_reader_check_finished,
681 array_types_only_reader_recurse,
683 array_types_only_reader_next
689 variant_reader_recurse,
694 #ifndef DBUS_DISABLE_ASSERT
696 all_reader_classes[] = {
698 &body_types_only_reader_class,
699 &struct_reader_class,
700 &struct_types_only_reader_class,
701 &dict_entry_reader_class,
702 &dict_entry_types_only_reader_class,
704 &array_types_only_reader_class,
705 &variant_reader_class
727 reader->
klass = &body_reader_class;
729 reader_init (reader, byte_order, type_str, type_pos,
730 value_str, value_pos);
732 #if RECURSIVE_MARSHAL_READ_TRACE
733 _dbus_verbose (
" type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
752 reader->
klass = &body_types_only_reader_class;
754 reader_init (reader, DBUS_COMPILER_BYTE_ORDER ,
757 #if RECURSIVE_MARSHAL_READ_TRACE
758 _dbus_verbose (
" type reader %p init types only type_pos = %d remaining sig '%s'\n",
791 _dbus_verbose (
" type reader %p current type_pos = %d type = %s\n",
841 const unsigned char **value_location)
873 #if RECURSIVE_MARSHAL_READ_TRACE
874 _dbus_verbose (
" type reader %p read basic type_pos = %d value_pos = %d remaining sig '%s'\n",
892 return array_reader_get_array_len (reader);
934 total_len = array_reader_get_array_len (reader);
935 end_pos = reader->
u.array.start_pos + total_len;
936 remaining_len = end_pos - reader->
value_pos;
938 #if RECURSIVE_MARSHAL_READ_TRACE
939 _dbus_verbose (
"end_pos %d total_len %d remaining_len %d value_pos %d\n",
940 end_pos, total_len, remaining_len, reader->
value_pos);
945 if (remaining_len == 0)
953 *n_elements = remaining_len / alignment;
956 #if RECURSIVE_MARSHAL_READ_TRACE
957 _dbus_verbose (
" type reader %p read fixed array type_pos = %d value_pos = %d remaining sig '%s'\n",
987 sub->
klass = &struct_types_only_reader_class;
989 sub->
klass = &struct_reader_class;
993 sub->
klass = &dict_entry_types_only_reader_class;
995 sub->
klass = &dict_entry_reader_class;
999 sub->
klass = &array_types_only_reader_class;
1001 sub->
klass = &array_reader_class;
1007 sub->
klass = &variant_reader_class;
1011 #ifndef DBUS_DISABLE_CHECKS
1023 #if RECURSIVE_MARSHAL_READ_TRACE
1024 _dbus_verbose (
" type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",
1045 #if RECURSIVE_MARSHAL_READ_TRACE
1046 _dbus_verbose (
" type reader %p START next() { type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
1057 #if RECURSIVE_MARSHAL_READ_TRACE
1058 _dbus_verbose (
" type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
1162 realign_reader = *realign_root;
1164 #if RECURSIVE_MARSHAL_WRITE_TRACE
1165 _dbus_verbose (
"INITIALIZING replacement block writer %p at value_pos %d\n",
1177 #if RECURSIVE_MARSHAL_WRITE_TRACE
1178 _dbus_verbose (
"COPYING from reader at value_pos %d to writer %p starting after value_pos %d\n",
1190 #if RECURSIVE_MARSHAL_WRITE_TRACE
1191 _dbus_verbose (
"REPLACEMENT at padding %d len %d\n", block->
padding,
1195 _dbus_verbose (
"TO BE REPLACED at value_pos = %d (align pad %d) len %d realign_reader.value_pos %d\n",
1215 apply_and_free_fixups (&fixups, reader);
1221 free_fixups (&fixups);
1268 if (!replacement_block_init (&block, reader))
1272 #if RECURSIVE_MARSHAL_WRITE_TRACE
1273 _dbus_verbose (
"INITIALIZING writer %p to write basic value at value_pos %d of replacement string\n",
1282 #if RECURSIVE_MARSHAL_WRITE_TRACE
1283 _dbus_verbose (
"WRITING basic value to writer %p (replacement string)\n", &writer);
1288 if (!replacement_block_replace (&block,
1296 replacement_block_free (&block);
1360 #if RECURSIVE_MARSHAL_WRITE_TRACE
1361 _dbus_verbose (
" SET BASIC type reader %p type_pos = %d value_pos = %d remaining sig '%s' realign_root = %p with value_pos %d current_type = %s\n",
1365 realign_root ? realign_root->
value_pos : -1,
1376 reader_set_basic_fixed_length (reader, current_type, value);
1382 return reader_set_basic_variable_length (reader, current_type,
1383 value, realign_root);
1416 if (!replacement_block_init (&block, reader))
1419 if (!replacement_block_replace (&block,
1427 replacement_block_free (&block);
1494 #if RECURSIVE_MARSHAL_WRITE_TRACE
1495 _dbus_verbose (
"writer %p init remaining sig '%s'\n", writer,
1519 NULL, 0, value_str, value_pos);
1578 value_str, value_pos);
1584 _dbus_type_writer_write_basic_no_typecode (
DBusTypeWriter *writer,
1642 #ifndef DBUS_DISABLE_CHECKS
1653 "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
1659 "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
1668 #if RECURSIVE_MARSHAL_WRITE_TRACE
1669 _dbus_verbose (
" type writer %p recurse parent %s type_pos = %d value_pos = %d is_expectation = %d remaining sig '%s' enabled = %d\n",
1677 _dbus_verbose (
" type writer %p recurse sub %s type_pos = %d value_pos = %d is_expectation = %d enabled = %d\n",
1695 #if RECURSIVE_MARSHAL_WRITE_TRACE
1696 _dbus_verbose (
" type writer %p write_or_verify start type_pos = %d remaining sig '%s' enabled = %d\n",
1709 #ifndef DBUS_DISABLE_CHECKS
1715 if (expected != typecode)
1719 "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
1723 _dbus_warn_check_failed (
"Array or variant type wasn't expecting any more values to be written into it, but a value %s was written.\n"
1724 "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
1749 #if RECURSIVE_MARSHAL_WRITE_TRACE
1750 _dbus_verbose (
" type writer %p write_or_verify end type_pos = %d remaining sig '%s'\n",
1762 int contained_type_start,
1763 int contained_type_len,
1778 if (!write_or_verify_typecode (sub, begin_char))
1798 int contained_type_start,
1799 int contained_type_len,
1807 #ifndef DBUS_DISABLE_CHECKS
1812 contained_type_start,
1815 writer->
u.array.element_type_pos + 1))
1817 _dbus_warn_check_failed (
"Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
1819 contained_type_start,
1820 contained_type_len));
1826 if (writer->
enabled && !is_array_append)
1840 sub->
u.array.element_type_pos = sub->
type_pos;
1857 contained_type_start, contained_type_len,
1859 sub->
u.array.element_type_pos))
1869 writer->
type_pos += 1 + contained_type_len;
1877 sub->
u.array.len_pos = _DBUS_ALIGN_VALUE (sub->
value_pos, 4);
1879 if (is_array_append)
1896 alignment = element_type_get_alignment (contained_type, contained_type_start);
1898 aligned = _DBUS_ALIGN_VALUE (sub->
value_pos, alignment);
1901 if (!is_array_append)
1915 if (is_array_append)
1919 _dbus_assert (_DBUS_ALIGN_VALUE (sub->
u.array.len_pos, 4) ==
1920 (
unsigned) sub->
u.array.len_pos);
1923 sub->
u.array.len_pos,
1932 sub->
u.array.len_pos = -1;
1939 #if RECURSIVE_MARSHAL_WRITE_TRACE
1940 _dbus_verbose (
" type writer %p recurse array done remaining sig '%s' array start_pos = %d len_pos = %d value_pos = %d\n", sub,
1944 sub->
u.array.start_pos, sub->
u.array.len_pos, sub->
value_pos);
1971 int contained_type_start,
1972 int contained_type_len,
1975 int contained_alignment;
2005 contained_type_len))
2043 int contained_type_start,
2044 int contained_type_len,
2048 writer_recurse_init_and_check (writer, container_type, sub);
2050 switch (container_type)
2053 return writer_recurse_struct_or_dict_entry (writer,
2056 contained_type_start, contained_type_len,
2060 return writer_recurse_struct_or_dict_entry (writer,
2063 contained_type_start, contained_type_len,
2067 return writer_recurse_array (writer,
2068 contained_type, contained_type_start, contained_type_len,
2069 sub, is_array_append);
2072 return writer_recurse_variant (writer,
2073 contained_type, contained_type_start, contained_type_len,
2097 int contained_type_start,
2100 int contained_type_len;
2103 contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
2105 contained_type_len = 0;
2107 return _dbus_type_writer_recurse_contained_len (writer, container_type,
2109 contained_type_start,
2130 int contained_type_start,
2133 int contained_type_len;
2136 contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
2138 contained_type_len = 0;
2140 return _dbus_type_writer_recurse_contained_len (writer,
DBUS_TYPE_ARRAY,
2142 contained_type_start,
2152 return writer->
value_pos - writer->
u.array.start_pos;
2171 #if RECURSIVE_MARSHAL_WRITE_TRACE
2172 _dbus_verbose (
" type writer %p unrecurse type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
2175 _dbus_verbose (
" type writer %p unrecurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
2193 if (sub->
u.array.len_pos >= 0)
2198 len = writer_get_array_len (sub);
2200 sub->
u.array.len_pos,
2203 #if RECURSIVE_MARSHAL_WRITE_TRACE
2204 _dbus_verbose (
" filled in sub array len to %u at len_pos %d\n",
2205 len, sub->
u.array.len_pos);
2208 #if RECURSIVE_MARSHAL_WRITE_TRACE
2211 _dbus_verbose (
" not filling in sub array len because we were disabled when we passed the len\n");
2276 #if RECURSIVE_MARSHAL_WRITE_TRACE
2277 _dbus_verbose (
" type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
2311 if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
2314 if (!write_or_verify_typecode (writer, type))
2320 #if RECURSIVE_MARSHAL_WRITE_TRACE
2321 _dbus_verbose (
" type writer %p basic type_pos = %d value_pos = %d is_expectation = %d enabled = %d\n",
2354 #if RECURSIVE_MARSHAL_WRITE_TRACE
2355 _dbus_verbose (
" type writer %p entering fixed multi type_pos = %d value_pos = %d n_elements %d\n",
2359 if (!write_or_verify_typecode (writer, element_type))
2374 #if RECURSIVE_MARSHAL_WRITE_TRACE
2375 _dbus_verbose (
" type writer %p fixed multi written new type_pos = %d new value_pos = %d n_elements %d\n",
2392 #if RECURSIVE_MARSHAL_WRITE_TRACE
2393 _dbus_verbose (
"ENABLING writer %p at %d because reader at value_pos %d is after reader at value_pos %d\n",
2434 int start_after_new_pos,
2435 int start_after_new_len,
2452 int reader_array_len_pos;
2453 int reader_array_start_pos;
2461 if (!inside_start_after && start_after &&
2465 this_is_start_after =
TRUE;
2467 this_is_start_after =
FALSE;
2474 reader_array_start_pos = subreader.
u.array.start_pos;
2479 reader_array_len_pos = -1;
2480 reader_array_start_pos = -1;
2484 &sig_start, &sig_len);
2486 #if RECURSIVE_MARSHAL_WRITE_TRACE
2487 _dbus_verbose (
"about to recurse into %s reader at %d subreader at %d writer at %d start_after reader at %d write target len %d inside_start_after = %d this_is_start_after = %d\n",
2492 start_after ? start_after->
value_pos : -1,
2494 inside_start_after, this_is_start_after);
2497 if (!inside_start_after && !this_is_start_after)
2498 enable_if_after (writer, &subreader, start_after);
2499 enabled_at_recurse = writer->
enabled;
2500 if (!_dbus_type_writer_recurse_contained_len (writer, current_type,
2501 sig_str, sig_start, sig_len,
2505 #if RECURSIVE_MARSHAL_WRITE_TRACE
2506 _dbus_verbose (
"recursed into subwriter at %d write target len %d\n",
2511 if (!writer_write_reader_helper (&subwriter, &subreader, start_after,
2512 start_after_new_pos, start_after_new_len,
2514 inside_start_after ||
2515 this_is_start_after))
2518 #if RECURSIVE_MARSHAL_WRITE_TRACE
2519 _dbus_verbose (
"about to unrecurse from %s subreader at %d writer at %d subwriter at %d write target len %d\n",
2527 if (!inside_start_after && !this_is_start_after)
2528 enable_if_after (writer, &subreader, start_after);
2529 past_start_after = writer->
enabled;
2538 if (start_after !=
NULL &&
2539 !enabled_at_recurse && past_start_after &&
2544 int bytes_written_after_start_after;
2545 int bytes_before_start_after;
2552 bytes_written_after_start_after = writer_get_array_len (&subwriter);
2554 bytes_before_start_after =
2555 start_after->
value_pos - reader_array_start_pos;
2559 bytes_before_start_after +
2560 start_after_new_len +
2561 bytes_written_after_start_after;
2570 if (old_len != fixup.
new_len && !append_fixup (fixups, &fixup))
2573 #if RECURSIVE_MARSHAL_WRITE_TRACE
2574 _dbus_verbose (
"Generated fixup len_pos_in_reader = %d new_len = %d reader_array_start_pos = %d start_after->value_pos = %d bytes_before_start_after = %d start_after_new_len = %d bytes_written_after_start_after = %d\n",
2577 reader_array_start_pos,
2579 bytes_before_start_after,
2580 start_after_new_len,
2581 bytes_written_after_start_after);
2591 #if RECURSIVE_MARSHAL_WRITE_TRACE
2592 _dbus_verbose (
"Reading basic value %s at %d\n",
2599 #if RECURSIVE_MARSHAL_WRITE_TRACE
2600 _dbus_verbose (
"Writing basic value %s at %d write target len %d inside_start_after = %d\n",
2604 inside_start_after);
2606 if (!inside_start_after)
2607 enable_if_after (writer, reader, start_after);
2610 #if RECURSIVE_MARSHAL_WRITE_TRACE
2611 _dbus_verbose (
"Wrote basic value %s, new value_pos %d write target len %d\n",
2625 apply_and_free_fixups (fixups,
NULL);
2665 int start_after_new_pos,
2666 int start_after_new_len,
2678 orig_enabled = writer->
enabled;
2683 if (!writer_write_reader_helper (writer, reader, start_after,
2684 start_after_new_pos,
2685 start_after_new_len,