2003-09-25 Mark McLoughlin <mark@skynet.ie>

* doc/dbus-specification.sgml: don't require header fields
	to be 4-byte aligned and specify that fields should be
	distinguished from padding by the fact that zero is not
	a valid field name.

	* doc/TODO: remove re-alignment item and add item to doc
	the OBJECT_PATH type.

	* dbus/dbus-message.c:
	(HeaderField): rename the original member to value_offset
	and introduce a name_offset member to keep track of where
	the field actually begins.
	(adjust_field_offsets): remove.
	(append_int_field), (append_uint_field),
	(append_string_field): don't align the start of the header
	field to a 4-byte boundary.
	(get_next_field): impl finding the next marhsalled field
	after a given field.
	(re_align_field_recurse): impl re-aligning a number of
	already marshalled fields.
	(delete_field): impl deleting a field of any type and
	re-aligning any following fields.
	(delete_int_or_uint_field), (delete_string_field): remove.
	(set_int_field), (set_uint_field): no need to re-check
	that we have the correct type for the field.
	(set_string_field): ditto and impl re-aligning any
	following fields.
	(decode_header_data): update to take into account that
	the fields aren't 4-byte aligned any more and the new
	way to distinguish padding from header fields. Also,
	don't exit when there is too much header padding.
	(process_test_subdir): print the directory.
	(_dbus_message_test): add test to make sure a following
	field is re-aligned correctly after field deletion.

	* dbus/dbus-string.[ch]:
	(_dbus_string_insert_bytes): rename from insert_byte and
	allow the insert of multiple bytes.
	(_dbus_string_test): test inserting multiple bytes.

	* dbus/dbus-marshal.c: (_dbus_marshal_set_string): add
	warning note to docs about having to re-align any
	marshalled values following the string.

	* dbus/dbus-message-builder.c:
	(append_string_field), (_dbus_message_data_load):
	don't align the header field.

	* dbus/dbus-auth.c: (process_test_subdir): print the
	directory.

	* test/break-loader.c: (randomly_add_one_byte): upd. for
	insert_byte change.

	* test/data/invalid-messages/bad-header-field-alignment.message:
	new test case.

	* test/data/valid-messages/unknown-header-field.message: shove
	a dict in the unknown field.
This commit is contained in:
Mark McLoughlin 2003-09-25 08:50:14 +00:00
parent dcc037cc1f
commit 46c072e113
12 changed files with 443 additions and 246 deletions

View file

@ -1,3 +1,65 @@
2003-09-25 Mark McLoughlin <mark@skynet.ie>
* doc/dbus-specification.sgml: don't require header fields
to be 4-byte aligned and specify that fields should be
distinguished from padding by the fact that zero is not
a valid field name.
* doc/TODO: remove re-alignment item and add item to doc
the OBJECT_PATH type.
* dbus/dbus-message.c:
(HeaderField): rename the original member to value_offset
and introduce a name_offset member to keep track of where
the field actually begins.
(adjust_field_offsets): remove.
(append_int_field), (append_uint_field),
(append_string_field): don't align the start of the header
field to a 4-byte boundary.
(get_next_field): impl finding the next marhsalled field
after a given field.
(re_align_field_recurse): impl re-aligning a number of
already marshalled fields.
(delete_field): impl deleting a field of any type and
re-aligning any following fields.
(delete_int_or_uint_field), (delete_string_field): remove.
(set_int_field), (set_uint_field): no need to re-check
that we have the correct type for the field.
(set_string_field): ditto and impl re-aligning any
following fields.
(decode_header_data): update to take into account that
the fields aren't 4-byte aligned any more and the new
way to distinguish padding from header fields. Also,
don't exit when there is too much header padding.
(process_test_subdir): print the directory.
(_dbus_message_test): add test to make sure a following
field is re-aligned correctly after field deletion.
* dbus/dbus-string.[ch]:
(_dbus_string_insert_bytes): rename from insert_byte and
allow the insert of multiple bytes.
(_dbus_string_test): test inserting multiple bytes.
* dbus/dbus-marshal.c: (_dbus_marshal_set_string): add
warning note to docs about having to re-align any
marshalled values following the string.
* dbus/dbus-message-builder.c:
(append_string_field), (_dbus_message_data_load):
don't align the header field.
* dbus/dbus-auth.c: (process_test_subdir): print the
directory.
* test/break-loader.c: (randomly_add_one_byte): upd. for
insert_byte change.
* test/data/invalid-messages/bad-header-field-alignment.message:
new test case.
* test/data/valid-messages/unknown-header-field.message: shove
a dict in the unknown field.
2003-09-25 Seth Nickell <seth@gnome.org>
* python/dbus.py:

