GDBusMessage: Validate header fields when serializing/deserializing

The D-Bus spec mentions exactly what header fields are required for
various message types. Add tests for this as well.

Also disallow empty interfaces for signals since the D-Bus spec says
this is Verboten already.

Signed-off-by: David Zeuthen <davidz@redhat.com>
This commit is contained in:
David Zeuthen
2010-08-04 14:38:51 -04:00
parent 6f070be65b
commit 89a1b571ad
3 changed files with 268 additions and 11 deletions

View File

@@ -20,6 +20,7 @@
* Author: David Zeuthen <davidz@redhat.com>
*/
#include <locale.h>
#include <gio/gio.h>
#include <string.h>
@@ -821,16 +822,170 @@ message_serialize_invalid (void)
/* ---------------------------------------------------------------------------------------------------- */
static void
message_serialize_header_checks (void)
{
GDBusMessage *message;
GDBusMessage *reply;
GError *error;
guchar *blob;
gsize blob_size;
/*
* check we can't serialize messages with INVALID type
*/
message = g_dbus_message_new ();
error = NULL;
blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
g_assert_cmpstr (error->message, ==, "Cannot serialize message: type is INVALID");
g_error_free (error);
g_assert (blob == NULL);
g_object_unref (message);
/*
* check we can't serialize signal messages with INTERFACE, PATH or MEMBER unset / set to reserved value
*/
message = g_dbus_message_new_signal ("/the/path", "The.Interface", "TheMember");
/* ----- */
/* interface NULL => error */
g_dbus_message_set_interface (message, NULL);
error = NULL;
blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: PATH, INTERFACE or MEMBER header field is missing");
g_error_free (error);
g_assert (blob == NULL);
/* interface reserved value => error */
g_dbus_message_set_interface (message, "org.freedesktop.DBus.Local");
error = NULL;
blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: The INTERFACE header field is using the reserved value org.freedesktop.DBus.Local");
g_error_free (error);
g_assert (blob == NULL);
/* reset interface */
g_dbus_message_set_interface (message, "The.Interface");
/* ----- */
/* path NULL => error */
g_dbus_message_set_path (message, NULL);
error = NULL;
blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: PATH, INTERFACE or MEMBER header field is missing");
g_error_free (error);
g_assert (blob == NULL);
/* path reserved value => error */
g_dbus_message_set_path (message, "/org/freedesktop/DBus/Local");
error = NULL;
blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: The PATH header field is using the reserved value /org/freedesktop/DBus/Local");
g_error_free (error);
g_assert (blob == NULL);
/* reset path */
g_dbus_message_set_path (message, "/the/path");
/* ----- */
/* member NULL => error */
g_dbus_message_set_member (message, NULL);
error = NULL;
blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: PATH, INTERFACE or MEMBER header field is missing");
g_error_free (error);
g_assert (blob == NULL);
/* reset member */
g_dbus_message_set_member (message, "TheMember");
/* ----- */
/* done */
g_object_unref (message);
/*
* check that we can't serialize method call messages with PATH or MEMBER unset
*/
message = g_dbus_message_new_method_call (NULL, "/the/path", NULL, "TheMember");
/* ----- */
/* path NULL => error */
g_dbus_message_set_path (message, NULL);
error = NULL;
blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
g_assert_cmpstr (error->message, ==, "Cannot serialize message: METHOD_CALL message: PATH or MEMBER header field is missing");
g_error_free (error);
g_assert (blob == NULL);
/* reset path */
g_dbus_message_set_path (message, "/the/path");
/* ----- */
/* member NULL => error */
g_dbus_message_set_member (message, NULL);
error = NULL;
blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
g_assert_cmpstr (error->message, ==, "Cannot serialize message: METHOD_CALL message: PATH or MEMBER header field is missing");
g_error_free (error);
g_assert (blob == NULL);
/* reset member */
g_dbus_message_set_member (message, "TheMember");
/* ----- */
/* done */
g_object_unref (message);
/*
* check that we can't serialize method reply messages with REPLY_SERIAL unset
*/
message = g_dbus_message_new_method_call (NULL, "/the/path", NULL, "TheMember");
g_dbus_message_set_serial (message, 42);
/* method reply */
reply = g_dbus_message_new_method_reply (message);
g_assert_cmpint (g_dbus_message_get_reply_serial (reply), ==, 42);
g_dbus_message_set_header (reply, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, NULL);
error = NULL;
blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
g_assert_cmpstr (error->message, ==, "Cannot serialize message: METHOD_RETURN message: REPLY_SERIAL header field is missing");
g_error_free (error);
g_assert (blob == NULL);
g_object_unref (reply);
/* method error - first nuke ERROR_NAME, then REPLY_SERIAL */
reply = g_dbus_message_new_method_error (message, "Some.Error.Name", "the message");
g_assert_cmpint (g_dbus_message_get_reply_serial (reply), ==, 42);
/* nuke ERROR_NAME */
g_dbus_message_set_error_name (reply, NULL);
error = NULL;
blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
g_assert_cmpstr (error->message, ==, "Cannot serialize message: ERROR message: REPLY_SERIAL or ERROR_NAME header field is missing");
g_error_free (error);
g_assert (blob == NULL);
/* reset ERROR_NAME */
g_dbus_message_set_error_name (reply, "Some.Error.Name");
/* nuke REPLY_SERIAL */
g_dbus_message_set_header (reply, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, NULL);
error = NULL;
blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
g_assert_cmpstr (error->message, ==, "Cannot serialize message: ERROR message: REPLY_SERIAL or ERROR_NAME header field is missing");
g_error_free (error);
g_assert (blob == NULL);
g_object_unref (reply);
g_object_unref (message);
}
/* ---------------------------------------------------------------------------------------------------- */
int
main (int argc,
char *argv[])
{
setlocale (LC_ALL, "C");
g_type_init ();
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/gdbus/message-serialize-basic", message_serialize_basic);
g_test_add_func ("/gdbus/message-serialize-complex", message_serialize_complex);
g_test_add_func ("/gdbus/message-serialize-invalid", message_serialize_invalid);
g_test_add_func ("/gdbus/message-serialize-header-checks", message_serialize_header_checks);
return g_test_run();
}