summaryrefslogtreecommitdiffstats
path: root/dbus/dbus-marshal-recursive.c
diff options
context:
space:
mode:
Diffstat (limited to 'dbus/dbus-marshal-recursive.c')
-rw-r--r--dbus/dbus-marshal-recursive.c860
1 files changed, 763 insertions, 97 deletions
diff --git a/dbus/dbus-marshal-recursive.c b/dbus/dbus-marshal-recursive.c
index e2823152..58cab0c2 100644
--- a/dbus/dbus-marshal-recursive.c
+++ b/dbus/dbus-marshal-recursive.c
@@ -29,7 +29,55 @@
* @addtogroup DBusMarshal
* @{
*/
-#define RECURSIVE_MARSHAL_TRACE 1
+#define RECURSIVE_MARSHAL_TRACE 0
+
+static void
+apply_and_free_fixups (DBusList **fixups,
+ DBusTypeReader *reader)
+{
+ DBusList *link;
+
+#if RECURSIVE_MARSHAL_TRACE
+ if (*fixups)
+ _dbus_verbose (" %d FIXUPS to apply\n",
+ _dbus_list_get_length (fixups));
+#endif
+
+ link = _dbus_list_get_first_link (fixups);
+ while (link != NULL)
+ {
+ DBusList *next;
+
+ next = _dbus_list_get_next_link (fixups, link);
+
+ if (reader)
+ {
+ DBusArrayLenFixup *f;
+
+ f = link->data;
+
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose (" applying FIXUP to reader %p at pos %d new_len = %d old len %d\n",
+ reader, f->len_pos_in_reader, f->new_len,
+ _dbus_marshal_read_uint32 (reader->value_str,
+ f->len_pos_in_reader,
+ reader->byte_order, NULL));
+#endif
+
+ _dbus_marshal_set_uint32 ((DBusString*) reader->value_str,
+ f->len_pos_in_reader,
+ f->new_len,
+ reader->byte_order);
+ }
+
+ dbus_free (link->data);
+ _dbus_list_free_link (link);
+
+ link = next;
+ }
+
+ *fixups = NULL;
+}
struct DBusTypeReaderClass
{
@@ -131,14 +179,17 @@ array_types_only_reader_recurse (DBusTypeReader *sub,
sub->array_len_offset = 7;
}
+/* array_len_offset is the offset back from start_pos to end of the len */
+#define ARRAY_READER_LEN_POS(reader) \
+ ((reader)->u.array.start_pos - ((int)(reader)->array_len_offset) - 4)
+
static int
array_reader_get_array_len (const DBusTypeReader *reader)
{
dbus_uint32_t array_len;
int len_pos;
- /* array_len_offset is the offset back from start_pos to end of the len */
- len_pos = reader->u.array.start_pos - ((int)reader->array_len_offset) - 4;
+ len_pos = ARRAY_READER_LEN_POS (reader);
_dbus_marshal_read_basic (reader->value_str,
len_pos,
@@ -384,6 +435,14 @@ array_reader_next (DBusTypeReader *reader,
end_pos = reader->u.array.start_pos + array_reader_get_array_len (reader);
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose (" reader %p array next START start_pos = %d end_pos = %d value_pos = %d current_type = %s\n",
+ reader,
+ reader->u.array.start_pos,
+ end_pos, reader->value_pos,
+ _dbus_type_to_string (current_type));
+#endif
+
_dbus_assert (reader->value_pos < end_pos);
_dbus_assert (reader->value_pos >= reader->u.array.start_pos);
@@ -428,6 +487,14 @@ array_reader_next (DBusTypeReader *reader,
break;
}
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose (" reader %p array next END start_pos = %d end_pos = %d value_pos = %d current_type = %s\n",
+ reader,
+ reader->u.array.start_pos,
+ end_pos, reader->value_pos,
+ _dbus_type_to_string (current_type));
+#endif
+
_dbus_assert (reader->value_pos <= end_pos);
if (reader->value_pos == end_pos)
@@ -859,6 +926,7 @@ _dbus_type_reader_get_signature (const DBusTypeReader *reader,
}
+
/* In the variable-length case, we have to fix alignment after we insert.
* The strategy is as follows:
*
@@ -878,6 +946,9 @@ _dbus_type_reader_get_signature (const DBusTypeReader *reader,
* - copy the new string back to the original
* string, replacing the relevant part of the
* original string
+ * - now any arrays in the original string that
+ * contained the replaced string may have the
+ * wrong length; so we have to fix that
*/
static dbus_bool_t
reader_set_basic_variable_length (DBusTypeReader *reader,
@@ -890,6 +961,7 @@ reader_set_basic_variable_length (DBusTypeReader *reader,
int padding;
DBusTypeWriter writer;
DBusTypeReader realign_reader;
+ DBusList *fixups;
_dbus_assert (realign_root != NULL);
@@ -932,11 +1004,28 @@ reader_set_basic_variable_length (DBusTypeReader *reader,
&replacement,
_dbus_string_get_length (&replacement));
- if (!_dbus_type_writer_write_reader (&writer,
- &realign_reader,
- reader))
+ fixups = NULL;
+ if (!_dbus_type_writer_write_reader_partial (&writer,
+ &realign_reader,
+ reader,
+ padding,
+ _dbus_string_get_length (&replacement) - padding,
+ &fixups))
goto out;
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose ("REPLACEMENT at padding %d len %d\n", padding,
+ _dbus_string_get_length (&replacement) - padding);
+ _dbus_verbose_bytes_of_string (&replacement, padding,
+ _dbus_string_get_length (&replacement) - padding);
+ _dbus_verbose ("TO BE REPLACED at value_pos = %d (align pad %d) len %d\n",
+ reader->value_pos, (int) (8 - _DBUS_ALIGN_OFFSET (reader->value_pos, 8)),
+ realign_reader.value_pos - reader->value_pos);
+ _dbus_verbose_bytes_of_string (reader->value_str,
+ reader->value_pos,
+ realign_reader.value_pos - reader->value_pos);
+#endif
+
/* Move the replacement into position
* (realign_reader should now be at the end of the block to be replaced)
*/
@@ -947,6 +1036,9 @@ reader_set_basic_variable_length (DBusTypeReader *reader,
realign_reader.value_pos - reader->value_pos))
goto out;
+ /* Process our fixups now that we can't have an OOM error */
+ apply_and_free_fixups (&fixups, reader);
+
retval = TRUE;
out:
@@ -1006,6 +1098,15 @@ _dbus_type_reader_set_basic (DBusTypeReader *reader,
current_type = _dbus_type_reader_get_current_type (reader);
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose (" type reader %p set basic type_pos = %d value_pos = %d remaining sig '%s' realign_root = %p with value_pos %d current_type = %s\n",
+ reader, reader->type_pos, reader->value_pos,
+ _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
+ realign_root,
+ realign_root ? realign_root->value_pos : -1,
+ _dbus_type_to_string (current_type));
+#endif
+
_dbus_assert (_dbus_type_is_basic (current_type));
if (_dbus_type_length_varies (current_type))
@@ -1418,10 +1519,6 @@ writer_recurse_array (DBusTypeWriter *writer,
sub->value_pos = aligned;
}
- sub->u.array.start_pos = sub->value_pos;
-
- _dbus_assert (sub->u.array.start_pos == sub->value_pos);
- _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
#if RECURSIVE_MARSHAL_TRACE
_dbus_verbose (" type writer %p recurse array done remaining sig '%s' array start_pos = %d len_pos = %d\n", sub,
@@ -1431,6 +1528,15 @@ writer_recurse_array (DBusTypeWriter *writer,
sub->u.array.start_pos, sub->u.array.len_pos);
#endif
}
+ else
+ {
+ /* not enabled, so we won't write the len_pos; set it to -1 to so indicate */
+ sub->u.array.len_pos = -1;
+ }
+
+ sub->u.array.start_pos = sub->value_pos;
+ _dbus_assert (sub->u.array.start_pos == sub->value_pos);
+ _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
return TRUE;
}
@@ -1584,12 +1690,17 @@ _dbus_type_writer_recurse (DBusTypeWriter *writer,
sub);
}
+static int
+writer_get_array_len (DBusTypeWriter *writer)
+{
+ _dbus_assert (writer->container_type == DBUS_TYPE_ARRAY);
+ return writer->value_pos - writer->u.array.start_pos;
+}
+
dbus_bool_t
_dbus_type_writer_unrecurse (DBusTypeWriter *writer,
DBusTypeWriter *sub)
{
- _dbus_assert (sub->type_pos > 0); /* can't be recursed if this fails */
-
/* type_pos_is_expectation never gets unset once set, or we'd get all hosed */
_dbus_assert (!writer->type_pos_is_expectation ||
(writer->type_pos_is_expectation && sub->type_pos_is_expectation));
@@ -1611,12 +1722,12 @@ _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
}
else if (sub->container_type == DBUS_TYPE_ARRAY)
{
- if (sub->enabled)
+ if (sub->u.array.len_pos >= 0) /* len_pos == -1 if we weren't enabled when we passed it */
{
dbus_uint32_t len;
/* Set the array length */
- len = sub->value_pos - sub->u.array.start_pos;
+ len = writer_get_array_len (sub);
_dbus_marshal_set_uint32 (sub->value_str,
sub->u.array.len_pos,
len,
@@ -1624,6 +1735,12 @@ _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
#if RECURSIVE_MARSHAL_TRACE
_dbus_verbose (" filled in sub array len to %u at len_pos %d\n",
len, sub->u.array.len_pos);
+#endif
+ }
+#if RECURSIVE_MARSHAL_TRACE
+ else
+ {
+ _dbus_verbose (" not filling in sub array len because we were disabled when we passed the len\n");
}
#endif
}
@@ -1737,42 +1854,64 @@ _dbus_type_writer_write_array (DBusTypeWriter *writer,
}
-/**
- * Iterate through all values in the given reader, writing a copy of
- * each value to the writer. The reader will be moved forward to its
- * end position.
- *
- * If a reader start_after is provided, it should be a reader for the
- * same data as the reader to be written. Only values occurring after
- * the value pointed to by start_after will be written to the writer.
- *
- * @param writer the writer to copy to
- * @param reader the reader to copy from
- * @param start_after #NULL or a reader showing where to start
- */
-dbus_bool_t
-_dbus_type_writer_write_reader (DBusTypeWriter *writer,
- DBusTypeReader *reader,
- const DBusTypeReader *start_after)
+static void
+enable_if_after (DBusTypeWriter *writer,
+ DBusTypeReader *reader,
+ const DBusTypeReader *start_after)
{
- DBusTypeWriter orig;
- int orig_type_len;
- int orig_value_len;
- int new_bytes;
- int current_type;
- int orig_enabled;
+ if (start_after)
+ {
+ if (!writer->enabled && _dbus_type_reader_greater_than (reader, start_after))
+ {
+ _dbus_type_writer_set_enabled (writer, TRUE);
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose ("ENABLING writer %p because reader at value_pos %d is after reader at value_pos %d\n",
+ writer, reader->value_pos, start_after->value_pos);
+#endif
+ }
- orig = *writer;
- orig_type_len = _dbus_string_get_length (writer->type_str);
- orig_value_len = _dbus_string_get_length (writer->value_str);
- orig_enabled = writer->enabled;
+ _dbus_assert ((!writer->enabled && !_dbus_type_reader_greater_than (reader, start_after)) ||
+ (writer->enabled && _dbus_type_reader_greater_than (reader, start_after)));
+ }
+}
- if (start_after)
+static dbus_bool_t
+append_fixup (DBusList **fixups,
+ const DBusArrayLenFixup *fixup)
+{
+ DBusArrayLenFixup *f;
+
+ f = dbus_new (DBusArrayLenFixup, 1);
+ if (f == NULL)
+ return FALSE;
+
+ *f = *fixup;
+
+ if (!_dbus_list_append (fixups, f))
{
- _dbus_type_writer_set_enabled (writer,
- _dbus_type_reader_greater_than (reader, start_after));
+ dbus_free (f);
+ return FALSE;
}
+ _dbus_assert (f->len_pos_in_reader == fixup->len_pos_in_reader);
+ _dbus_assert (f->new_len == fixup->new_len);
+
+ return TRUE;
+}
+
+/* This loop is trivial if you ignore all the start_after nonsense,
+ * so if you're trying to figure it out, start by ignoring that
+ */
+static dbus_bool_t
+writer_write_reader_helper (DBusTypeWriter *writer,
+ DBusTypeReader *reader,
+ const DBusTypeReader *start_after,
+ int start_after_new_pos,
+ int start_after_new_len,
+ DBusList **fixups)
+{
+ int current_type;
+
while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID)
{
if (_dbus_type_is_container (current_type))
@@ -1782,22 +1921,92 @@ _dbus_type_writer_write_reader (DBusTypeWriter *writer,
const DBusString *sig_str;
int sig_start;
int sig_len;
+ dbus_bool_t enabled_at_recurse;
+ dbus_bool_t past_start_after;
+ int reader_array_len_pos;
+ int reader_array_start_pos;
_dbus_type_reader_recurse (reader, &subreader);
+ if (current_type == DBUS_TYPE_ARRAY)
+ {
+ reader_array_len_pos = ARRAY_READER_LEN_POS (&subreader);
+ reader_array_start_pos = subreader.u.array.start_pos;
+ }
+ else
+ {
+ /* quiet gcc */
+ reader_array_len_pos = -1;
+ reader_array_start_pos = -1;
+ }
+
_dbus_type_reader_get_signature (&subreader, &sig_str,
&sig_start, &sig_len);
+ enable_if_after (writer, &subreader, start_after);
+ enabled_at_recurse = writer->enabled;
if (!_dbus_type_writer_recurse_contained_len (writer, current_type,
sig_str, sig_start, sig_len,
&subwriter))
goto oom;
- if (!_dbus_type_writer_write_reader (&subwriter, &subreader, start_after))
+ if (!writer_write_reader_helper (&subwriter, &subreader, start_after,
+ start_after_new_pos, start_after_new_len,
+ fixups))
goto oom;
+ enable_if_after (writer, &subreader, start_after);
+ past_start_after = writer->enabled;
if (!_dbus_type_writer_unrecurse (writer, &subwriter))
goto oom;
+
+ /* If we weren't enabled when we recursed, we didn't
+ * write an array len; if we passed start_after
+ * somewhere inside the array, then we need to generate
+ * a fixup.
+ */
+ if (start_after != NULL &&
+ !enabled_at_recurse && past_start_after &&
+ current_type == DBUS_TYPE_ARRAY &&
+ fixups != NULL)
+ {
+ DBusArrayLenFixup fixup;
+ int bytes_written_after_start_after;
+ int bytes_before_start_after;
+ int old_len;
+
+ /* this is moderately unkosher since we already unrecursed,
+ * but it works as long as unrecurse doesn't break us on purpose
+ */
+ bytes_written_after_start_after = writer_get_array_len (&subwriter);
+
+ bytes_before_start_after =
+ start_after->value_pos - reader_array_start_pos;
+
+ fixup.len_pos_in_reader = reader_array_len_pos;
+ fixup.new_len =
+ bytes_before_start_after +
+ start_after_new_len +
+ bytes_written_after_start_after;
+
+ old_len = _dbus_marshal_read_uint32 (reader->value_str,
+ fixup.len_pos_in_reader,
+ reader->byte_order, NULL);
+
+ if (old_len != fixup.new_len && !append_fixup (fixups, &fixup))
+ goto oom;
+
+#if RECURSIVE_MARSHAL_TRACE
+ _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",
+ fixup.len_pos_in_reader,
+ fixup.new_len,
+ reader_array_start_pos,
+ start_after->value_pos,
+ bytes_before_start_after,
+ start_after_new_len,
+ bytes_written_after_start_after);
+#endif
+ }
}
else
{
@@ -1807,6 +2016,7 @@ _dbus_type_writer_write_reader (DBusTypeWriter *writer,
_dbus_type_reader_read_basic (reader, &val);
+ enable_if_after (writer, reader, start_after);
if (!_dbus_type_writer_write_basic (writer, current_type, &val))
goto oom;
}
@@ -1814,6 +2024,74 @@ _dbus_type_writer_write_reader (DBusTypeWriter *writer,
_dbus_type_reader_next (reader);
}
+ return TRUE;
+
+ oom:
+ if (fixups)
+ apply_and_free_fixups (fixups, NULL); /* NULL for reader to apply to */
+
+ return FALSE;
+}
+
+/**
+ * Iterate through all values in the given reader, writing a copy of
+ * each value to the writer. The reader will be moved forward to its
+ * end position.
+ *
+ * If a reader start_after is provided, it should be a reader for the
+ * same data as the reader to be written. Only values occurring after
+ * the value pointed to by start_after will be written to the writer.
+ *
+ * If start_after is provided, then the copy of the reader will be
+ * partial. This means that array lengths will not have been copied.
+ * The assumption is that you wrote a new version of the value at
+ * start_after to the writer. You have to pass in the start position
+ * and length of the new value. (If you are deleting the value
+ * at start_after, pass in 0 for the length.)
+ *
+ * If the fixups parameter is non-#NULL, then any array length that
+ * was read but not written due to start_after will be provided
+ * as a #DBusArrayLenFixup. The fixup contains the position of the
+ * array length in the source data, and the correct array length
+ * assuming you combine the source data before start_after with
+ * the written data at start_after and beyond.
+ *
+ * @param writer the writer to copy to
+ * @param reader the reader to copy from
+ * @param start_after #NULL or a reader showing where to start
+ * @param start_after_new_pos the position of start_after equivalent in the target data
+ * @param start_after_new_len the length of start_after equivalent in the target data
+ * @param fixups list to append #DBusArrayLenFixup if the write was partial
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_type_writer_write_reader_partial (DBusTypeWriter *writer,
+ DBusTypeReader *reader,
+ const DBusTypeReader *start_after,
+ int start_after_new_pos,
+ int start_after_new_len,
+ DBusList **fixups)
+{
+ DBusTypeWriter orig;
+ int orig_type_len;
+ int orig_value_len;
+ int new_bytes;
+ int orig_enabled;
+
+ orig = *writer;
+ orig_type_len = _dbus_string_get_length (writer->type_str);
+ orig_value_len = _dbus_string_get_length (writer->value_str);
+ orig_enabled = writer->enabled;
+
+ if (start_after)
+ _dbus_type_writer_set_enabled (writer, FALSE);
+
+ if (!writer_write_reader_helper (writer, reader, start_after,
+ start_after_new_pos,
+ start_after_new_len,
+ fixups))
+ goto oom;
+
_dbus_type_writer_set_enabled (writer, orig_enabled);
return TRUE;
@@ -1832,6 +2110,22 @@ _dbus_type_writer_write_reader (DBusTypeWriter *writer,
}
/**
+ * Iterate through all values in the given reader, writing a copy of
+ * each value to the writer. The reader will be moved forward to its
+ * end position.
+ *
+ * @param writer the writer to copy to
+ * @param reader the reader to copy from
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_type_writer_write_reader (DBusTypeWriter *writer,
+ DBusTypeReader *reader)
+{
+ return _dbus_type_writer_write_reader_partial (writer, reader, NULL, 0, 0, NULL);
+}
+
+/**
* If disabled, a writer can still be iterated forward and recursed/unrecursed
* but won't write any values. Types will still be written unless the
* writer is a "values only" writer, because the writer needs access to
@@ -1855,7 +2149,7 @@ _dbus_type_writer_set_enabled (DBusTypeWriter *writer,
#include <stdio.h>
#include <stdlib.h>
-/* Whether to do the OOM stuff */
+/* Whether to do the OOM stuff (only with other expensive tests) */
#define TEST_OOM_HANDLING 0
/* We do start offset 0 through 9, to get various alignment cases. Still this
* obviously makes the test suite run 10x as slow.
@@ -2109,6 +2403,11 @@ struct TestTypeNodeContainerClass
TestTypeNodeClass base;
};
+/* FIXME this could be chilled out substantially by unifying
+ * the basic types into basic_write_value/basic_read_value
+ * and by merging read_value and set_value into one function
+ * taking a flag argument.
+ */
static dbus_bool_t int32_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
@@ -2116,6 +2415,10 @@ static dbus_bool_t int32_write_value (TestTypeNode *node,
static dbus_bool_t int32_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t int32_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t int64_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
@@ -2123,6 +2426,10 @@ static dbus_bool_t int64_write_value (TestTypeNode *node,
static dbus_bool_t int64_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t int64_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t string_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
@@ -2130,6 +2437,10 @@ static dbus_bool_t string_write_value (TestTypeNode *node,
static dbus_bool_t string_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t string_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t bool_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
@@ -2137,6 +2448,10 @@ static dbus_bool_t bool_write_value (TestTypeNode *node,
static dbus_bool_t bool_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t bool_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t byte_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
@@ -2144,6 +2459,10 @@ static dbus_bool_t byte_write_value (TestTypeNode *node,
static dbus_bool_t byte_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t byte_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t double_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
@@ -2151,6 +2470,10 @@ static dbus_bool_t double_write_value (TestTypeNode *node,
static dbus_bool_t double_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t double_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t object_path_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
@@ -2158,6 +2481,10 @@ static dbus_bool_t object_path_write_value (TestTypeNode *node,
static dbus_bool_t object_path_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t object_path_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t signature_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
@@ -2165,6 +2492,10 @@ static dbus_bool_t signature_write_value (TestTypeNode *node,
static dbus_bool_t signature_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t signature_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t struct_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
@@ -2172,6 +2503,10 @@ static dbus_bool_t struct_write_value (TestTypeNode *node,
static dbus_bool_t struct_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t struct_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t struct_build_signature (TestTypeNode *node,
DBusString *str);
static dbus_bool_t array_write_value (TestTypeNode *node,
@@ -2181,6 +2516,10 @@ static dbus_bool_t array_write_value (TestTypeNode *node,
static dbus_bool_t array_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t array_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t array_build_signature (TestTypeNode *node,
DBusString *str);
static dbus_bool_t variant_write_value (TestTypeNode *node,
@@ -2190,6 +2529,10 @@ static dbus_bool_t variant_write_value (TestTypeNode *node,
static dbus_bool_t variant_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t variant_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static void container_destroy (TestTypeNode *node);
@@ -2201,7 +2544,7 @@ static const TestTypeNodeClass int32_class = {
NULL,
int32_write_value,
int32_read_value,
- NULL,
+ int32_set_value,
NULL
};
@@ -2213,7 +2556,7 @@ static const TestTypeNodeClass uint32_class = {
NULL,
int32_write_value, /* recycle from int32 */
int32_read_value, /* recycle from int32 */
- NULL,
+ int32_set_value, /* recycle from int32 */
NULL
};
@@ -2225,7 +2568,7 @@ static const TestTypeNodeClass int64_class = {
NULL,
int64_write_value,
int64_read_value,
- NULL,
+ int64_set_value,
NULL
};
@@ -2237,7 +2580,7 @@ static const TestTypeNodeClass uint64_class = {
NULL,
int64_write_value, /* recycle from int64 */
int64_read_value, /* recycle from int64 */
- NULL,
+ int64_set_value, /* recycle from int64 */
NULL
};
@@ -2249,7 +2592,7 @@ static const TestTypeNodeClass string_0_class = {
NULL,
string_write_value,
string_read_value,
- NULL,
+ string_set_value,
NULL
};
@@ -2261,7 +2604,7 @@ static const TestTypeNodeClass string_1_class = {
NULL,
string_write_value,
string_read_value,
- NULL,
+ string_set_value,
NULL
};
@@ -2274,7 +2617,7 @@ static const TestTypeNodeClass string_3_class = {
NULL,
string_write_value,
string_read_value,
- NULL,
+ string_set_value,
NULL
};
@@ -2287,7 +2630,7 @@ static const TestTypeNodeClass string_8_class = {
NULL,
string_write_value,
string_read_value,
- NULL,
+ string_set_value,
NULL
};
@@ -2299,7 +2642,7 @@ static const TestTypeNodeClass bool_class = {
NULL,
bool_write_value,
bool_read_value,
- NULL,
+ bool_set_value,
NULL
};
@@ -2311,7 +2654,7 @@ static const TestTypeNodeClass byte_class = {
NULL,
byte_write_value,
byte_read_value,
- NULL,
+ byte_set_value,
NULL
};
@@ -2323,7 +2666,7 @@ static const TestTypeNodeClass double_class = {
NULL,
double_write_value,
double_read_value,
- NULL,
+ double_set_value,
NULL
};
@@ -2335,7 +2678,7 @@ static const TestTypeNodeClass object_path_class = {
NULL,
object_path_write_value,
object_path_read_value,
- NULL,
+ object_path_set_value,
NULL
};
@@ -2347,7 +2690,7 @@ static const TestTypeNodeClass signature_class = {
NULL,
signature_write_value,
signature_read_value,
- NULL,
+ signature_set_value,
NULL
};
@@ -2359,7 +2702,7 @@ static const TestTypeNodeClass struct_1_class = {
container_destroy,
struct_write_value,
struct_read_value,
- NULL,
+ struct_set_value,
struct_build_signature
};
@@ -2371,7 +2714,7 @@ static const TestTypeNodeClass struct_2_class = {
container_destroy,
struct_write_value,
struct_read_value,
- NULL,
+ struct_set_value,
struct_build_signature
};
@@ -2383,7 +2726,7 @@ static const TestTypeNodeClass array_0_class = {
container_destroy,
array_write_value,
array_read_value,
- NULL,
+ array_set_value,
array_build_signature
};
@@ -2395,7 +2738,7 @@ static const TestTypeNodeClass array_1_class = {
container_destroy,
array_write_value,
array_read_value,
- NULL,
+ array_set_value,
array_build_signature
};
@@ -2407,7 +2750,7 @@ static const TestTypeNodeClass array_2_class = {
container_destroy,
array_write_value,
array_read_value,
- NULL,
+ array_set_value,
array_build_signature
};
@@ -2419,7 +2762,7 @@ static const TestTypeNodeClass array_9_class = {
container_destroy,
array_write_value,
array_read_value,
- NULL,
+ array_set_value,
array_build_signature
};
@@ -2431,7 +2774,7 @@ static const TestTypeNodeClass variant_class = {
container_destroy,
variant_write_value,
variant_read_value,
- NULL,
+ variant_set_value,
NULL
};
@@ -2541,6 +2884,22 @@ node_read_value (TestTypeNode *node,
return TRUE;
}
+/* Warning: if this one fails due to OOM, it has side effects (can
+ * modify only some of the sub-values). OK in a test suite, but we
+ * never do this in real code.
+ */
+static dbus_bool_t
+node_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ if (!(* node->klass->set_value) (node, reader, realign_root, seed))
+ return FALSE;
+
+ return TRUE;
+}
+
static dbus_bool_t
node_build_signature (TestTypeNode *node,
DBusString *str)
@@ -2607,7 +2966,7 @@ run_test_copy (NodeIterationData *nid)
dest.initial_offset, '\0'))
goto out;
- if (!_dbus_type_writer_write_reader (&writer, &reader, NULL))
+ if (!_dbus_type_writer_write_reader (&writer, &reader))
goto out;
/* Data blocks should now be identical */
@@ -2704,6 +3063,71 @@ run_test_values_only_write (NodeIterationData *nid)
return retval;
}
+/* offset the seed for setting, so we set different numbers than
+ * we originally wrote. Don't offset by a huge number since in
+ * some cases it's value = possibilities[seed % n_possibilities]
+ * and we don't want to wrap around. bool_from_seed
+ * is just seed % 2 even.
+ */
+#define SET_SEED 1
+static dbus_bool_t
+run_test_set_values (NodeIterationData *nid)
+{
+ DBusTypeReader reader;
+ DBusTypeReader realign_root;
+ dbus_bool_t retval;
+ int i;
+
+ _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
+
+ retval = FALSE;
+
+ data_block_init_reader_writer (nid->block,
+ &reader, NULL);
+
+ realign_root = reader;
+
+ i = 0;
+ while (i < nid->n_nodes)
+ {
+ if (!node_set_value (nid->nodes[i],
+ &reader, &realign_root,
+ i + SET_SEED))
+ goto out;
+
+ if (i + 1 == nid->n_nodes)
+ NEXT_EXPECTING_FALSE (&reader);
+ else
+ NEXT_EXPECTING_TRUE (&reader);
+
+ ++i;
+ }
+
+ /* Check that the new values were set */
+
+ reader = realign_root;
+
+ i = 0;
+ while (i < nid->n_nodes)
+ {
+ if (!node_read_value (nid->nodes[i], &reader,
+ i + SET_SEED))
+ goto out;
+
+ if (i + 1 == nid->n_nodes)
+ NEXT_EXPECTING_FALSE (&reader);
+ else
+ NEXT_EXPECTING_TRUE (&reader);
+
+ ++i;
+ }
+
+ retval = TRUE;
+
+ out:
+ return retval;
+}
+
static dbus_bool_t
run_test_nodes_iteration (void *data)
{
@@ -2766,6 +3190,16 @@ run_test_nodes_iteration (void *data)
if (n_iterations_expected_this_test <= MAX_ITERATIONS_FOR_EXPENSIVE_TESTS)
{
+ /* this set values test uses code from copy and
+ * values_only_write so would ideally be last so you get a
+ * simpler test case for problems with copying or values_only
+ * writing; but it also needs an already-written DataBlock so it
+ * has to go first. Comment it out if it breaks, and see if the
+ * later tests also break - debug them first if so.
+ */
+ if (!run_test_set_values (nid))
+ goto out;
+
if (!run_test_copy (nid))
goto out;
@@ -2805,14 +3239,18 @@ run_test_nodes_in_one_configuration (TestTypeNode **nodes,
nid.nodes = nodes;
nid.n_nodes = n_nodes;
-#if TEST_OOM_HANDLING
- _dbus_test_oom_handling ("running test node",
- run_test_nodes_iteration,
- &nid);
-#else
- if (!run_test_nodes_iteration (&nid))
- _dbus_assert_not_reached ("no memory");
-#endif
+ if (TEST_OOM_HANDLING &&
+ n_iterations_expected_this_test <= MAX_ITERATIONS_FOR_EXPENSIVE_TESTS)
+ {
+ _dbus_test_oom_handling ("running test node",
+ run_test_nodes_iteration,
+ &nid);
+ }
+ else
+ {
+ if (!run_test_nodes_iteration (&nid))
+ _dbus_assert_not_reached ("no memory");
+ }
data_block_free (&block);
}
@@ -3356,6 +3794,22 @@ int32_read_value (TestTypeNode *node,
return TRUE;
}
+static dbus_bool_t
+int32_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ /* also used for uint32 */
+ dbus_int32_t v;
+
+ v = int32_from_seed (seed);
+
+ return _dbus_type_reader_set_basic (reader,
+ &v,
+ realign_root);
+}
+
#ifdef DBUS_HAVE_INT64
static dbus_int64_t
int64_from_seed (int seed)
@@ -3414,6 +3868,26 @@ int64_read_value (TestTypeNode *node,
#endif
}
+static dbus_bool_t
+int64_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+#ifdef DBUS_HAVE_INT64
+ /* also used for uint64 */
+ dbus_int64_t v;
+
+ v = int64_from_seed (seed);
+
+ return _dbus_type_reader_set_basic (reader,
+ &v,
+ realign_root);
+#else
+ return TRUE;
+#endif
+}
+
#define MAX_SAMPLE_STRING_LEN 10
static void
string_from_seed (char *buf,
@@ -3425,6 +3899,21 @@ string_from_seed (char *buf,
_dbus_assert (len < MAX_SAMPLE_STRING_LEN);
+ /* vary the length slightly, though we also have multiple string
+ * value types for this, varying it here tests the set_value code
+ */
+ switch (seed % 3)
+ {
+ case 1:
+ len += 2;
+ break;
+ case 2:
+ len -= 2;
+ break;
+ }
+ if (len < 0)
+ len = 0;
+
v = (unsigned char) ('A' + seed);
i = 0;
@@ -3485,6 +3974,23 @@ string_read_value (TestTypeNode *node,
return TRUE;
}
+static dbus_bool_t
+string_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ char buf[MAX_SAMPLE_STRING_LEN];
+ const char *v_string = buf;
+
+ string_from_seed (buf, node->klass->subclass_detail,
+ seed);
+
+ return _dbus_type_reader_set_basic (reader,
+ &v_string,
+ realign_root);
+}
+
#define BOOL_FROM_SEED(seed) (seed % 2)
static dbus_bool_t
@@ -3519,6 +4025,21 @@ bool_read_value (TestTypeNode *node,
return TRUE;
}
+static dbus_bool_t
+bool_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ unsigned char v;
+
+ v = BOOL_FROM_SEED (seed);
+
+ return _dbus_type_reader_set_basic (reader,
+ &v,
+ realign_root);
+}
+
#define BYTE_FROM_SEED(seed) ((unsigned char) int32_from_seed (seed))
static dbus_bool_t
@@ -3553,6 +4074,22 @@ byte_read_value (TestTypeNode *node,
return TRUE;
}
+
+static dbus_bool_t
+byte_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ unsigned char v;
+
+ v = BYTE_FROM_SEED (seed);
+
+ return _dbus_type_reader_set_basic (reader,
+ &v,
+ realign_root);
+}
+
static double
double_from_seed (int seed)
{
@@ -3594,8 +4131,8 @@ double_read_value (TestTypeNode *node,
#ifdef DBUS_HAVE_INT64
_dbus_warn ("Expected double %g got %g\n bits = 0x%llx vs.\n bits = 0x%llx)\n",
expected, v,
- *(dbus_uint64_t*)&expected,
- *(dbus_uint64_t*)&v);
+ *(dbus_uint64_t*)(char*)&expected,
+ *(dbus_uint64_t*)(char*)&v);
#endif
_dbus_assert_not_reached ("test failed");
}
@@ -3603,6 +4140,20 @@ double_read_value (TestTypeNode *node,
return TRUE;
}
+static dbus_bool_t
+double_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ double v;
+
+ v = double_from_seed (seed);
+
+ return _dbus_type_reader_set_basic (reader,
+ &v,
+ realign_root);
+}
#define MAX_SAMPLE_OBJECT_PATH_LEN 10
static void
@@ -3611,11 +4162,15 @@ object_path_from_seed (char *buf,
{
int i;
unsigned char v;
+ int len;
+
+ len = seed % 9;
+ _dbus_assert (len < MAX_SAMPLE_OBJECT_PATH_LEN);
v = (unsigned char) ('A' + seed);
i = 0;
- while (i < 8)
+ while (i + 1 < len)
{
if (v < 'A' || v > 'z')
v = 'A';
@@ -3672,6 +4227,21 @@ object_path_read_value (TestTypeNode *node,
return TRUE;
}
+static dbus_bool_t
+object_path_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ char buf[MAX_SAMPLE_OBJECT_PATH_LEN];
+ const char *v_string = buf;
+
+ object_path_from_seed (buf, seed);
+
+ return _dbus_type_reader_set_basic (reader,
+ &v_string,
+ realign_root);
+}
#define MAX_SAMPLE_SIGNATURE_LEN 10
static void
@@ -3680,13 +4250,14 @@ signature_from_seed (char *buf,
{
int i;
const char *s;
+ /* try to avoid ascending, descending, or alternating length to help find bugs */
const char *sample_signatures[] = {
+ "asax"
"",
- "ai",
+ "asau(xxxx)",
"x",
- "a(ii)",
- "asax"
- "asau(xxxx)"
+ "ai",
+ "a(ii)"
};
s = sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)];
@@ -3739,6 +4310,23 @@ signature_read_value (TestTypeNode *node,
return TRUE;
}
+
+static dbus_bool_t
+signature_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ char buf[MAX_SAMPLE_SIGNATURE_LEN];
+ const char *v_string = buf;
+
+ signature_from_seed (buf, seed);
+
+ return _dbus_type_reader_set_basic (reader,
+ &v_string,
+ realign_root);
+}
+
static dbus_bool_t
struct_write_value (TestTypeNode *node,
DataBlock *block,
@@ -3795,9 +4383,10 @@ struct_write_value (TestTypeNode *node,
}
static dbus_bool_t
-struct_read_value (TestTypeNode *node,
- DBusTypeReader *reader,
- int seed)
+struct_read_or_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
{
TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
DBusTypeReader sub;
@@ -3821,8 +4410,16 @@ struct_read_value (TestTypeNode *node,
TestTypeNode *child = link->data;
DBusList *next = _dbus_list_get_next_link (&container->children, link);
- if (!node_read_value (child, &sub, seed + i))
- return FALSE;
+ if (realign_root == NULL)
+ {
+ if (!node_read_value (child, &sub, seed + i))
+ return FALSE;
+ }
+ else
+ {
+ if (!node_set_value (child, &sub, realign_root, seed + i))
+ return FALSE;
+ }
if (i == (n_copies - 1) && next == NULL)
NEXT_EXPECTING_FALSE (&sub);
@@ -3839,6 +4436,23 @@ struct_read_value (TestTypeNode *node,
}
static dbus_bool_t
+struct_read_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ int seed)
+{
+ return struct_read_or_set_value (node, reader, NULL, seed);
+}
+
+static dbus_bool_t
+struct_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ return struct_read_or_set_value (node, reader, realign_root, seed);
+}
+
+static dbus_bool_t
struct_build_signature (TestTypeNode *node,
DBusString *str)
{
@@ -3948,9 +4562,10 @@ array_write_value (TestTypeNode *node,
}
static dbus_bool_t
-array_read_value (TestTypeNode *node,
- DBusTypeReader *reader,
- int seed)
+array_read_or_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
{
TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
DBusTypeReader sub;
@@ -3978,8 +4593,16 @@ array_read_value (TestTypeNode *node,
TestTypeNode *child = link->data;
DBusList *next = _dbus_list_get_next_link (&container->children, link);
- if (!node_read_value (child, &sub, seed + i))
- return FALSE;
+ if (realign_root == NULL)
+ {
+ if (!node_read_value (child, &sub, seed + i))
+ return FALSE;
+ }
+ else
+ {
+ if (!node_set_value (child, &sub, realign_root, seed + i))
+ return FALSE;
+ }
if (i == (n_copies - 1) && next == NULL)
NEXT_EXPECTING_FALSE (&sub);
@@ -4001,6 +4624,23 @@ array_read_value (TestTypeNode *node,
}
static dbus_bool_t
+array_read_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ int seed)
+{
+ return array_read_or_set_value (node, reader, NULL, seed);
+}
+
+static dbus_bool_t
+array_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ return array_read_or_set_value (node, reader, realign_root, seed);
+}
+
+static dbus_bool_t
array_build_signature (TestTypeNode *node,
DBusString *str)
{
@@ -4073,9 +4713,10 @@ variant_write_value (TestTypeNode *node,
}
static dbus_bool_t
-variant_read_value (TestTypeNode *node,
- DBusTypeReader *reader,
- int seed)
+variant_read_or_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
{
TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
DBusTypeReader sub;
@@ -4090,14 +4731,39 @@ variant_read_value (TestTypeNode *node,
_dbus_type_reader_recurse (reader, &sub);
- if (!node_read_value (child, &sub, seed + VARIANT_SEED))
- return FALSE;
+ if (realign_root == NULL)
+ {
+ if (!node_read_value (child, &sub, seed + VARIANT_SEED))
+ return FALSE;
+ }
+ else
+ {
+ if (!node_set_value (child, &sub, realign_root, seed + VARIANT_SEED))
+ return FALSE;
+ }
NEXT_EXPECTING_FALSE (&sub);
return TRUE;
}
+static dbus_bool_t
+variant_read_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ int seed)
+{
+ return variant_read_or_set_value (node, reader, NULL, seed);
+}
+
+static dbus_bool_t
+variant_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ return variant_read_or_set_value (node, reader, realign_root, seed);
+}
+
static void
container_destroy (TestTypeNode *node)
{