View file

@ -2380,7 +2380,7 @@ process_test_subdir (const DBusString *test_base_dir,
goto failed;
}
printf ("Testing:\n");
printf ("Testing %s:\n", subdir);
next:
while (_dbus_directory_get_next_file (dir, &filename, &error))

View file

@ -395,6 +395,10 @@ _dbus_marshal_set_uint64 (DBusString *str,
* an existing string or the wrong length will be deleted
* and replaced with the new string.
*
* Note: no attempt is made by this function to re-align
* any data which has been already marshalled after this
* string. Use with caution.
*
* @param str the string to write the marshalled string to
* @param offset the byte offset where string should be written
* @param byte_order the byte order to use

View file

@ -300,12 +300,6 @@ append_string_field (DBusString *dest,
{
int len;
if (!_dbus_string_align_length (dest, 4))
{
_dbus_warn ("could not align field name\n");
return FALSE;
}
if (!_dbus_string_append_byte (dest, field))
{
_dbus_warn ("couldn't append field name byte\n");
@ -710,11 +704,6 @@ _dbus_message_data_load (DBusString *dest,
goto parse_failed;
}
if (unalign)
unalign = FALSE;
else
_dbus_string_align_length (dest, 4);
if (!_dbus_string_append_byte (dest, field))
{
_dbus_warn ("could not append header field name byte\n");

View file

@ -47,9 +47,8 @@
*/
typedef struct
{
int offset; /**< Offset to start of field (location of name of field
* for named fields)
*/
int name_offset; /**< Offset to name of field */
int value_offset; /**< Offset to value of field */
} HeaderField;
/** Offset to byte order from start of header */
@ -183,26 +182,6 @@ append_header_padding (DBusMessage *message)
return TRUE;
}
static void
adjust_field_offsets (DBusMessage *message,
int offsets_after,
int delta)
{
int i;
if (delta == 0)
return;
i = 0;
while (i <= DBUS_HEADER_FIELD_LAST)
{
if (message->header_fields[i].offset > offsets_after)
message->header_fields[i].offset += delta;
++i;
}
}
#ifdef DBUS_BUILD_TESTS
/* tests-only until it's actually used */
static dbus_int32_t
@ -213,7 +192,7 @@ get_int_field (DBusMessage *message,
_dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
offset = message->header_fields[field].offset;
offset = message->header_fields[field].value_offset;
if (offset < 0)
return -1; /* useless if -1 is a valid value of course */
@ -233,7 +212,7 @@ get_uint_field (DBusMessage *message,
_dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
offset = message->header_fields[field].offset;
offset = message->header_fields[field].value_offset;
if (offset < 0)
return -1; /* useless if -1 is a valid value of course */
@ -252,7 +231,7 @@ get_string_field (DBusMessage *message,
int offset;
const char *data;
offset = message->header_fields[field].offset;
offset = message->header_fields[field].value_offset;
_dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
@ -283,7 +262,7 @@ get_path_field_decomposed (DBusMessage *message,
{
int offset;
offset = message->header_fields[field].offset;
offset = message->header_fields[field].value_offset;
_dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
@ -306,16 +285,12 @@ append_int_field (DBusMessage *message,
int field,
int value)
{
int orig_len;
_dbus_assert (!message->locked);
clear_header_padding (message);
orig_len = _dbus_string_get_length (&message->header);
if (!_dbus_string_align_length (&message->header, 4))
goto failed;
message->header_fields[field].name_offset =
_dbus_string_get_length (&message->header);
if (!_dbus_string_append_byte (&message->header, field))
goto failed;
@ -326,7 +301,7 @@ append_int_field (DBusMessage *message,
if (!_dbus_string_align_length (&message->header, 4))
goto failed;
message->header_fields[field].offset =
message->header_fields[field].value_offset =
_dbus_string_get_length (&message->header);
if (!_dbus_marshal_int32 (&message->header, message->byte_order,
@ -339,8 +314,10 @@ append_int_field (DBusMessage *message,
return TRUE;
failed:
message->header_fields[field].offset = -1;
_dbus_string_set_length (&message->header, orig_len);
_dbus_string_set_length (&message->header,
message->header_fields[field].name_offset);
message->header_fields[field].name_offset = -1;
message->header_fields[field].value_offset = -1;
/* this must succeed because it was allocated on function entry and
* DBusString doesn't ever realloc smaller
@ -356,16 +333,12 @@ append_uint_field (DBusMessage *message,
int field,
int value)
{
int orig_len;
_dbus_assert (!message->locked);
clear_header_padding (message);
orig_len = _dbus_string_get_length (&message->header);
if (!_dbus_string_align_length (&message->header, 4))
goto failed;
message->header_fields[field].name_offset =
_dbus_string_get_length (&message->header);
if (!_dbus_string_append_byte (&message->header, field))
goto failed;
@ -376,7 +349,7 @@ append_uint_field (DBusMessage *message,
if (!_dbus_string_align_length (&message->header, 4))
goto failed;
message->header_fields[field].offset =
message->header_fields[field].value_offset =
_dbus_string_get_length (&message->header);
if (!_dbus_marshal_uint32 (&message->header, message->byte_order,
@ -389,8 +362,10 @@ append_uint_field (DBusMessage *message,
return TRUE;
failed:
message->header_fields[field].offset = -1;
_dbus_string_set_length (&message->header, orig_len);
_dbus_string_set_length (&message->header,
message->header_fields[field].name_offset);
message->header_fields[field].name_offset = -1;
message->header_fields[field].value_offset = -1;
/* this must succeed because it was allocated on function entry and
* DBusString doesn't ever realloc smaller
@ -406,16 +381,12 @@ append_string_field (DBusMessage *message,
int type,
const char *value)
{
int orig_len;
_dbus_assert (!message->locked);
clear_header_padding (message);
orig_len = _dbus_string_get_length (&message->header);
if (!_dbus_string_align_length (&message->header, 4))
goto failed;
message->header_fields[field].name_offset =
_dbus_string_get_length (&message->header);
if (!_dbus_string_append_byte (&message->header, field))
goto failed;
@ -426,7 +397,7 @@ append_string_field (DBusMessage *message,
if (!_dbus_string_align_length (&message->header, 4))
goto failed;
message->header_fields[field].offset =
message->header_fields[field].value_offset =
_dbus_string_get_length (&message->header);
if (!_dbus_marshal_string (&message->header, message->byte_order,
@ -439,8 +410,10 @@ append_string_field (DBusMessage *message,
return TRUE;
failed:
message->header_fields[field].offset = -1;
_dbus_string_set_length (&message->header, orig_len);
_dbus_string_set_length (&message->header,
message->header_fields[field].name_offset);
message->header_fields[field].name_offset = -1;
message->header_fields[field].value_offset = -1;
/* this must succeed because it was allocated on function entry and
* DBusString doesn't ever realloc smaller
@ -451,71 +424,205 @@ append_string_field (DBusMessage *message,
return FALSE;
}
#ifdef DBUS_BUILD_TESTS
/* This isn't used, but building it when tests are enabled just to
* keep it compiling if we need it in future
*/
static void
delete_int_or_uint_field (DBusMessage *message,
int field)
static int
get_next_field (DBusMessage *message,
int field)
{
int offset = message->header_fields[field].offset;
int offset = message->header_fields[field].name_offset;
int closest;
int i;
int retval = DBUS_HEADER_FIELD_INVALID;
_dbus_assert (!message->locked);
if (offset < 0)
return;
i = 0;
closest = _DBUS_INT_MAX;
while (i < DBUS_HEADER_FIELD_LAST)
{
if (message->header_fields[i].name_offset > offset &&
message->header_fields[i].name_offset < closest)
{
closest = message->header_fields[i].name_offset;
retval = i;
}
++i;
}
clear_header_padding (message);
/* The field typecode and name take up 4 bytes */
_dbus_string_delete (&message->header,
offset - 4,
8);
message->header_fields[field].offset = -1;
adjust_field_offsets (message,
offset - 4,
- 8);
append_header_padding (message);
return retval;
}
#endif
static void
delete_string_field (DBusMessage *message,
int field)
static dbus_bool_t
re_align_field_recurse (DBusMessage *message,
int field,
int offset)
{
int offset = message->header_fields[field].offset;
int len;
int delete_len;
int old_name_offset = message->header_fields[field].name_offset;
int old_value_offset = message->header_fields[field].value_offset;
int prev_padding, padding, delta;
int type;
int next_field;
int pos = offset;
/* padding between the typecode byte and the value itself */
prev_padding = old_value_offset - old_name_offset + 2;
pos++;
type = _dbus_string_get_byte (&message->header, pos);
pos++;
switch (type)
{
case DBUS_TYPE_NIL:
case DBUS_TYPE_BYTE:
case DBUS_TYPE_BOOLEAN:
padding = 0;
break;
case DBUS_TYPE_INT32:
case DBUS_TYPE_UINT32:
case DBUS_TYPE_STRING:
case DBUS_TYPE_OBJECT_PATH:
padding = _DBUS_ALIGN_VALUE (pos, 4) - pos;
break;
case DBUS_TYPE_INT64:
case DBUS_TYPE_UINT64:
case DBUS_TYPE_DOUBLE:
padding = _DBUS_ALIGN_VALUE (pos, 8) - pos;
break;
case DBUS_TYPE_NAMED:
case DBUS_TYPE_ARRAY:
case DBUS_TYPE_DICT:
_dbus_assert_not_reached ("no defined header fields may contain a named, array or dict value");
break;
case DBUS_TYPE_INVALID:
default:
_dbus_assert_not_reached ("invalid type in marshalled header");
break;
}
delta = padding - prev_padding;
if (delta > 0)
{
if (!_dbus_string_insert_bytes (&message->header, pos, delta, 0))
return FALSE;
}
else if (delta < 0)
{
_dbus_string_delete (&message->header, pos, -delta);
}
next_field = get_next_field (message, field);
if (next_field != DBUS_HEADER_FIELD_INVALID)
{
int next_offset = message->header_fields[next_field].name_offset;
_dbus_assert (next_offset > 0);
if (!re_align_field_recurse (message, field,
pos + padding + (next_offset - old_value_offset)))
goto failed;
}
else
{
if (!append_header_padding (message))
goto failed;
}
message->header_fields[field].name_offset = offset;
message->header_fields[field].value_offset = pos + padding;
return TRUE;
failed:
if (delta > 0)
{
_dbus_string_delete (&message->header, pos, delta);
}
else if (delta < 0)
{
/* this must succeed because it was allocated on function entry and
* DBusString doesn't ever realloc smaller
*/
_dbus_string_insert_bytes (&message->header, pos, -delta, 0);
}
return FALSE;
}
static dbus_bool_t
delete_field (DBusMessage *message,
int field)
{
int offset = message->header_fields[field].name_offset;
int next_field;
_dbus_assert (!message->locked);
if (offset < 0)
return;
return FALSE;
clear_header_padding (message);
get_string_field (message, field, &len);
/* The field typecode and name take up 4 bytes, and the nul
* termination is 1 bytes, string length integer is 4 bytes
*/
delete_len = 4 + 4 + 1 + len;
_dbus_string_delete (&message->header,
offset - 4,
delete_len);
message->header_fields[field].offset = -1;
adjust_field_offsets (message,
offset - 4,
- delete_len);
next_field = get_next_field (message, field);
if (next_field == DBUS_HEADER_FIELD_INVALID)
{
_dbus_string_set_length (&message->header, offset);
append_header_padding (message);
message->header_fields[field].name_offset = -1;
message->header_fields[field].value_offset = -1;
/* this must succeed because it was allocated on function entry and
* DBusString doesn't ever realloc smaller
*/
if (!append_header_padding (message))
_dbus_assert_not_reached ("failed to reappend header padding");
return TRUE;
}
else
{
DBusString deleted;
int next_offset = message->header_fields[next_field].name_offset;
_dbus_assert (next_offset > 0);
if (!_dbus_string_init (&deleted))
goto failed;
if (!_dbus_string_move_len (&message->header,
offset, next_offset - offset,
&deleted, 0))
{
_dbus_string_free (&deleted);
goto failed;
}
/* appends the header padding */
if (!re_align_field_recurse (message, next_field, offset))
{
/* this must succeed because it was allocated on function entry and
* DBusString doesn't ever realloc smaller
*/
if (!_dbus_string_copy (&deleted, 0, &message->header, offset))
_dbus_assert_not_reached ("failed to revert to original field");
_dbus_string_free (&deleted);
goto failed;
}
_dbus_string_free (&deleted);
message->header_fields[field].name_offset = -1;
message->header_fields[field].value_offset = -1;
return TRUE;
failed:
/* this must succeed because it was allocated on function entry and
* DBusString doesn't ever realloc smaller
*/
if (!append_header_padding (message))
_dbus_assert_not_reached ("failed to reappend header padding");
return FALSE;
}
}
#ifdef DBUS_BUILD_TESTS
@ -524,20 +631,14 @@ set_int_field (DBusMessage *message,
int field,
int value)
{
int offset = message->header_fields[field].offset;
int offset = message->header_fields[field].value_offset;
_dbus_assert (!message->locked);
if (offset < 0)
{
/* need to append the field */
switch (field)
{
default:
_dbus_assert_not_reached ("appending an int field we don't support appending");
return FALSE;
}
return append_int_field (message, field, value);
}
else
{
@ -555,23 +656,14 @@ set_uint_field (DBusMessage *message,
int field,
dbus_uint32_t value)
{
int offset = message->header_fields[field].offset;
int offset = message->header_fields[field].value_offset;
_dbus_assert (!message->locked);
if (offset < 0)
{
/* need to append the field */
switch (field)
{
case DBUS_HEADER_FIELD_REPLY_SERIAL:
return append_uint_field (message, field, value);
default:
_dbus_assert_not_reached ("appending a uint field we don't support appending");
return FALSE;
}
return append_uint_field (message, field, value);
}
else
{
@ -589,7 +681,7 @@ set_string_field (DBusMessage *message,
int type,
const char *value)
{
int offset = message->header_fields[field].offset;
int offset = message->header_fields[field].value_offset;
_dbus_assert (!message->locked);
_dbus_assert (value != NULL);
@ -597,52 +689,59 @@ set_string_field (DBusMessage *message,
if (offset < 0)
{
/* need to append the field */
switch (field)
{
case DBUS_HEADER_FIELD_PATH:
case DBUS_HEADER_FIELD_SENDER_SERVICE:
case DBUS_HEADER_FIELD_INTERFACE:
case DBUS_HEADER_FIELD_MEMBER:
case DBUS_HEADER_FIELD_ERROR_NAME:
case DBUS_HEADER_FIELD_SERVICE:
return append_string_field (message, field, type, value);
default:
_dbus_assert_not_reached ("appending a string field we don't support appending");
return FALSE;
}
return append_string_field (message, field, type, value);
}
else
{
DBusString v;
int old_len;
int new_len;
char *old_value;
int next_field;
int next_offset;
int len;
clear_header_padding (message);
old_len = _dbus_string_get_length (&message->header);
old_value = _dbus_demarshal_string (&message->header,
message->byte_order,
offset,
&next_offset);
if (!old_value)
goto failed;
len = strlen (value);
_dbus_string_init_const_len (&v, value,
len + 1); /* include nul */
if (!_dbus_marshal_set_string (&message->header,
message->byte_order,
offset, &v,
len))
goto failed;
new_len = _dbus_string_get_length (&message->header);
offset, &v, len))
{
dbus_free (old_value);
goto failed;
}
adjust_field_offsets (message,
offset,
new_len - old_len);
next_field = get_next_field (message, field);
if (next_field != DBUS_HEADER_FIELD_INVALID)
{
/* re-appends the header padding */
if (!re_align_field_recurse (message, next_field, next_offset))
{
len = strlen (old_value);
_dbus_string_init_const_len (&v, old_value,
len + 1); /* include nul */
if (!_dbus_marshal_set_string (&message->header,
message->byte_order,
offset, &v, len))
_dbus_assert_not_reached ("failed to revert to original string");
dbus_free (old_value);
goto failed;
}
}
dbus_free (old_value);
if (!append_header_padding (message))
goto failed;
return TRUE;
failed:
@ -983,7 +1082,8 @@ dbus_message_new_empty_header (void)
i = 0;
while (i <= DBUS_HEADER_FIELD_LAST)
{
message->header_fields[i].offset = -1;
message->header_fields[i].name_offset = -1;
message->header_fields[i].value_offset = -1;
++i;
}
@ -1281,7 +1381,7 @@ dbus_message_copy (const DBusMessage *message)
for (i = 0; i <= DBUS_HEADER_FIELD_LAST; i++)
{
retval->header_fields[i].offset = message->header_fields[i].offset;
retval->header_fields[i] = message->header_fields[i];
}
return retval;
@ -1390,7 +1490,7 @@ dbus_message_set_path (DBusMessage *message,
if (object_path == NULL)
{
delete_string_field (message, DBUS_HEADER_FIELD_PATH);
delete_field (message, DBUS_HEADER_FIELD_PATH);
return TRUE;
}
else
@ -1464,7 +1564,7 @@ dbus_message_set_interface (DBusMessage *message,
if (interface == NULL)
{
delete_string_field (message, DBUS_HEADER_FIELD_INTERFACE);
delete_field (message, DBUS_HEADER_FIELD_INTERFACE);
return TRUE;
}
else
@ -1512,7 +1612,7 @@ dbus_message_set_member (DBusMessage *message,
if (member == NULL)
{
delete_string_field (message, DBUS_HEADER_FIELD_MEMBER);
delete_field (message, DBUS_HEADER_FIELD_MEMBER);
return TRUE;
}
else
@ -1559,8 +1659,7 @@ dbus_message_set_error_name (DBusMessage *message,
if (error_name == NULL)
{
delete_string_field (message,
DBUS_HEADER_FIELD_ERROR_NAME);
delete_field (message, DBUS_HEADER_FIELD_ERROR_NAME);
return TRUE;
}
else
@ -1604,7 +1703,7 @@ dbus_message_set_destination (DBusMessage *message,
if (destination == NULL)
{
delete_string_field (message, DBUS_HEADER_FIELD_SERVICE);
delete_field (message, DBUS_HEADER_FIELD_SERVICE);
return TRUE;
}
else
@ -4081,8 +4180,7 @@ dbus_message_set_sender (DBusMessage *message,
if (sender == NULL)
{
delete_string_field (message,
DBUS_HEADER_FIELD_SENDER_SERVICE);
delete_field (message, DBUS_HEADER_FIELD_SENDER_SERVICE);
return TRUE;
}
else
@ -4550,7 +4648,7 @@ decode_string_field (const DBusString *data,
_dbus_assert (header_field != NULL);
_dbus_assert (field_data != NULL);
if (header_field->offset >= 0)
if (header_field->name_offset >= 0)
{
_dbus_verbose ("%s field provided twice\n",
_dbus_header_field_to_string (field));
@ -4575,12 +4673,13 @@ decode_string_field (const DBusString *data,
_dbus_string_init_const (field_data,
_dbus_string_get_const_data (data) + string_data_pos);
header_field->offset = _DBUS_ALIGN_VALUE (pos, 4);
header_field->name_offset = pos;
header_field->value_offset = _DBUS_ALIGN_VALUE (pos, 4);
#if 0
_dbus_verbose ("Found field %s at offset %d\n",
_dbus_header_field_to_string (field),
header_field->offset);
header_field->value_offset);
#endif
return TRUE;
@ -4609,29 +4708,18 @@ decode_header_data (const DBusString *data,
i = 0;
while (i <= DBUS_HEADER_FIELD_LAST)
{
fields[i].offset = -1;
fields[i].name_offset = -1;
fields[i].value_offset = -1;
++i;
}
/* Now handle the named fields. A real named field is at least 1
* byte for the name, plus a type code (1 byte) plus padding, plus
* the field value. So if we have less than 8 bytes left, it must
* be alignment padding, not a field. While >= 8 bytes can't be
* entirely alignment padding.
*/
pos = 16;
while ((pos + 7) < header_len)
while (pos < header_len)
{
pos = _DBUS_ALIGN_VALUE (pos, 4);
if ((pos + 1) > header_len)
{
_dbus_verbose ("not enough space remains in header for header field value\n");
return FALSE;
}
field = _dbus_string_get_byte (data, pos);
pos += 1;
if (field == DBUS_HEADER_FIELD_INVALID)
break; /* Must be padding */
pos++;
if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
{
@ -4737,7 +4825,7 @@ decode_header_data (const DBusString *data,
* type.
*/
if (fields[field].offset >= 0)
if (fields[field].name_offset >= 0)
{
_dbus_verbose ("path field provided twice\n");
return FALSE;
@ -4748,15 +4836,16 @@ decode_header_data (const DBusString *data,
return FALSE;
}
fields[field].offset = _DBUS_ALIGN_VALUE (pos, 4);
fields[field].name_offset = pos;
fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
/* No forging signals from the local path */
{
const char *s;
s = _dbus_string_get_const_data_len (data,
fields[field].offset,
fields[field].value_offset,
_dbus_string_get_length (data) -
fields[field].offset);
fields[field].value_offset);
if (strcmp (s, DBUS_PATH_ORG_FREEDESKTOP_LOCAL) == 0)
{
_dbus_verbose ("Message is on the local path\n");
@ -4765,11 +4854,11 @@ decode_header_data (const DBusString *data,
}
_dbus_verbose ("Found path at offset %d\n",
fields[field].offset);
fields[field].value_offset);
break;
case DBUS_HEADER_FIELD_REPLY_SERIAL:
if (fields[field].offset >= 0)
if (fields[field].name_offset >= 0)
{
_dbus_verbose ("reply field provided twice\n");
return FALSE;
@ -4781,10 +4870,11 @@ decode_header_data (const DBusString *data,
return FALSE;
}
fields[field].offset = _DBUS_ALIGN_VALUE (pos, 4);
fields[field].name_offset = pos;
fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
_dbus_verbose ("Found reply serial at offset %d\n",
fields[field].offset);
fields[field].value_offset);
break;
default:
@ -4798,7 +4888,11 @@ decode_header_data (const DBusString *data,
if (pos < header_len)
{
/* Alignment padding, verify that it's nul */
_dbus_assert ((header_len - pos) < 8);
if ((header_len - pos) >= 8)
{
_dbus_verbose ("too much header alignment padding\n");
return FALSE;
}
if (!_dbus_string_validate_nul (data,
pos, (header_len - pos)))
@ -4813,25 +4907,25 @@ decode_header_data (const DBusString *data,
{
case DBUS_MESSAGE_TYPE_SIGNAL:
case DBUS_MESSAGE_TYPE_METHOD_CALL:
if (fields[DBUS_HEADER_FIELD_PATH].offset < 0)
if (fields[DBUS_HEADER_FIELD_PATH].value_offset < 0)
{
_dbus_verbose ("No path field provided\n");
return FALSE;
}
/* FIXME make this optional, only for method calls */
if (fields[DBUS_HEADER_FIELD_INTERFACE].offset < 0)
if (fields[DBUS_HEADER_FIELD_INTERFACE].value_offset < 0)
{
_dbus_verbose ("No interface field provided\n");
return FALSE;
}
if (fields[DBUS_HEADER_FIELD_MEMBER].offset < 0)
if (fields[DBUS_HEADER_FIELD_MEMBER].value_offset < 0)
{
_dbus_verbose ("No member field provided\n");
return FALSE;
}
break;
case DBUS_MESSAGE_TYPE_ERROR:
if (fields[DBUS_HEADER_FIELD_ERROR_NAME].offset < 0)
if (fields[DBUS_HEADER_FIELD_ERROR_NAME].value_offset < 0)
{
_dbus_verbose ("No error-name field provided\n");
return FALSE;
@ -6069,7 +6163,7 @@ process_test_subdir (const DBusString *test_base_dir,
goto failed;
}
printf ("Testing:\n");
printf ("Testing %s:\n", subdir);
next:
while (_dbus_directory_get_next_file (dir, &filename, &error))
@ -6432,11 +6526,14 @@ _dbus_message_test (const char *test_data_dir)
_dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
"TestMethod"));
_dbus_message_set_serial (message, 1234);
dbus_message_set_sender (message, "org.foo.bar");
_dbus_assert (dbus_message_has_sender (message, "org.foo.bar"));
/* string length including nul byte not a multiple of 4 */
dbus_message_set_sender (message, "org.foo.bar1");
_dbus_assert (dbus_message_has_sender (message, "org.foo.bar1"));
dbus_message_set_reply_serial (message, 5678);
dbus_message_set_sender (message, NULL);
_dbus_assert (!dbus_message_has_sender (message, "org.foo.bar"));
_dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1"));
_dbus_assert (dbus_message_get_serial (message) == 1234);
_dbus_assert (dbus_message_get_reply_serial (message) == 5678);
_dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
_dbus_assert (dbus_message_get_no_reply (message) == FALSE);

View file

@ -562,26 +562,30 @@ _dbus_string_get_byte (const DBusString *str,
}
/**
* Inserts the given byte at the given position.
* Inserts a number of bytes of a given value at the
* given position.
*
* @param str the string
* @param i the position
* @param n_bytes number of bytes
* @param byte the value to insert
* @returns #TRUE on success
*/
dbus_bool_t
_dbus_string_insert_byte (DBusString *str,
int i,
unsigned char byte)
_dbus_string_insert_bytes (DBusString *str,
int i,
int n_bytes,
unsigned char byte)
{
DBUS_STRING_PREAMBLE (str);
_dbus_assert (i <= real->len);
_dbus_assert (i >= 0);
_dbus_assert (n_bytes > 0);
if (!open_gap (1, real, i))
if (!open_gap (n_bytes, real, i))
return FALSE;
real->str[i] = byte;
memset (real->str + i, byte, n_bytes);
return TRUE;
}
@ -3572,23 +3576,26 @@ _dbus_string_test (void)
_dbus_string_set_byte (&str, 1, 'q');
_dbus_assert (_dbus_string_get_byte (&str, 1) == 'q');
if (!_dbus_string_insert_byte (&str, 0, 255))
if (!_dbus_string_insert_bytes (&str, 0, 1, 255))
_dbus_assert_not_reached ("can't insert byte");
if (!_dbus_string_insert_byte (&str, 2, 'Z'))
if (!_dbus_string_insert_bytes (&str, 2, 4, 'Z'))
_dbus_assert_not_reached ("can't insert byte");
if (!_dbus_string_insert_byte (&str, _dbus_string_get_length (&str), 'W'))
if (!_dbus_string_insert_bytes (&str, _dbus_string_get_length (&str), 1, 'W'))
_dbus_assert_not_reached ("can't insert byte");
_dbus_assert (_dbus_string_get_byte (&str, 0) == 255);
_dbus_assert (_dbus_string_get_byte (&str, 1) == 'H');
_dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z');
_dbus_assert (_dbus_string_get_byte (&str, 3) == 'q');
_dbus_assert (_dbus_string_get_byte (&str, 4) == 'l');
_dbus_assert (_dbus_string_get_byte (&str, 5) == 'l');
_dbus_assert (_dbus_string_get_byte (&str, 6) == 'o');
_dbus_assert (_dbus_string_get_byte (&str, 7) == 'W');
_dbus_assert (_dbus_string_get_byte (&str, 3) == 'Z');
_dbus_assert (_dbus_string_get_byte (&str, 4) == 'Z');
_dbus_assert (_dbus_string_get_byte (&str, 5) == 'Z');
_dbus_assert (_dbus_string_get_byte (&str, 6) == 'q');
_dbus_assert (_dbus_string_get_byte (&str, 7) == 'l');
_dbus_assert (_dbus_string_get_byte (&str, 8) == 'l');
_dbus_assert (_dbus_string_get_byte (&str, 9) == 'o');
_dbus_assert (_dbus_string_get_byte (&str, 10) == 'W');
_dbus_string_free (&str);

View file

@ -72,8 +72,9 @@ void _dbus_string_set_byte (DBusString *str,
unsigned char byte);
unsigned char _dbus_string_get_byte (const DBusString *str,
int start);
dbus_bool_t _dbus_string_insert_byte (DBusString *str,
dbus_bool_t _dbus_string_insert_bytes (DBusString *str,
int i,
int n_bytes,
unsigned char byte);
dbus_bool_t _dbus_string_steal_data (DBusString *str,
char **data_return);

View file

@ -90,8 +90,6 @@
- document the auth protocol as a set of states and transitions, and
then reimplement it in those terms
- Header fields names are required to be aligned on a 4 byte boundary
at the moment. No alignment should be neccessary.
- dbus_gproxy or dbus_g_proxy?
- The OBJECT_PATH type is not documented in the spec.

View file

@ -265,11 +265,10 @@
</para>
<para>
Header fields MUST be aligned to a 4-byte boundary. Header field
names MUST consist of a single byte, possible values of which are
defined below. Following the name, the field MUST have a type code
represented as a single unsigned byte, and then a properly-aligned
value of that type. See <xref
Header field names MUST consist of a single byte, possible values
of which are defined below. Following the name, the field MUST have
a type code represented as a single unsigned byte, and then a
properly-aligned value of that type. See <xref
linkend="message-protocol-arguments"> for a description of how each
type is encoded. If an implementation sees a header field name that
it does not understand, it MUST ignore that field.
@ -358,10 +357,9 @@
buffer while keeping data types aligned, the total length of the header
must be a multiple of 8 bytes. To achieve this, the header MUST be padded
with nul bytes to align its total length on an 8-byte boundary.
The minimum number of padding bytes MUST be used. Because all possible
named fields use at least 8 bytes, implementations can distinguish
padding (which must be less than 8 bytes) from additional named fields
(which must be at least 8 bytes).
The minimum number of padding bytes MUST be used. Because zero is an
invalid field name, implementations can distinguish padding (which must be
zero initialized) from additional named fields.
</para>
</sect2>

View file

@ -287,8 +287,8 @@ randomly_add_one_byte (const DBusString *orig_data,
i = random_int_in_range (0, _dbus_string_get_length (mutated));
_dbus_string_insert_byte (mutated, i,
random_int_in_range (0, 256));
_dbus_string_insert_bytes (mutated, i, 1,
random_int_in_range (0, 256));
}
static void

View file

@ -0,0 +1,34 @@
## last field incorrectly aligned to 4 bytes
## VALID_HEADER includes a LENGTH Header and LENGTH Body
VALID_HEADER method_call
HEADER_FIELD INTERFACE
TYPE STRING
STRING 'org.freedesktop.Foo'
HEADER_FIELD MEMBER
TYPE STRING
STRING 'Bar'
HEADER_FIELD UNKNOWN
TYPE STRING
STRING 'a'
ALIGN 4
HEADER_FIELD UNKNOWN
TYPE ARRAY
TYPE BYTE
ALIGN 4
LENGTH ThisByteArray
START_LENGTH ThisByteArray
BYTE 1
BYTE 2
END_LENGTH ThisByteArray
ALIGN 8
END_LENGTH Header
START_LENGTH Body
END_LENGTH Body

View file

@ -3,9 +3,16 @@
## VALID_HEADER includes a LENGTH Header and LENGTH Body
VALID_HEADER method_call
REQUIRED_FIELDS
HEADER_FIELD UNKNOWN
TYPE DICT
LENGTH Dict
START_LENGTH Dict
STRING 'int32'
TYPE INT32
INT32 0xfeeb
INT32 0x12345678
END_LENGTH Dict
ALIGN 8
END_LENGTH Header
START_LENGTH Body