X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=test%2Fcorrupt.c;h=1a7d44607f4e0d86ee5419c6290d0eac19c5a226;hb=7d9239c9c78cb6d0b9c282376fcf3cda1de23209;hp=eb8e049f22981a0ca757fa3de64632ad114155d6;hpb=f43d76a83b12ae0f230a9a23082bf87cb71bf52f;p=platform%2Fupstream%2Fdbus.git diff --git a/test/corrupt.c b/test/corrupt.c index eb8e049..1a7d446 100644 --- a/test/corrupt.c +++ b/test/corrupt.c @@ -30,10 +30,12 @@ #include #include -#include + +#include "test-utils.h" typedef struct { DBusError e; + TestMainContext *ctx; DBusServer *server; DBusConnection *server_conn; @@ -72,13 +74,14 @@ new_conn_cb (DBusServer *server, g_assert (f->server_conn == NULL); f->server_conn = dbus_connection_ref (server_conn); - dbus_connection_setup_with_g_main (server_conn, NULL); + test_connection_setup (f->ctx, server_conn); } static void setup (Fixture *f, gconstpointer addr) { + f->ctx = test_main_context_get (); dbus_error_init (&f->e); g_queue_init (&f->client_messages); @@ -88,7 +91,7 @@ setup (Fixture *f, dbus_server_set_new_connection_function (f->server, new_conn_cb, f, NULL); - dbus_server_setup_with_g_main (f->server, NULL); + test_server_setup (f->ctx, f->server); } static void @@ -103,12 +106,12 @@ test_connect (Fixture *f, dbus_server_get_address (f->server), &f->e); assert_no_error (&f->e); g_assert (f->client_conn != NULL); - dbus_connection_setup_with_g_main (f->client_conn, NULL); + test_connection_setup (f->ctx, f->client_conn); while (f->server_conn == NULL) { g_print ("."); - g_main_context_iteration (NULL, TRUE); + test_main_context_iterate (f->ctx, TRUE); } have_mem = dbus_connection_add_filter (f->client_conn, @@ -137,7 +140,7 @@ test_message (Fixture *f, while (g_queue_is_empty (&f->client_messages)) { g_print ("."); - g_main_context_iteration (NULL, TRUE); + test_main_context_iterate (f->ctx, TRUE); } g_assert_cmpuint (g_queue_get_length (&f->client_messages), ==, 1); @@ -160,6 +163,38 @@ test_message (Fixture *f, dbus_message_unref (outgoing); } +static void +send_n_bytes (GSocket *socket, + const gchar *blob, + gssize blob_len) +{ + gssize len, total_sent; + GError *gerror = NULL; + + total_sent = 0; + + while (total_sent < blob_len) + { + len = g_socket_send (socket, + blob + total_sent, + blob_len - total_sent, + NULL, &gerror); + + /* this is NULL-safe: a NULL error does not match */ + if (g_error_matches (gerror, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) + { + /* we could wait for G_IO_OUT, but life's too short; just sleep */ + g_clear_error (&gerror); + g_usleep (G_USEC_PER_SEC / 10); + continue; + } + + g_assert_no_error (gerror); + g_assert (len >= 0); + total_sent += len; + } +} + /* Enough bytes for it to be obvious that this connection is broken */ #define CORRUPT_LEN 1024 @@ -174,7 +209,6 @@ test_corrupt (Fixture *f, GSocket *socket; GError *gerror = NULL; int fd; - gssize len, total_sent; DBusMessage *incoming; test_message (f, addr); @@ -191,24 +225,14 @@ test_corrupt (Fixture *f, g_assert_no_error (gerror); g_assert (socket != NULL); - total_sent = 0; - - while (total_sent < CORRUPT_LEN) - { - len = g_socket_send_with_blocking (socket, - not_a_dbus_message + total_sent, CORRUPT_LEN - total_sent, - TRUE, NULL, &gerror); - g_assert_no_error (gerror); - g_assert (len >= 0); - total_sent += len; - } + send_n_bytes (socket, not_a_dbus_message, CORRUPT_LEN); /* Now spin on the client connection: the server just sent it complete * rubbish, so it should disconnect */ while (g_queue_is_empty (&f->client_messages)) { g_print ("."); - g_main_context_iteration (NULL, TRUE); + test_main_context_iterate (f->ctx, TRUE); } incoming = g_queue_pop_head (&f->client_messages); @@ -225,6 +249,102 @@ test_corrupt (Fixture *f, "/org/freedesktop/DBus/Local"); dbus_message_unref (incoming); + + /* Free the DBusConnection before the GSocket, because GSocket is + * going to close our fd. GSocket tolerates closing an already-closed + * fd, whereas DBusLoop + DBusSocketSetEpoll doesn't. On Unix + * we could use dup() but that isn't portable to Windows :-( + */ + dbus_connection_close (f->server_conn); + dbus_connection_unref (f->server_conn); + f->server_conn = NULL; + + g_object_unref (socket); +} + +static void +test_byte_order (Fixture *f, + gconstpointer addr) +{ + GSocket *socket; + GError *gerror = NULL; + int fd; + char *blob; + const gchar *arg = not_a_dbus_message; + const gchar * const *args = &arg; + int blob_len; + DBusMessage *message; + dbus_bool_t mem; + + test_message (f, addr); + + message = dbus_message_new_signal ("/", "a.b", "c"); + g_assert (message != NULL); + /* Append 0xFF bytes, so that the length of the body when byte-swapped + * is 0xFF000000, which is invalid */ + mem = dbus_message_append_args (message, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &args, 0xFF, + DBUS_TYPE_INVALID); + g_assert (mem); + mem = dbus_message_marshal (message, &blob, &blob_len); + g_assert (mem); + g_assert_cmpuint (blob_len, >, 0xFF); + g_assert (blob != NULL); + + dbus_message_unref (message); + + /* Break the message by changing its claimed byte order, without actually + * byteswapping anything. We happen to know that byte order is the first + * byte. */ + if (blob[0] == 'B') + blob[0] = 'l'; + else + blob[0] = 'B'; + + /* OK, now the connection is working, let's break it */ + + dbus_connection_flush (f->server_conn); + + if (!dbus_connection_get_socket (f->server_conn, &fd)) + g_error ("failed to steal fd from server connection"); + + socket = g_socket_new_from_fd (fd, &gerror); + g_assert_no_error (gerror); + g_assert (socket != NULL); + + send_n_bytes (socket, blob, blob_len); + + dbus_free (blob); + + /* Now spin on the client connection: the server just sent it a faulty + * message, so it should disconnect */ + while (g_queue_is_empty (&f->client_messages)) + { + g_print ("."); + test_main_context_iterate (f->ctx, TRUE); + } + + message = g_queue_pop_head (&f->client_messages); + + g_assert (!dbus_message_contains_unix_fds (message)); + g_assert_cmpstr (dbus_message_get_destination (message), ==, NULL); + g_assert_cmpstr (dbus_message_get_error_name (message), ==, NULL); + g_assert_cmpstr (dbus_message_get_interface (message), ==, + "org.freedesktop.DBus.Local"); + g_assert_cmpstr (dbus_message_get_member (message), ==, "Disconnected"); + g_assert_cmpstr (dbus_message_get_sender (message), ==, NULL); + g_assert_cmpstr (dbus_message_get_signature (message), ==, ""); + g_assert_cmpstr (dbus_message_get_path (message), ==, + "/org/freedesktop/DBus/Local"); + + dbus_message_unref (message); + + /* Free the DBusConnection before the GSocket, as above. */ + dbus_connection_close (f->server_conn); + dbus_connection_unref (f->server_conn); + f->server_conn = NULL; + + g_object_unref (socket); } static void @@ -251,6 +371,8 @@ teardown (Fixture *f, dbus_server_unref (f->server); f->server = NULL; } + + test_main_context_unref (f->ctx); } int @@ -268,5 +390,8 @@ main (int argc, test_corrupt, teardown); #endif + g_test_add ("/corrupt/byte-order/tcp", Fixture, "tcp:host=127.0.0.1", setup, + test_byte_order, teardown); + return g_test_run (); }