25 #include "dbus-marshal-recursive.h"
26 #include "dbus-marshal-basic.h"
27 #include "dbus-signature.h"
28 #include "dbus-internals.h"
43 int start_after_new_pos,
44 int start_after_new_len,
48 #define RECURSIVE_MARSHAL_READ_TRACE 0
51 #define RECURSIVE_MARSHAL_WRITE_TRACE 0
75 apply_and_free_fixups (
DBusList **fixups,
80 #if RECURSIVE_MARSHAL_WRITE_TRACE
82 _dbus_verbose (
" %d FIXUPS to apply\n",
99 #if RECURSIVE_MARSHAL_WRITE_TRACE
100 _dbus_verbose (
" applying FIXUP to reader %p at pos %d new_len = %d old len %d\n",
138 element_type_get_alignment (
const DBusString *str,
175 struct_or_dict_entry_types_only_reader_recurse (
DBusTypeReader *sub,
178 base_reader_recurse (sub, parent);
192 struct_or_dict_entry_types_only_reader_recurse (sub, parent);
202 base_reader_recurse (sub, parent);
214 #define ARRAY_READER_LEN_POS(reader) \
215 ((reader)->u.array.start_pos - ((int)(reader)->array_len_offset) - 4)
225 _dbus_assert (_DBUS_ALIGN_VALUE (len_pos, 4) == (
unsigned) len_pos);
227 _dbus_string_get_const_udata_len (reader->
value_str, len_pos, 4));
229 #if RECURSIVE_MARSHAL_READ_TRACE
230 _dbus_verbose (
" reader %p len_pos %d array len %u len_offset %d\n",
246 array_types_only_reader_recurse (sub, parent);
254 alignment = element_type_get_alignment (sub->
type_str,
263 #if RECURSIVE_MARSHAL_READ_TRACE
264 _dbus_verbose (
" type reader %p array start = %d len_offset = %d array len = %d array element type = %s\n",
266 sub->
u.array.start_pos,
268 array_reader_get_array_len (sub),
279 int contained_alignment;
281 base_reader_recurse (sub, parent);
299 #if RECURSIVE_MARSHAL_READ_TRACE
300 _dbus_verbose (
" type reader %p variant containing '%s'\n",
316 end_pos = reader->
u.array.start_pos + array_reader_get_array_len (reader);
325 skip_one_complete_type (
const DBusString *type_str,
344 const unsigned char *p;
345 const unsigned char *start;
350 start = (
const unsigned char *)type_str;
351 p = start + *type_pos;
421 *type_pos = (int) (p - start);
425 find_len_of_complete_type (
const DBusString *type_str,
432 skip_one_complete_type (type_str, &end);
434 return end - type_pos;
441 switch (current_type)
508 base_reader_next (reader, current_type);
529 base_reader_next (reader, current_type);
563 end_pos = reader->
u.array.start_pos + array_reader_get_array_len (reader);
565 #if RECURSIVE_MARSHAL_READ_TRACE
566 _dbus_verbose (
" reader %p array next START start_pos = %d end_pos = %d value_pos = %d current_type = %s\n",
568 reader->
u.array.start_pos,
618 #if RECURSIVE_MARSHAL_READ_TRACE
619 _dbus_verbose (
" reader %p array next END start_pos = %d end_pos = %d value_pos = %d current_type = %s\n",
621 reader->
u.array.start_pos,
630 skip_one_complete_type (reader->
type_str,
654 struct_or_dict_entry_reader_recurse,
662 struct_or_dict_entry_types_only_reader_recurse,
670 struct_or_dict_entry_reader_recurse,
672 dict_entry_reader_next
676 "dict_entry types", 5,
678 struct_or_dict_entry_types_only_reader_recurse,
680 dict_entry_reader_next
686 array_reader_recurse,
687 array_reader_check_finished,
694 array_types_only_reader_recurse,
696 array_types_only_reader_next
702 variant_reader_recurse,
707 #ifndef DBUS_DISABLE_ASSERT
709 all_reader_classes[] = {
711 &body_types_only_reader_class,
712 &struct_reader_class,
713 &struct_types_only_reader_class,
714 &dict_entry_reader_class,
715 &dict_entry_types_only_reader_class,
717 &array_types_only_reader_class,
718 &variant_reader_class
740 reader_init (reader, byte_order, type_str, type_pos,
741 value_str, value_pos);
743 reader->
klass = &body_reader_class;
745 #if RECURSIVE_MARSHAL_READ_TRACE
746 _dbus_verbose (
" type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
765 reader_init (reader, DBUS_COMPILER_BYTE_ORDER ,
768 reader->
klass = &body_types_only_reader_class;
770 #if RECURSIVE_MARSHAL_READ_TRACE
771 _dbus_verbose (
" type reader %p init types only type_pos = %d remaining sig '%s'\n",
804 _dbus_verbose (
" type reader %p current type_pos = %d type = %s\n",
854 const unsigned char **value_location)
858 *value_location = _dbus_string_get_const_udata_len (reader->
value_str,
886 #if RECURSIVE_MARSHAL_READ_TRACE
887 _dbus_verbose (
" type reader %p read basic type_pos = %d value_pos = %d remaining sig '%s'\n",
905 return array_reader_get_array_len (reader);
947 total_len = array_reader_get_array_len (reader);
948 end_pos = reader->
u.array.start_pos + total_len;
949 remaining_len = end_pos - reader->
value_pos;
951 #if RECURSIVE_MARSHAL_READ_TRACE
952 _dbus_verbose (
"end_pos %d total_len %d remaining_len %d value_pos %d\n",
953 end_pos, total_len, remaining_len, reader->
value_pos);
958 if (remaining_len == 0)
966 *n_elements = remaining_len / alignment;
969 #if RECURSIVE_MARSHAL_READ_TRACE
970 _dbus_verbose (
" type reader %p read fixed array type_pos = %d value_pos = %d remaining sig '%s'\n",
1001 klass = &struct_types_only_reader_class;
1003 klass = &struct_reader_class;
1007 klass = &dict_entry_types_only_reader_class;
1009 klass = &dict_entry_reader_class;
1013 klass = &array_types_only_reader_class;
1015 klass = &array_reader_class;
1021 klass = &variant_reader_class;
1025 #ifndef DBUS_DISABLE_CHECKS
1036 (* klass->
recurse) (sub, reader);
1039 #if RECURSIVE_MARSHAL_READ_TRACE
1040 _dbus_verbose (
" type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",
1061 #if RECURSIVE_MARSHAL_READ_TRACE
1062 _dbus_verbose (
" type reader %p START next() { type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
1073 #if RECURSIVE_MARSHAL_READ_TRACE
1074 _dbus_verbose (
" type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
1178 realign_reader = *realign_root;
1180 #if RECURSIVE_MARSHAL_WRITE_TRACE
1181 _dbus_verbose (
"INITIALIZING replacement block writer %p at value_pos %d\n",
1193 #if RECURSIVE_MARSHAL_WRITE_TRACE
1194 _dbus_verbose (
"COPYING from reader at value_pos %d to writer %p starting after value_pos %d\n",
1198 if (!_dbus_type_writer_write_reader_partial (&writer,
1206 #if RECURSIVE_MARSHAL_WRITE_TRACE
1207 _dbus_verbose (
"REPLACEMENT at padding %d len %d\n", block->
padding,
1211 _dbus_verbose (
"TO BE REPLACED at value_pos = %d (align pad %d) len %d realign_reader.value_pos %d\n",
1231 apply_and_free_fixups (&fixups, reader);
1237 free_fixups (&fixups);
1284 if (!replacement_block_init (&block, reader))
1288 #if RECURSIVE_MARSHAL_WRITE_TRACE
1289 _dbus_verbose (
"INITIALIZING writer %p to write basic value at value_pos %d of replacement string\n",
1298 #if RECURSIVE_MARSHAL_WRITE_TRACE
1299 _dbus_verbose (
"WRITING basic value to writer %p (replacement string)\n", &writer);
1304 if (!replacement_block_replace (&block,
1312 replacement_block_free (&block);
1376 #if RECURSIVE_MARSHAL_WRITE_TRACE
1377 _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",
1381 realign_root ? realign_root->
value_pos : -1,
1392 reader_set_basic_fixed_length (reader, current_type, value);
1398 return reader_set_basic_variable_length (reader, current_type,
1399 value, realign_root);
1432 if (!replacement_block_init (&block, reader))
1435 if (!replacement_block_replace (&block,
1443 replacement_block_free (&block);
1510 #if RECURSIVE_MARSHAL_WRITE_TRACE
1511 _dbus_verbose (
"writer %p init remaining sig '%s'\n", writer,
1535 NULL, 0, value_str, value_pos);
1594 value_str, value_pos);
1600 _dbus_type_writer_write_basic_no_typecode (
DBusTypeWriter *writer,
1658 #ifndef DBUS_DISABLE_CHECKS
1669 "The overall signature expected here was '%s' and we are on byte %d of that signature.",
1675 "The overall signature expected here was '%s' and we are on byte %d of that signature.",
1684 #if RECURSIVE_MARSHAL_WRITE_TRACE
1685 _dbus_verbose (
" type writer %p recurse parent %s type_pos = %d value_pos = %d is_expectation = %d remaining sig '%s' enabled = %d\n",
1693 _dbus_verbose (
" type writer %p recurse sub %s type_pos = %d value_pos = %d is_expectation = %d enabled = %d\n",
1711 #if RECURSIVE_MARSHAL_WRITE_TRACE
1712 _dbus_verbose (
" type writer %p write_or_verify start type_pos = %d remaining sig '%s' enabled = %d\n",
1725 #ifndef DBUS_DISABLE_CHECKS
1731 if (expected != typecode)
1735 "The overall signature expected here was '%s' and we are on byte %d of that signature.",
1739 _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"
1740 "The overall signature expected here was '%s' and we are on byte %d of that signature.",
1765 #if RECURSIVE_MARSHAL_WRITE_TRACE
1766 _dbus_verbose (
" type writer %p write_or_verify end type_pos = %d remaining sig '%s'\n",
1778 int contained_type_start,
1779 int contained_type_len,
1794 if (!write_or_verify_typecode (sub, begin_char))
1814 int contained_type_start,
1815 int contained_type_len,
1823 #ifndef DBUS_DISABLE_CHECKS
1828 contained_type_start,
1831 writer->
u.array.element_type_pos + 1))
1833 _dbus_warn_check_failed (
"Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array",
1835 contained_type_start,
1836 contained_type_len));
1842 if (writer->
enabled && !is_array_append)
1856 sub->
u.array.element_type_pos = sub->
type_pos;
1873 contained_type_start, contained_type_len,
1875 sub->
u.array.element_type_pos))
1885 writer->
type_pos += 1 + contained_type_len;
1893 sub->
u.array.len_pos = _DBUS_ALIGN_VALUE (sub->
value_pos, 4);
1895 if (is_array_append)
1912 alignment = element_type_get_alignment (contained_type, contained_type_start);
1914 aligned = _DBUS_ALIGN_VALUE (sub->
value_pos, alignment);
1917 if (!is_array_append)
1931 if (is_array_append)
1935 _dbus_assert (_DBUS_ALIGN_VALUE (sub->
u.array.len_pos, 4) ==
1936 (
unsigned) sub->
u.array.len_pos);
1938 _dbus_string_get_const_udata_len (sub->
value_str,
1939 sub->
u.array.len_pos,
1948 sub->
u.array.len_pos = -1;
1955 #if RECURSIVE_MARSHAL_WRITE_TRACE
1956 _dbus_verbose (
" type writer %p recurse array done remaining sig '%s' array start_pos = %d len_pos = %d value_pos = %d\n", sub,
1960 sub->
u.array.start_pos, sub->
u.array.len_pos, sub->
value_pos);
1987 int contained_type_start,
1988 int contained_type_len,
1991 int contained_alignment;
2021 contained_type_len))
2059 int contained_type_start,
2060 int contained_type_len,
2064 writer_recurse_init_and_check (writer, container_type, sub);
2066 switch (container_type)
2069 return writer_recurse_struct_or_dict_entry (writer,
2072 contained_type_start, contained_type_len,
2076 return writer_recurse_struct_or_dict_entry (writer,
2079 contained_type_start, contained_type_len,
2083 return writer_recurse_array (writer,
2084 contained_type, contained_type_start, contained_type_len,
2085 sub, is_array_append);
2088 return writer_recurse_variant (writer,
2089 contained_type, contained_type_start, contained_type_len,
2113 int contained_type_start,
2116 int contained_type_len;
2119 contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
2121 contained_type_len = 0;
2123 return _dbus_type_writer_recurse_contained_len (writer, container_type,
2125 contained_type_start,
2146 int contained_type_start,
2149 int contained_type_len;
2152 contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
2154 contained_type_len = 0;
2156 return _dbus_type_writer_recurse_contained_len (writer,
DBUS_TYPE_ARRAY,
2158 contained_type_start,
2168 return writer->
value_pos - writer->
u.array.start_pos;
2187 #if RECURSIVE_MARSHAL_WRITE_TRACE
2188 _dbus_verbose (
" type writer %p unrecurse type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
2191 _dbus_verbose (
" type writer %p unrecurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
2209 if (sub->
u.array.len_pos >= 0)
2214 len = writer_get_array_len (sub);
2216 sub->
u.array.len_pos,
2219 #if RECURSIVE_MARSHAL_WRITE_TRACE
2220 _dbus_verbose (
" filled in sub array len to %u at len_pos %d\n",
2221 len, sub->
u.array.len_pos);
2224 #if RECURSIVE_MARSHAL_WRITE_TRACE
2227 _dbus_verbose (
" not filling in sub array len because we were disabled when we passed the len\n");
2292 #if RECURSIVE_MARSHAL_WRITE_TRACE
2293 _dbus_verbose (
" type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
2327 if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
2330 if (!write_or_verify_typecode (writer, type))
2336 #if RECURSIVE_MARSHAL_WRITE_TRACE
2337 _dbus_verbose (
" type writer %p basic type_pos = %d value_pos = %d is_expectation = %d enabled = %d\n",
2370 #if RECURSIVE_MARSHAL_WRITE_TRACE
2371 _dbus_verbose (
" type writer %p entering fixed multi type_pos = %d value_pos = %d n_elements %d\n",
2375 if (!write_or_verify_typecode (writer, element_type))
2390 #if RECURSIVE_MARSHAL_WRITE_TRACE
2391 _dbus_verbose (
" type writer %p fixed multi written new type_pos = %d new value_pos = %d n_elements %d\n",
2405 if (!writer->
enabled && _dbus_type_reader_greater_than (reader, start_after))
2407 _dbus_type_writer_set_enabled (writer,
TRUE);
2408 #if RECURSIVE_MARSHAL_WRITE_TRACE
2409 _dbus_verbose (
"ENABLING writer %p at %d because reader at value_pos %d is after reader at value_pos %d\n",
2414 _dbus_assert ((!writer->
enabled && !_dbus_type_reader_greater_than (reader, start_after)) ||
2415 (writer->
enabled && _dbus_type_reader_greater_than (reader, start_after)));
2450 int start_after_new_pos,
2451 int start_after_new_len,
2468 int reader_array_len_pos;
2469 int reader_array_start_pos;
2477 if (!inside_start_after && start_after &&
2481 this_is_start_after =
TRUE;
2483 this_is_start_after =
FALSE;
2490 reader_array_start_pos = subreader.
u.array.start_pos;
2495 reader_array_len_pos = -1;
2496 reader_array_start_pos = -1;
2500 &sig_start, &sig_len);
2502 #if RECURSIVE_MARSHAL_WRITE_TRACE
2503 _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",
2508 start_after ? start_after->
value_pos : -1,
2510 inside_start_after, this_is_start_after);
2513 if (!inside_start_after && !this_is_start_after)
2514 enable_if_after (writer, &subreader, start_after);
2515 enabled_at_recurse = writer->
enabled;
2516 if (!_dbus_type_writer_recurse_contained_len (writer, current_type,
2517 sig_str, sig_start, sig_len,
2521 #if RECURSIVE_MARSHAL_WRITE_TRACE
2522 _dbus_verbose (
"recursed into subwriter at %d write target len %d\n",
2527 if (!writer_write_reader_helper (&subwriter, &subreader, start_after,
2528 start_after_new_pos, start_after_new_len,
2530 inside_start_after ||
2531 this_is_start_after))
2534 #if RECURSIVE_MARSHAL_WRITE_TRACE
2535 _dbus_verbose (
"about to unrecurse from %s subreader at %d writer at %d subwriter at %d write target len %d\n",
2543 if (!inside_start_after && !this_is_start_after)
2544 enable_if_after (writer, &subreader, start_after);
2545 past_start_after = writer->
enabled;
2554 if (start_after !=
NULL &&
2555 !enabled_at_recurse && past_start_after &&
2560 int bytes_written_after_start_after;
2561 int bytes_before_start_after;
2568 bytes_written_after_start_after = writer_get_array_len (&subwriter);
2570 bytes_before_start_after =
2571 start_after->
value_pos - reader_array_start_pos;
2575 bytes_before_start_after +
2576 start_after_new_len +
2577 bytes_written_after_start_after;
2583 _dbus_string_get_const_udata_len (reader->
value_str,
2586 if (old_len != fixup.
new_len && !append_fixup (fixups, &fixup))
2589 #if RECURSIVE_MARSHAL_WRITE_TRACE
2590 _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",
2593 reader_array_start_pos,
2595 bytes_before_start_after,
2596 start_after_new_len,
2597 bytes_written_after_start_after);
2607 #if RECURSIVE_MARSHAL_WRITE_TRACE
2608 _dbus_verbose (
"Reading basic value %s at %d\n",
2615 #if RECURSIVE_MARSHAL_WRITE_TRACE
2616 _dbus_verbose (
"Writing basic value %s at %d write target len %d inside_start_after = %d\n",
2620 inside_start_after);
2622 if (!inside_start_after)
2623 enable_if_after (writer, reader, start_after);
2626 #if RECURSIVE_MARSHAL_WRITE_TRACE
2627 _dbus_verbose (
"Wrote basic value %s, new value_pos %d write target len %d\n",
2641 apply_and_free_fixups (fixups,
NULL);
2681 int start_after_new_pos,
2682 int start_after_new_len,
2694 orig_enabled = writer->
enabled;
2697 _dbus_type_writer_set_enabled (writer,
FALSE);
2699 if (!writer_write_reader_helper (writer, reader, start_after,
2700 start_after_new_pos,
2701 start_after_new_len,
2705 _dbus_type_writer_set_enabled (writer, orig_enabled);
2735 return _dbus_type_writer_write_reader_partial (writer, reader,
NULL, 0, 0,
NULL);