summaryrefslogtreecommitdiffstats
path: root/dbus/dbus-marshal.c
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2003-01-26 07:48:16 +0000
committerHavoc Pennington <hp@redhat.com>2003-01-26 07:48:16 +0000
commit50c25505f62786756519ef1e194883360eda82e0 (patch)
tree968d4b0b148a78a665ea7b023350047e070aafed /dbus/dbus-marshal.c
parentd5ad082fecbbd803fd89b3574ac137b3fa964bc7 (diff)
2003-01-26 Havoc Pennington <hp@pobox.com>
The unit tests pass, but otherwise untested. If it breaks, the tests should have been better. ;-) * bus/driver.c (bus_driver_handle_hello): return if we disconnect the connection. * dbus/dbus-message.c: redo everything so we maintain message->header as the only copy of the various fields. This avoids the possibility of out-of-memory in some cases, for example dbus_message_lock() can't run out of memory anymore, and avoids extra copying. Figured I may as well go ahead and do this since it was busted for dbus_message_lock to not return failure on OOM, and dbus_message_write_header was totally unchecked for OOM. Also fixed some random other bugs. * dbus/dbus-marshal.c (_dbus_marshal_get_field_end_pos): verify that strings are nul-terminated. Also, end_pos can be equal to string length just not greater than, I think. (_dbus_marshal_set_int32): new function (_dbus_marshal_set_uint32): new function (_dbus_marshal_set_string): new function * dbus/dbus-connection.c (_dbus_connection_new_for_transport): fix a warning, init timeout_list to NULL (dbus_connection_send_message): don't use uninitialized variable "serial" * dbus/dbus-string.c (_dbus_string_replace_len): new function
Diffstat (limited to 'dbus/dbus-marshal.c')
-rw-r--r--dbus/dbus-marshal.c117
1 files changed, 113 insertions, 4 deletions
diff --git a/dbus/dbus-marshal.c b/dbus/dbus-marshal.c
index 231e4b3b..aa6e2c6b 100644
--- a/dbus/dbus-marshal.c
+++ b/dbus/dbus-marshal.c
@@ -135,6 +135,98 @@ _dbus_pack_int32 (dbus_int32_t value,
}
/**
+ * Sets the 4 bytes at the given offset to a marshaled signed integer,
+ * replacing anything found there previously.
+ *
+ * @param str the string to write the marshalled int to
+ * @param offset the byte offset where int should be written
+ * @param byte_order the byte order to use
+ * @param value the value
+ *
+ */
+void
+_dbus_marshal_set_int32 (DBusString *str,
+ int byte_order,
+ int offset,
+ dbus_int32_t value)
+{
+ char *data;
+
+ _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
+ byte_order == DBUS_BIG_ENDIAN);
+
+ _dbus_string_get_data_len (str, &data, offset, 4);
+
+ _dbus_pack_int32 (value, byte_order, data);
+}
+
+/**
+ * Sets the 4 bytes at the given offset to a marshaled unsigned
+ * integer, replacing anything found there previously.
+ *
+ * @param str the string to write the marshalled int to
+ * @param offset the byte offset where int should be written
+ * @param byte_order the byte order to use
+ * @param value the value
+ *
+ */
+void
+_dbus_marshal_set_uint32 (DBusString *str,
+ int byte_order,
+ int offset,
+ dbus_uint32_t value)
+{
+ char *data;
+
+ _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
+ byte_order == DBUS_BIG_ENDIAN);
+
+ _dbus_string_get_data_len (str, &data, offset, 4);
+
+ _dbus_pack_uint32 (value, byte_order, data);
+}
+
+/**
+ * Sets the existing marshaled string at the given offset with
+ * a new marshaled string. The given offset must point to
+ * an existing string or the wrong length will be deleted
+ * and replaced with the new string.
+ *
+ * @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
+ * @param value the value
+ * @returns #TRUE on success
+ *
+ */
+dbus_bool_t
+_dbus_marshal_set_string (DBusString *str,
+ int byte_order,
+ int offset,
+ const DBusString *value)
+{
+ int old_len;
+ int new_len;
+
+ _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
+ byte_order == DBUS_BIG_ENDIAN);
+
+ old_len = _dbus_demarshal_uint32 (str, byte_order,
+ offset, NULL);
+
+ new_len = _dbus_string_get_length (value);
+
+ if (!_dbus_string_replace_len (value, 0, new_len,
+ str, offset + 4, old_len))
+ return FALSE;
+
+ _dbus_marshal_set_uint32 (str, byte_order,
+ offset, new_len);
+
+ return TRUE;
+}
+
+/**
* Marshals a double value.
*
* @param str the string to append the marshalled value to
@@ -175,7 +267,7 @@ _dbus_marshal_int32 (DBusString *str,
return FALSE;
if (byte_order != DBUS_COMPILER_BYTE_ORDER)
- swap_bytes ((unsigned char *)&value, sizeof (dbus_int32_t));
+ value = DBUS_INT32_SWAP_LE_BE (value);
return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_int32_t));
}
@@ -197,7 +289,7 @@ _dbus_marshal_uint32 (DBusString *str,
return FALSE;
if (byte_order != DBUS_COMPILER_BYTE_ORDER)
- swap_bytes ((unsigned char *)&value, sizeof (dbus_uint32_t));
+ value = DBUS_UINT32_SWAP_LE_BE (value);
return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_uint32_t));
}
@@ -752,8 +844,13 @@ _dbus_demarshal_string_array (DBusString *str,
/**
* Returns the position right after the end position
- * end position of a field
+ * end position of a field. Validates the field
+ * contents as required (e.g. ensures that
+ * string fields have a valid length and
+ * are nul-terminated).
*
+ * @todo security: audit the field validation code.
+ *
* @todo warns on invalid type in a message, but
* probably the whole message needs to be dumped,
* or we might even drop the connection due
@@ -810,6 +907,18 @@ _dbus_marshal_get_field_end_pos (DBusString *str,
*end_pos = pos + len + 1;
+ if (*end_pos > _dbus_string_get_length (str))
+ {
+ _dbus_verbose ("string length outside length of the message\n");
+ return FALSE;
+ }
+
+ if (_dbus_string_get_byte (str, pos+len) != '\0')
+ {
+ _dbus_verbose ("string field not nul-terminated\n");
+ return FALSE;
+ }
+
break;
}
@@ -888,7 +997,7 @@ _dbus_marshal_get_field_end_pos (DBusString *str,
return FALSE;
}
- if (*end_pos >= _dbus_string_get_length (str))
+ if (*end_pos > _dbus_string_get_length (str))
return FALSE;
return TRUE;