summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2008-06-19 16:47:16 (GMT)
committerColin Walters <walters@verbum.org>2008-06-19 16:47:16 (GMT)
commit2514b84b3644223653018cd75d0d6e1459a7ab70 (patch)
tree780b394253f0f6f698979d4302c9ffb96b76e56a
parentd1b80d803a0268bd4b3dd5b9a9522230461f2947 (diff)
downloaddbus-glib-2514b84b3644223653018cd75d0d6e1459a7ab70.tar.gz
dbus-glib-2514b84b3644223653018cd75d0d6e1459a7ab70.tar.xz
Bug 16419: stack overflow demarshaling recursive variants
* dbus/dbus-gvalue.h: Add a recursion_depth member. * dbus/dbus-gvalue.c: Keep track of recursion depth in _dbus_gvalue_demarshal, cut it off at a default (right now 32). * dbus/dbus-gobject.c: Initialize recursion depth. * dbus/dbus-gproxy.c: Ditto. * test/core/test-variant-recursion.c: Test the variant recursion case, make sure the remote site will throw an error. * test/core/Makefile.am: Add test-variant-recursion.
-rw-r--r--dbus/dbus-gobject.c2
-rw-r--r--dbus/dbus-gproxy.c2
-rw-r--r--dbus/dbus-gvalue.c21
-rw-r--r--dbus/dbus-gvalue.h1
-rw-r--r--test/core/Makefile.am6
-rwxr-xr-xtest/core/run-test.sh1
-rw-r--r--test/core/test-variant-recursion.c89
7 files changed, 119 insertions, 3 deletions
diff --git a/dbus/dbus-gobject.c b/dbus/dbus-gobject.c
index ee76011..b6e72e2 100644
--- a/dbus/dbus-gobject.c
+++ b/dbus/dbus-gobject.c
@@ -679,6 +679,7 @@ set_object_property (DBusConnection *connection,
dbus_message_iter_recurse (iter, &sub);
+ context.recursion_depth = 0;
context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (connection);
context.proxy = NULL;
@@ -1111,6 +1112,7 @@ invoke_object_method (GObject *object,
DBusGValueMarshalCtx context;
GError *error = NULL;
+ context.recursion_depth = 0;
context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (connection);
context.proxy = NULL;
diff --git a/dbus/dbus-gproxy.c b/dbus/dbus-gproxy.c
index 5d21b0e..36d55f8 100644
--- a/dbus/dbus-gproxy.c
+++ b/dbus/dbus-gproxy.c
@@ -1647,6 +1647,7 @@ marshal_dbus_message_to_g_marshaller (GClosure *closure,
{
DBusGValueMarshalCtx context;
+ context.recursion_depth = 0;
context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection);
context.proxy = proxy;
@@ -2272,6 +2273,7 @@ dbus_g_proxy_end_call_internal (DBusGProxy *proxy,
GValue gvalue = { 0, };
DBusGValueMarshalCtx context;
+ context.recursion_depth = 0;
context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection);
context.proxy = proxy;
diff --git a/dbus/dbus-gvalue.c b/dbus/dbus-gvalue.c
index 5f7c9cc..fa8382c 100644
--- a/dbus/dbus-gvalue.c
+++ b/dbus/dbus-gvalue.c
@@ -34,6 +34,9 @@
#include <glib/gi18n.h>
#include "dbus/dbus-signature.h"
+/* Seems reasonable, but this should probably be part of the standard protocol */
+#define DBUS_GLIB_MAX_VARIANT_RECURSION 32
+
static gboolean demarshal_static_variant (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
@@ -1131,6 +1134,16 @@ _dbus_gvalue_demarshal (DBusGValueMarshalCtx *context,
{
GType gtype;
DBusGValueDemarshalFunc demarshaller;
+ gboolean retcode = FALSE;
+
+ if (context->recursion_depth > DBUS_GLIB_MAX_VARIANT_RECURSION)
+ {
+ g_set_error (error, DBUS_GERROR,
+ DBUS_GERROR_NO_MEMORY,
+ "Variant recursion limit exceeded");
+ return FALSE;
+ }
+ context->recursion_depth++;
gtype = G_VALUE_TYPE (value);
@@ -1143,10 +1156,14 @@ _dbus_gvalue_demarshal (DBusGValueMarshalCtx *context,
DBUS_GERROR_INVALID_ARGS,
_("No demarshaller registered for type \"%s\""),
g_type_name (gtype));
- return FALSE;
+
+ goto out;
}
- return demarshaller (context, iter, value, error);
+ retcode = demarshaller (context, iter, value, error);
+ out:
+ context->recursion_depth--;
+ return retcode;
}
gboolean
diff --git a/dbus/dbus-gvalue.h b/dbus/dbus-gvalue.h
index 1bfd719..35e05be 100644
--- a/dbus/dbus-gvalue.h
+++ b/dbus/dbus-gvalue.h
@@ -12,6 +12,7 @@ G_BEGIN_DECLS
typedef struct {
DBusGConnection *gconnection;
DBusGProxy *proxy;
+ guint recursion_depth;
} DBusGValueMarshalCtx;
void _dbus_g_value_types_init (void);
diff --git a/test/core/Makefile.am b/test/core/Makefile.am
index 4887c14..aeb0e89 100644
--- a/test/core/Makefile.am
+++ b/test/core/Makefile.am
@@ -39,7 +39,7 @@ endif
## we use noinst_PROGRAMS not check_PROGRAMS for TESTS so that we
## build even when not doing "make check"
-noinst_PROGRAMS= test-dbus-glib test-service-glib $(THREAD_APPS) peer-server peer-client test-types
+noinst_PROGRAMS= test-dbus-glib test-service-glib $(THREAD_APPS) peer-server peer-client test-types test-variant-recursion
test_dbus_glib_SOURCES= \
my-object-marshal.c \
@@ -47,6 +47,10 @@ test_dbus_glib_SOURCES= \
test_dbus_glib_LDADD= $(DBUS_GLIB_TOOL_LIBS) $(top_builddir)/dbus/libdbus-glib-1.la $(top_builddir)/dbus/libdbus-gtool.la
+test_variant_recursion_SOURCES=test-variant-recursion.c
+
+test_variant_recursion_LDADD= $(DBUS_GLIB_TOOL_LIBS) $(top_builddir)/dbus/libdbus-glib-1.la $(top_builddir)/dbus/libdbus-gtool.la
+
BUILT_SOURCES = test-service-glib-glue.h test-service-glib-bindings.h my-object-marshal.c my-object-marshal.h
test_service_glib_SOURCES= \
diff --git a/test/core/run-test.sh b/test/core/run-test.sh
index 78cf5fa..04869c5 100755
--- a/test/core/run-test.sh
+++ b/test/core/run-test.sh
@@ -38,4 +38,5 @@ else
dbus-monitor --session &
fi
${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/core/test-dbus-glib || die "test-dbus-glib failed"
+ ${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/core/test-variant-recursion || die "test-variant-recursion failed"
fi
diff --git a/test/core/test-variant-recursion.c b/test/core/test-variant-recursion.c
new file mode 100644
index 0000000..30efc4a
--- /dev/null
+++ b/test/core/test-variant-recursion.c
@@ -0,0 +1,89 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+#include <dbus/dbus-glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <glib-object.h>
+
+static gboolean
+make_recursive_stringify_call (int recursion_depth,
+ DBusGProxy *proxy,
+ GError **error)
+{
+ char *out_str;
+
+ int i;
+ GValue *vals = g_new0 (GValue, recursion_depth+1);
+
+ for (i = recursion_depth-1; i >= 0; i--)
+ {
+ GValue *curval = &(vals[i]);
+ g_value_init (curval, G_TYPE_VALUE);
+ }
+ for (i = 0; i < recursion_depth; i++)
+ {
+ GValue *curval = &(vals[i]);
+ GValue *nextval = &(vals[i+1]);
+ g_value_take_boxed (curval, nextval);
+ }
+ g_value_init (&(vals[recursion_depth]), G_TYPE_STRING);
+ g_value_set_string (&(vals[recursion_depth]), "end of the line");
+ return dbus_g_proxy_call (proxy, "Stringify", error,
+ G_TYPE_VALUE, &(vals[0]),
+ G_TYPE_INVALID,
+ G_TYPE_STRING, &out_str,
+ G_TYPE_INVALID);
+}
+
+int
+main (int argc, char **argv)
+{
+ DBusGConnection *connection;
+ GError *error = NULL;
+ DBusGProxy *proxy;
+ GMainLoop *loop;
+
+ g_type_init ();
+
+ g_log_set_always_fatal (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL);
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if (connection == NULL)
+ g_error ("Failed to open connection to bus: %s", error->message);
+
+ proxy = dbus_g_proxy_new_for_name (connection,
+ "org.freedesktop.DBus.GLib.TestService",
+ "/org/freedesktop/DBus/GLib/Tests/MyTestObject",
+ "org.freedesktop.DBus.GLib.Tests.MyObject");
+
+ if (proxy == NULL)
+ g_error ("Failed to create proxy for name owner: %s", error->message);
+
+ /* Do an echo to be sure it started */
+ if (!dbus_g_proxy_call (proxy, "DoNothing", &error,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID))
+ g_error ("Failed to complete DoNothing call: %s", error->message);
+
+ /* Fewer than the current internal limit (16) */
+ if (make_recursive_stringify_call (10, proxy, &error))
+ g_error ("Unexpected success code from 10 recursive variant call: %s", error->message);
+ if (error->code != DBUS_GERROR_REMOTE_EXCEPTION)
+ g_error ("Error code was not remote exception: %s", error->message);
+ g_printerr ("Got expected error %d: \"%s\" from recursive variant call\n", error->code, error->message);
+ g_clear_error (&error);
+ /* More than the current internal limit (16) */
+ if (make_recursive_stringify_call (50, proxy, &error))
+ g_error ("Unexpected success code from 50 recursive variant call: %s", error->message);
+ if (error->code != DBUS_GERROR_REMOTE_EXCEPTION)
+ g_error ("Error code was not remote exception: %s", error->message);
+ g_printerr ("Got expected error %d: \"%s\" from recursive variant call\n", error->code, error->message);
+ g_clear_error (&error);
+
+ g_object_unref (G_OBJECT (proxy));
+
+ return 0;
+}