From 6499ad53567a64cb70f2fdc690ad405350fe1ce3 Mon Sep 17 00:00:00 2001
From: Sebastian Wilhelmi <wilhelmi@google.com>
Date: Thu, 6 Jan 2022 21:04:56 +0000
Subject: [PATCH] gdbusmessage: Disallow empty structures/tuples in D-Bus
 messages

They are disallowed in the specification:
https://dbus.freedesktop.org/doc/dbus-specification.html#container-types

Helps: #2557

Conflict:NA
Reference:https://gitlab.gnome.org/GNOME/glib/-/commit/6499ad53567a64cb70f2fdc690ad405350fe1ce3

---
 gio/gdbusmessage.c              | 19 +++++++
 gio/tests/gdbus-serialization.c | 88 +++++++++++++++++++++++++++++++++
 2 files changed, 107 insertions(+)

diff --git a/gio/gdbusmessage.c b/gio/gdbusmessage.c
index 6e3bd8b..0645b90 100644
--- a/gio/gdbusmessage.c
+++ b/gio/gdbusmessage.c
@@ -1833,6 +1833,16 @@ parse_value_from_blob (GMemoryBuffer       *buf,
 
               g_variant_builder_init (&builder, type);
               element_type = g_variant_type_first (type);
+              if (!element_type)
+                {
+                  g_variant_builder_clear (&builder);
+                  g_set_error_literal (&local_error,
+                                       G_IO_ERROR,
+                                       G_IO_ERROR_INVALID_ARGUMENT,
+                                       _("Empty structures (tuples) are not allowed in D-Bus"));
+                  goto fail;
+                }
+
               while (element_type != NULL)
                 {
                   GVariant *item;
@@ -2538,6 +2548,15 @@ append_value_to_blob (GVariant            *value,
     default:
       if (g_variant_type_is_dict_entry (type) || g_variant_type_is_tuple (type))
         {
+          if (!g_variant_type_first (type))
+            {
+              g_set_error_literal (error,
+                                   G_IO_ERROR,
+                                   G_IO_ERROR_INVALID_ARGUMENT,
+                                   _("Empty structures (tuples) are not allowed in D-Bus"));
+              goto fail;
+            }
+
           padding_added = ensure_output_padding (mbuf, 8);
           if (value != NULL)
             {
diff --git a/gio/tests/gdbus-serialization.c b/gio/tests/gdbus-serialization.c
index 2ca28d9..34df053 100644
--- a/gio/tests/gdbus-serialization.c
+++ b/gio/tests/gdbus-serialization.c
@@ -1411,6 +1411,90 @@ test_message_parse_deep_body_nesting (void)
   g_clear_error (&local_error);
 }
 
+static void
+test_message_parse_empty_structure (void)
+{
+  const guint8 data[] =
+    {
+      'l',  /* little-endian byte order */
+      0x02,  /* message type (method return) */
+      0x00,  /* message flags (none) */
+      0x01,  /* major protocol version */
+      0x08, 0x00, 0x00, 0x00,  /* body length (in bytes) */
+      0x00, 0x00, 0x00, 0x00,  /* message serial */
+      /* a{yv} of header fields */
+      0x20, 0x00, 0x00, 0x00,  /* array length (in bytes), must be a multiple of 8 */
+        0x01,  /* array key (PATH) */
+        0x01,  /* signature length */
+        'o',  /* type (OBJECT_PATH) */
+        0x00,  /* nul terminator */
+        0x05, 0x00, 0x00, 0x00, /* length 5 */
+        '/', 'p', 'a', 't', 'h', 0x00, 0x00, 0x00, /* string '/path' and padding */
+        0x03,  /* array key (MEMBER) */
+        0x01,  /* signature length */
+        's',  /* type (STRING) */
+        0x00,  /* nul terminator */
+        0x06, 0x00, 0x00, 0x00, /* length 6 */
+        'M', 'e', 'm', 'b', 'e', 'r', 0x00, 0x00, /* string 'Member' and padding */
+        0x08,  /* array key (SIGNATURE) */
+        0x01,  /* signature length */
+        'g',  /* type (SIGNATURE) */
+        0x00,  /* nul terminator */
+        0x03, /* length 3 */
+        'a', '(', ')', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* type 'a()' and padding */
+        0x08, 0x00, 0x00, 0x00, /* array length: 4 bytes */
+        0x00, 0x00, 0x00, 0x00, /* padding to 8 bytes */
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* array data */
+        0x00
+    };
+  gsize size = sizeof (data);
+  GDBusMessage *message = NULL;
+  GError *local_error = NULL;
+
+  g_test_summary ("Test that empty structures are rejected when parsing.");
+  g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2557");
+
+  message = g_dbus_message_new_from_blob ((guchar *) data, size,
+                                          G_DBUS_CAPABILITY_FLAGS_NONE,
+                                          &local_error);
+  g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
+  g_assert_cmpstr (local_error->message, ==, "Empty structures (tuples) are not allowed in D-Bus");
+  g_assert_null (message);
+
+  g_clear_error (&local_error);
+}
+
+static void
+test_message_serialize_empty_structure (void)
+{
+  GDBusMessage *message;
+  GVariantBuilder builder;
+  gsize size = 0;
+  GError *local_error = NULL;
+
+  g_test_summary ("Test that empty structures are rejected when serializing.");
+  g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2557");
+
+  message = g_dbus_message_new ();
+  g_variant_builder_init (&builder, G_VARIANT_TYPE ("(a())"));
+  g_variant_builder_open (&builder, G_VARIANT_TYPE ("a()"));
+  g_variant_builder_add (&builder, "()");
+  g_variant_builder_close (&builder);
+  g_dbus_message_set_message_type (message, G_DBUS_MESSAGE_TYPE_METHOD_CALL);
+  g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH,
+                             g_variant_new_object_path ("/path"));
+  g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER,
+                             g_variant_new_string ("Member"));
+  g_dbus_message_set_body (message, g_variant_builder_end (&builder));
+
+  g_dbus_message_to_blob (message, &size, G_DBUS_CAPABILITY_FLAGS_NONE, &local_error);
+  g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
+  g_assert_cmpstr (local_error->message, ==, "Empty structures (tuples) are not allowed in D-Bus");
+
+  g_clear_error (&local_error);
+  g_clear_object (&message);
+}
+
 /* ---------------------------------------------------------------------------------------------------- */
 
 int
@@ -1433,6 +1517,8 @@ main (int   argc,
                    test_message_serialize_header_checks);
   g_test_add_func ("/gdbus/message-serialize/double-array",
                    test_message_serialize_double_array);
+  g_test_add_func ("/gdbus/message-serialize/empty-structure",
+                   test_message_serialize_empty_structure);
 
   g_test_add_func ("/gdbus/message-parse/empty-arrays-of-arrays",
                    test_message_parse_empty_arrays_of_arrays);
@@ -1448,6 +1534,8 @@ main (int   argc,
                    test_message_parse_deep_header_nesting);
   g_test_add_func ("/gdbus/message-parse/deep-body-nesting",
                    test_message_parse_deep_body_nesting);
+  g_test_add_func ("/gdbus/message-parse/empty-structure",
+                   test_message_parse_empty_structure);
 
   return g_test_run();
 }
-- 
GitLab

