From c5482002db0695859ffb5ce124d779770682d697 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 15 Sep 2014 15:53:20 +0100 Subject: [PATCH 1/3] Add a regression test for fd.o #83530 --- test/core/Makefile.am | 8 ++ test/core/my-object.c | 3 + test/core/my-object.h | 1 + test/core/run-test.sh | 1 + test/core/unsupported-type.c | 334 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 347 insertions(+) create mode 100644 test/core/unsupported-type.c diff --git a/test/core/Makefile.am b/test/core/Makefile.am index e4bceb4..9897d71 100644 --- a/test/core/Makefile.am +++ b/test/core/Makefile.am @@ -78,6 +78,7 @@ noinst_PROGRAMS = \ test-proxy-noc \ test-proxy-peer \ test-registrations \ + test-unsupported-type \ test-variant-recursion \ test-gvariant \ test-shared-bus \ @@ -176,6 +177,13 @@ test_peer_on_bus_SOURCES = peer-on-bus.c test_shared_bus_SOURCES = shared-bus.c +test_unsupported_type_SOURCES = \ + my-object.c \ + my-object.h \ + my-object-marshal.c \ + unsupported-type.c \ + $(NULL) + CLEANFILES = \ $(BUILT_SOURCES) \ run-with-tmp-session-bus.conf diff --git a/test/core/my-object.c b/test/core/my-object.c index e31dca3..688ef96 100644 --- a/test/core/my-object.c +++ b/test/core/my-object.c @@ -674,6 +674,9 @@ gboolean my_object_echo_variant (MyObject *obj, GValue *variant, GValue *ret, GError **error) { GType t; + + obj->echo_variant_called++; + t = G_VALUE_TYPE(variant); g_value_init (ret, t); g_value_copy (variant, ret); diff --git a/test/core/my-object.h b/test/core/my-object.h index 779efac..759ac0a 100644 --- a/test/core/my-object.h +++ b/test/core/my-object.h @@ -19,6 +19,7 @@ struct MyObject guint val; gdouble super_studly; gboolean should_be_hidden; + gsize echo_variant_called; }; struct MyObjectClass diff --git a/test/core/run-test.sh b/test/core/run-test.sh index fe4dc21..777bb92 100755 --- a/test/core/run-test.sh +++ b/test/core/run-test.sh @@ -53,4 +53,5 @@ else ${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/core/test-private || die "test-private failed" ${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/core/test-error-mapping || die "test-error-mapping failed" ${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/core/test-peer-on-bus || die "test-peer-on-bus failed" + ${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/core/test-unsupported-type || die "test-unsupported-type failed" fi diff --git a/test/core/unsupported-type.c b/test/core/unsupported-type.c new file mode 100644 index 0000000..f8dca7c --- /dev/null +++ b/test/core/unsupported-type.c @@ -0,0 +1,334 @@ +/* + * Copyright © 2009-2014 Collabora Ltd. + * Copyright © 2009-2011 Nokia Corporation + * + * In preparation for dbus-glib relicensing (if it ever happens), this file is + * licensed under (at your option) either the AFL v2.1, the GPL v2 or later, + * or an MIT/X11-style license: + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include + +#ifdef G_OS_UNIX +# include +# include +# include +# include +#endif + +#include "my-object.h" + +GMainLoop *loop = NULL; + +typedef struct { + DBusGConnection *bus; + GObject *object; + DBusGProxy *proxy; + DBusGProxyCall *call; + gsize in_flight; + int fd; +} Fixture; + +#ifdef G_OS_UNIX +static void +call_cb (DBusGProxy *proxy, + DBusGProxyCall *call, + gpointer user_data) +{ + Fixture *f = user_data; + + g_assert (proxy == f->proxy); + g_assert (call == f->call); + + f->in_flight--; +} + +static void +setup (Fixture *f, + gconstpointer path_to_use) +{ + DBusConnection *libdbus; + + f->bus = dbus_g_bus_get_private (DBUS_BUS_SESSION, + g_main_context_default (), NULL); + g_assert (f->bus != NULL); + libdbus = dbus_g_connection_get_connection (f->bus); + dbus_connection_set_exit_on_disconnect (libdbus, FALSE); + + f->object = g_object_new (MY_TYPE_OBJECT, NULL); + g_assert (MY_IS_OBJECT (f->object)); + dbus_g_connection_register_g_object (f->bus, "/object", + (GObject *) f->object); + + f->proxy = dbus_g_proxy_new_for_name (f->bus, + dbus_bus_get_unique_name (libdbus), + "/notdbusglib", "org.freedesktop.DBus.GLib.Tests.Example"); + + f->fd = g_open ("/dev/null", O_RDONLY, 0); + + if (f->fd < 0) + g_error ("unable to open /dev/null: %s", g_strerror (errno)); +} + +static void +teardown (Fixture *f, + gconstpointer test_data G_GNUC_UNUSED) +{ + g_clear_object (&f->proxy); + + if (f->object != NULL) + { + dbus_g_connection_unregister_g_object (f->bus, f->object); + g_object_unref (f->object); + } + + if (f->bus != NULL) + { + dbus_connection_close (dbus_g_connection_get_connection (f->bus)); + dbus_g_connection_unref (f->bus); + } + + if (f->fd >= 0) + { + close (f->fd); + f->fd = -1; + } +} + +static void +pending_call_store_reply (DBusPendingCall *pc, + void *data) +{ + DBusMessage **message_p = data; + + g_assert (*message_p == NULL); + *message_p = dbus_pending_call_steal_reply (pc); + g_assert (*message_p != NULL); +} + +/* + * Exercise a call to a dbus-glib method with an unsupported parameter + * type. The only unsupported parameter type we know is 'h', a Unix fd, + * which is why this test is Unix-only. + */ +static void +test_call (Fixture *f, + gconstpointer test_data G_GNUC_UNUSED) +{ + DBusConnection *libdbus = dbus_g_connection_get_connection (f->bus); + const char *unique = dbus_bus_get_unique_name (libdbus); + DBusMessage *m = dbus_message_new_method_call (unique, + "/object", "org.freedesktop.DBus.GLib.Tests.MyObject", + "EchoVariant"); + DBusPendingCall *pc; + DBusMessageIter iter; + DBusMessageIter var_iter; + DBusMessage *reply = NULL; + + if (m == NULL) + g_error ("OOM"); + + dbus_message_iter_init_append (m, &iter); + + if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, + DBUS_TYPE_UNIX_FD_AS_STRING, &var_iter)) + g_error ("OOM"); + + if (!dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_UNIX_FD, + &f->fd)) + { + /* FIXME: cannot distinguish between inability to use fd and OOM */ + dbus_message_iter_abandon_container (&iter, &var_iter); + dbus_message_unref (m); + g_test_skip ("Unix fd-passing does not appear to be supported"); + return; + } + + if (!dbus_message_iter_close_container (&iter, &var_iter)) + g_error ("OOM"); + + if (!dbus_connection_send_with_reply (libdbus, m, &pc, -1) || pc == NULL) + g_error ("OOM"); + + if (dbus_pending_call_get_completed (pc)) + pending_call_store_reply (pc, &reply); + else if (!dbus_pending_call_set_notify (pc, pending_call_store_reply, + &reply, NULL)) + g_error ("OOM"); + + dbus_message_unref (m); + + while (reply == NULL) + g_main_context_iteration (NULL, TRUE); + + dbus_pending_call_unref (pc); + + /* it didn't work */ +#if 0 + /* this is what it should be */ + g_assert_cmpstr (dbus_message_get_error_name (reply), ==, + DBUS_ERROR_INVALID_SIGNATURE); +#else + /* this is what it is right now */ + g_assert_cmpstr (dbus_message_get_error_name (reply), ==, + "org.freedesktop.DBus.GLib.ErrorError"); +#endif + /* it didn't call the into the user-supplied C code */ + g_assert_cmpuint (MY_OBJECT (f->object)->echo_variant_called, ==, 0); + + dbus_message_unref (reply); +} + +/* + * Exercise a call from dbus-glib to a method returning an unsupported + * parameter type. Again, the only unsupported parameter type we know is 'h'. + */ +static void +unregister_cb (DBusConnection *conn, + void *user_data) +{ +} + +static DBusHandlerResult +message_cb (DBusConnection *conn, + DBusMessage *m, + void *user_data) +{ + Fixture *f = user_data; + DBusMessage *reply = dbus_message_new_method_return (m); + DBusMessageIter iter; + DBusMessageIter var_iter; + + if (reply == NULL) + g_error ("OOM"); + + dbus_message_iter_init_append (reply, &iter); + + if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, + DBUS_TYPE_UNIX_FD_AS_STRING, &var_iter)) + g_error ("OOM"); + + if (dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_UNIX_FD, + &f->fd)) + { + if (!dbus_message_iter_close_container (&iter, &var_iter)) + g_error ("OOM"); + } + else + { + /* FIXME: cannot distinguish between inability to use fd and OOM */ + dbus_message_iter_abandon_container (&iter, &var_iter); + dbus_message_unref (reply); + reply = dbus_message_new_error (m, + DBUS_ERROR_NOT_SUPPORTED, "Unable to append Unix fd"); + + if (reply == NULL) + g_error ("OOM"); + } + + if (!dbus_connection_send (conn, reply, NULL)) + g_error ("OOM"); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusObjectPathVTable vtable = { + unregister_cb, + message_cb, + NULL, + NULL, + NULL, + NULL +}; + +static void +test_ret (Fixture *f, + gconstpointer test_data G_GNUC_UNUSED) +{ + DBusConnection *libdbus = dbus_g_connection_get_connection (f->bus); + GError *error = NULL; + GValue value; + + dbus_connection_register_object_path (libdbus, "/notdbusglib", + &vtable, f); + + f->in_flight = 1; + f->call = dbus_g_proxy_begin_call (f->proxy, "ReturnUnixFd", + call_cb, f, NULL, + G_TYPE_INVALID); + + while (f->in_flight > 0) + g_main_context_iteration (NULL, TRUE); + + if (dbus_g_proxy_end_call (f->proxy, f->call, &error, + G_TYPE_VALUE, &value, + G_TYPE_INVALID)) + { + g_error ("that shouldn't have worked!"); + } + + if (g_error_matches (error, DBUS_GERROR, DBUS_GERROR_NOT_SUPPORTED)) + { + g_test_skip ("couldn't send a Unix fd"); + } + else + { + g_assert_error (error, DBUS_GERROR, DBUS_GERROR_INVALID_ARGS); + } + + g_clear_error (&error); + dbus_connection_unregister_object_path (libdbus, "/notdbusglib"); +} +#endif + +int +main (int argc, + char **argv) +{ + g_type_init (); + dbus_g_type_specialized_init (); + + g_test_init (&argc, &argv, NULL); + +#ifdef G_OS_UNIX + g_test_add ("/unsupported-type/call", + Fixture, NULL, setup, test_call, teardown); + g_test_add ("/unsupported-type/ret", + Fixture, NULL, setup, test_ret, teardown); +#endif + + return g_test_run (); +} -- 2.1.0