1 /* GLib testing framework examples and tests
3 * Copyright (C) 2008-2010 Red Hat, Inc.
5 * SPDX-License-Identifier: LGPL-2.1-or-later
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 * Author: David Zeuthen <davidz@redhat.com>
30 #include <dbus/dbus.h>
32 /* ---------------------------------------------------------------------------------------------------- */
35 hexdump (const guchar *str, gsize len)
37 const guchar *data = (const guchar *) str;
40 for (n = 0; n < len; n += 16)
42 g_printerr ("%04x: ", n);
44 for (m = n; m < n + 16; m++)
46 if (m > n && (m%4) == 0)
49 g_printerr ("%02x ", data[m]);
56 for (m = n; m < len && m < n + 16; m++)
57 g_printerr ("%c", g_ascii_isprint (data[m]) ? data[m] : '.');
63 /* ---------------------------------------------------------------------------------------------------- */
66 append_gv_to_dbus_iter (DBusMessageIter *iter,
70 const GVariantType *type;
72 type = g_variant_get_type (value);
73 if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
75 dbus_bool_t v = g_variant_get_boolean (value);
76 dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &v);
78 else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
80 guint8 v = g_variant_get_byte (value);
81 dbus_message_iter_append_basic (iter, DBUS_TYPE_BYTE, &v);
83 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
85 gint16 v = g_variant_get_int16 (value);
86 dbus_message_iter_append_basic (iter, DBUS_TYPE_INT16, &v);
88 else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
90 guint16 v = g_variant_get_uint16 (value);
91 dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT16, &v);
93 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
95 gint32 v = g_variant_get_int32 (value);
96 dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &v);
98 else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
100 guint32 v = g_variant_get_uint32 (value);
101 dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &v);
103 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
105 gint64 v = g_variant_get_int64 (value);
106 dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &v);
108 else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
110 guint64 v = g_variant_get_uint64 (value);
111 dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &v);
113 else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
115 gdouble v = g_variant_get_double (value);
116 dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &v);
118 else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
120 const gchar *v = g_variant_get_string (value, NULL);
121 dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &v);
123 else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
125 const gchar *v = g_variant_get_string (value, NULL);
126 dbus_message_iter_append_basic (iter, DBUS_TYPE_OBJECT_PATH, &v);
128 else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
130 const gchar *v = g_variant_get_string (value, NULL);
131 dbus_message_iter_append_basic (iter, DBUS_TYPE_SIGNATURE, &v);
133 else if (g_variant_type_is_variant (type))
138 child = g_variant_get_child_value (value, 0);
139 dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT,
140 g_variant_get_type_string (child),
142 if (!append_gv_to_dbus_iter (&sub, child, error))
144 g_variant_unref (child);
147 dbus_message_iter_close_container (iter, &sub);
148 g_variant_unref (child);
150 else if (g_variant_type_is_array (type))
152 DBusMessageIter dbus_iter;
153 const gchar *type_string;
154 GVariantIter gv_iter;
157 type_string = g_variant_get_type_string (value);
158 type_string++; /* skip the 'a' */
160 dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY,
161 type_string, &dbus_iter);
162 g_variant_iter_init (&gv_iter, value);
164 while ((item = g_variant_iter_next_value (&gv_iter)))
166 if (!append_gv_to_dbus_iter (&dbus_iter, item, error))
172 dbus_message_iter_close_container (iter, &dbus_iter);
174 else if (g_variant_type_is_tuple (type))
176 DBusMessageIter dbus_iter;
177 GVariantIter gv_iter;
180 dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT,
182 g_variant_iter_init (&gv_iter, value);
184 while ((item = g_variant_iter_next_value (&gv_iter)))
186 if (!append_gv_to_dbus_iter (&dbus_iter, item, error))
190 dbus_message_iter_close_container (iter, &dbus_iter);
192 else if (g_variant_type_is_dict_entry (type))
194 DBusMessageIter dbus_iter;
197 dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY,
199 key = g_variant_get_child_value (value, 0);
200 if (!append_gv_to_dbus_iter (&dbus_iter, key, error))
202 g_variant_unref (key);
205 g_variant_unref (key);
207 val = g_variant_get_child_value (value, 1);
208 if (!append_gv_to_dbus_iter (&dbus_iter, val, error))
210 g_variant_unref (val);
213 g_variant_unref (val);
215 dbus_message_iter_close_container (iter, &dbus_iter);
221 G_IO_ERROR_INVALID_ARGUMENT,
222 "Error serializing GVariant with type-string '%s' to a D-Bus message",
223 g_variant_get_type_string (value));
234 append_gv_to_dbus_message (DBusMessage *message,
245 DBusMessageIter iter;
246 GVariantIter gv_iter;
249 dbus_message_iter_init_append (message, &iter);
251 g_variant_iter_init (&gv_iter, value);
253 while ((item = g_variant_iter_next_value (&gv_iter)))
255 if (!append_gv_to_dbus_iter (&iter, item, error))
257 g_prefix_error (error,
258 "Error encoding in-arg %d: ",
273 print_gv_dbus_message (GVariant *value)
275 DBusMessage *message;
280 message = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
281 dbus_message_set_serial (message, 0x41);
282 dbus_message_set_path (message, "/foo/bar");
283 dbus_message_set_member (message, "Member");
286 if (!append_gv_to_dbus_message (message, value, &error))
288 g_printerr ("Error printing GVariant as DBusMessage: %s", error->message);
289 g_error_free (error);
293 dbus_message_marshal (message, &blob, &blob_len);
295 hexdump ((guchar *) blob, blob_len);
297 dbus_message_unref (message);
300 /* ---------------------------------------------------------------------------------------------------- */
303 dbus_1_message_append (GString *s,
305 DBusMessageIter *iter)
310 g_string_append_printf (s, "%*s", indent, "");
312 arg_type = dbus_message_iter_get_arg_type (iter);
315 case DBUS_TYPE_BOOLEAN:
318 dbus_message_iter_get_basic (iter, &value);
319 g_string_append_printf (s, "bool: %s\n", value ? "true" : "false");
326 dbus_message_iter_get_basic (iter, &value);
327 g_string_append_printf (s, "byte: 0x%02x\n", (guint) value);
331 case DBUS_TYPE_INT16:
334 dbus_message_iter_get_basic (iter, &value);
335 g_string_append_printf (s, "int16: %" G_GINT16_FORMAT "\n", value);
339 case DBUS_TYPE_UINT16:
342 dbus_message_iter_get_basic (iter, &value);
343 g_string_append_printf (s, "uint16: %" G_GUINT16_FORMAT "\n", value);
347 case DBUS_TYPE_INT32:
350 dbus_message_iter_get_basic (iter, &value);
351 g_string_append_printf (s, "int32: %" G_GINT32_FORMAT "\n", value);
355 case DBUS_TYPE_UINT32:
358 dbus_message_iter_get_basic (iter, &value);
359 g_string_append_printf (s, "uint32: %" G_GUINT32_FORMAT "\n", value);
363 case DBUS_TYPE_INT64:
366 dbus_message_iter_get_basic (iter, &value);
367 g_string_append_printf (s, "int64: %" G_GINT64_FORMAT "\n", value);
371 case DBUS_TYPE_UINT64:
374 dbus_message_iter_get_basic (iter, &value);
375 g_string_append_printf (s, "uint64: %" G_GUINT64_FORMAT "\n", value);
379 case DBUS_TYPE_DOUBLE:
382 dbus_message_iter_get_basic (iter, &value);
383 g_string_append_printf (s, "double: %f\n", value);
387 case DBUS_TYPE_STRING:
390 dbus_message_iter_get_basic (iter, &value);
391 g_string_append_printf (s, "string: '%s'\n", value);
395 case DBUS_TYPE_OBJECT_PATH:
398 dbus_message_iter_get_basic (iter, &value);
399 g_string_append_printf (s, "object_path: '%s'\n", value);
403 case DBUS_TYPE_SIGNATURE:
406 dbus_message_iter_get_basic (iter, &value);
407 g_string_append_printf (s, "signature: '%s'\n", value);
411 #ifdef DBUS_TYPE_UNIX_FD
412 case DBUS_TYPE_UNIX_FD:
414 /* unfortunately there's currently no way to get just the
415 * protocol value, since dbus_message_iter_get_basic() wants
416 * to be 'helpful' and dup the fd for the user...
418 g_string_append (s, "unix-fd: (not extracted)\n");
423 case DBUS_TYPE_VARIANT:
424 g_string_append_printf (s, "variant:\n");
425 dbus_message_iter_recurse (iter, &sub);
426 while (dbus_message_iter_get_arg_type (&sub))
428 dbus_1_message_append (s, indent + 2, &sub);
429 dbus_message_iter_next (&sub);
433 case DBUS_TYPE_ARRAY:
434 g_string_append_printf (s, "array:\n");
435 dbus_message_iter_recurse (iter, &sub);
436 while (dbus_message_iter_get_arg_type (&sub))
438 dbus_1_message_append (s, indent + 2, &sub);
439 dbus_message_iter_next (&sub);
443 case DBUS_TYPE_STRUCT:
444 g_string_append_printf (s, "struct:\n");
445 dbus_message_iter_recurse (iter, &sub);
446 while (dbus_message_iter_get_arg_type (&sub))
448 dbus_1_message_append (s, indent + 2, &sub);
449 dbus_message_iter_next (&sub);
453 case DBUS_TYPE_DICT_ENTRY:
454 g_string_append_printf (s, "dict_entry:\n");
455 dbus_message_iter_recurse (iter, &sub);
456 while (dbus_message_iter_get_arg_type (&sub))
458 dbus_1_message_append (s, indent + 2, &sub);
459 dbus_message_iter_next (&sub);
464 g_printerr ("Error serializing D-Bus message to GVariant. Unsupported arg type '%c' (%d)",
467 g_assert_not_reached ();
473 dbus_1_message_print (DBusMessage *message)
477 DBusMessageIter iter;
479 s = g_string_new (NULL);
481 dbus_message_iter_init (message, &iter);
482 while (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID)
484 g_string_append_printf (s, "value %d: ", n);
485 dbus_1_message_append (s, 2, &iter);
486 dbus_message_iter_next (&iter);
490 return g_string_free (s, FALSE);
493 /* ---------------------------------------------------------------------------------------------------- */
496 get_body_signature (GVariant *value)
508 s = g_variant_get_type_string (value);
512 ret = g_strndup (s + 1, len - 2);
518 /* If @value is floating, this assumes ownership. */
520 get_and_check_serialization (GVariant *value)
524 DBusMessage *dbus_1_message;
525 GDBusMessage *message;
526 GDBusMessage *recovered_message;
528 DBusError dbus_error;
529 gchar *last_serialization = NULL;
533 message = g_dbus_message_new ();
534 g_dbus_message_set_body (message, value);
535 g_dbus_message_set_message_type (message, G_DBUS_MESSAGE_TYPE_METHOD_CALL);
536 g_dbus_message_set_serial (message, 0x41);
537 s = get_body_signature (value);
538 g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, g_variant_new_object_path ("/foo/bar"));
539 g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, g_variant_new_string ("Member"));
540 g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, g_variant_new_signature (s));
543 /* First check that the serialization to the D-Bus wire format is correct - do this for both byte orders */
544 for (n = 0; n < 2; n++)
546 GDBusMessageByteOrder byte_order;
550 byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
553 byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
556 g_assert_not_reached ();
559 g_dbus_message_set_byte_order (message, byte_order);
562 blob = g_dbus_message_to_blob (message,
564 G_DBUS_CAPABILITY_FLAGS_NONE,
566 g_assert_no_error (error);
567 g_assert (blob != NULL);
571 case G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN:
572 g_assert_cmpint (blob[0], ==, 'B');
574 case G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN:
575 g_assert_cmpint (blob[0], ==, 'l');
579 dbus_error_init (&dbus_error);
580 dbus_1_message = dbus_message_demarshal ((char *) blob, blob_size, &dbus_error);
581 if (dbus_error_is_set (&dbus_error))
583 g_printerr ("Error calling dbus_message_demarshal() on this blob: %s: %s\n",
586 hexdump (blob, blob_size);
587 dbus_error_free (&dbus_error);
589 s = g_variant_print (value, TRUE);
590 g_printerr ("\nThe blob was generated from the following GVariant value:\n%s\n\n", s);
593 g_printerr ("If the blob was encoded using DBusMessageIter, the payload would have been:\n");
594 print_gv_dbus_message (value);
596 g_assert_not_reached ();
599 s = dbus_1_message_print (dbus_1_message);
600 dbus_message_unref (dbus_1_message);
602 /* Then serialize back and check that the body is identical */
605 recovered_message = g_dbus_message_new_from_blob (blob,
607 G_DBUS_CAPABILITY_FLAGS_NONE,
609 g_assert_no_error (error);
610 g_assert (recovered_message != NULL);
614 g_assert (g_dbus_message_get_body (recovered_message) == NULL);
618 g_assert (g_dbus_message_get_body (recovered_message) != NULL);
619 g_assert_cmpvariant (g_dbus_message_get_body (recovered_message), value);
621 g_object_unref (recovered_message);
624 if (last_serialization != NULL)
626 g_assert_cmpstr (last_serialization, ==, s);
627 g_free (last_serialization);
630 last_serialization = g_steal_pointer (&s);
633 g_object_unref (message);
635 return g_steal_pointer (&last_serialization);
638 /* If @value is floating, this assumes ownership. */
640 check_serialization (GVariant *value,
641 const gchar *expected_dbus_1_output)
643 gchar *s = get_and_check_serialization (value);
644 g_assert_cmpstr (s, ==, expected_dbus_1_output);
649 test_message_serialize_basic (void)
651 check_serialization (NULL, "");
653 check_serialization (g_variant_new ("(sogybnqiuxtd)",
663 -(G_GUINT64_CONSTANT(2)<<34),
664 G_GUINT64_CONSTANT(0xffffffffffffffff),
666 "value 0: string: 'this is a string'\n"
667 "value 1: object_path: '/this/is/a/path'\n"
668 "value 2: signature: 'sad'\n"
669 "value 3: byte: 0x2a\n"
670 "value 4: bool: true\n"
671 "value 5: int16: -42\n"
672 "value 6: uint16: 60000\n"
673 "value 7: int32: -44\n"
674 "value 8: uint32: 100000\n"
675 "value 9: int64: -34359738368\n"
676 "value 10: uint64: 18446744073709551615\n"
677 "value 11: double: 42.500000\n");
680 /* ---------------------------------------------------------------------------------------------------- */
683 test_message_serialize_complex (void)
688 gchar *serialization = NULL;
692 value = g_variant_parse (G_VARIANT_TYPE ("(aia{ss})"),
693 "([1, 2, 3], {'one': 'white', 'two': 'black'})",
695 g_assert_no_error (error);
696 g_assert (value != NULL);
697 check_serialization (value,
708 " string: 'black'\n");
709 g_variant_unref (value);
711 value = g_variant_parse (G_VARIANT_TYPE ("(sa{sv}as)"),
712 "('01234567890123456', {}, ['Something'])",
714 g_assert_no_error (error);
715 g_assert (value != NULL);
716 check_serialization (value,
717 "value 0: string: '01234567890123456'\n"
720 " string: 'Something'\n");
721 g_variant_unref (value);
723 /* https://bugzilla.gnome.org/show_bug.cgi?id=621838 */
724 check_serialization (g_variant_new_parsed ("(@aay [], {'cwd': <'/home/davidz/Hacking/glib/gio/tests'>})"),
730 " string: '/home/davidz/Hacking/glib/gio/tests'\n");
732 #ifdef DBUS_TYPE_UNIX_FD
733 value = g_variant_parse (G_VARIANT_TYPE ("(hah)"),
736 g_assert_no_error (error);
737 g_assert (value != NULL);
738 /* about (not extracted), see comment in DBUS_TYPE_UNIX_FD case in
739 * dbus_1_message_append() above.
741 check_serialization (value,
742 "value 0: unix-fd: (not extracted)\n"
744 " unix-fd: (not extracted)\n"
745 " unix-fd: (not extracted)\n");
746 g_variant_unref (value);
749 /* Deep nesting of variants (just below the recursion limit). */
750 value = g_variant_new_string ("buried");
751 for (i = 0; i < 64; i++)
752 value = g_variant_new_variant (value);
753 value = g_variant_new_tuple (&value, 1);
755 serialization = get_and_check_serialization (value);
756 g_assert_nonnull (serialization);
757 g_assert_true (g_str_has_prefix (serialization,
758 "value 0: variant:\n"
761 g_free (serialization);
763 /* Deep nesting of arrays and structs (just below the recursion limit).
764 * See https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-signature */
765 value = g_variant_new_string ("hello");
766 for (i = 0; i < 32; i++)
767 value = g_variant_new_tuple (&value, 1);
768 for (i = 0; i < 32; i++)
769 value = g_variant_new_array (NULL, &value, 1);
770 value = g_variant_new_tuple (&value, 1);
772 serialization = get_and_check_serialization (value);
773 g_assert_nonnull (serialization);
774 g_assert_true (g_str_has_prefix (serialization,
778 g_free (serialization);
782 /* ---------------------------------------------------------------------------------------------------- */
791 gsize slen = strlen (before) + 1;
793 g_assert_cmpuint (strlen (before), ==, strlen (after));
794 g_assert_cmpuint (len, >=, slen);
796 for (i = 0; i < (len - slen + 1); i++)
798 if (memcmp (blob + i, before, slen) == 0)
799 memcpy (blob + i, after, slen);
804 test_message_serialize_invalid (void)
808 /* Other things we could check (note that GDBus _does_ check for all
809 * these things - we just don't have test-suit coverage for it)
811 * - array exceeding 64 MiB (2^26 bytes) - unfortunately libdbus-1 checks
814 * process 19620: arguments to dbus_message_iter_append_fixed_array() were incorrect,
815 * assertion "n_elements <= DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type)"
816 * failed in file dbus-message.c line 2344.
817 * This is normally a bug in some application using the D-Bus library.
818 * D-Bus not built with -rdynamic so unable to print a backtrace
819 * Aborted (core dumped)
821 * - message exceeding 128 MiB (2^27 bytes)
823 * - endianness, message type, flags, protocol version
826 for (n = 0; n < 3; n++)
828 GDBusMessage *message;
830 DBusMessage *dbus_message;
833 /* these are in pairs with matching length */
834 const gchar *valid_utf8_str = "this is valid...";
835 const gchar *invalid_utf8_str = "this is invalid\xff";
836 const gchar *valid_signature = "a{sv}a{sv}a{sv}aiai";
837 const gchar *invalid_signature = "not valid signature";
838 const gchar *valid_object_path = "/this/is/a/valid/dbus/object/path";
839 const gchar *invalid_object_path = "/this/is/not a valid object path!";
841 dbus_message = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
842 dbus_message_set_serial (dbus_message, 0x41);
843 dbus_message_set_path (dbus_message, "/foo/bar");
844 dbus_message_set_member (dbus_message, "Member");
849 dbus_message_append_args (dbus_message,
850 DBUS_TYPE_STRING, &valid_utf8_str,
855 /* invalid object path */
856 dbus_message_append_args (dbus_message,
857 DBUS_TYPE_OBJECT_PATH, &valid_object_path,
862 /* invalid signature */
863 dbus_message_append_args (dbus_message,
864 DBUS_TYPE_SIGNATURE, &valid_signature,
869 g_assert_not_reached ();
872 dbus_message_marshal (dbus_message, &blob, &blob_len);
873 /* hack up the message to be invalid by replacing each valid string
874 * with its invalid counterpart */
875 replace (blob, blob_len, valid_utf8_str, invalid_utf8_str);
876 replace (blob, blob_len, valid_object_path, invalid_object_path);
877 replace (blob, blob_len, valid_signature, invalid_signature);
880 message = g_dbus_message_new_from_blob ((guchar *) blob,
882 G_DBUS_CAPABILITY_FLAGS_NONE,
884 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
885 g_error_free (error);
886 g_assert (message == NULL);
889 dbus_message_unref (dbus_message);
894 /* ---------------------------------------------------------------------------------------------------- */
897 test_message_serialize_header_checks (void)
899 GDBusMessage *message;
901 GError *error = NULL;
906 * check we can't serialize messages with INVALID type
908 message = g_dbus_message_new ();
909 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
910 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
911 g_assert_cmpstr (error->message, ==, "Cannot serialize message: type is INVALID");
912 g_clear_error (&error);
913 g_assert_null (blob);
914 g_object_unref (message);
917 * check we can't serialize messages with an INVALID header
919 message = g_dbus_message_new_signal ("/the/path", "The.Interface", "TheMember");
920 g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INVALID, g_variant_new_boolean (FALSE));
921 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
923 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
924 g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: INVALID header field supplied");
925 g_assert_null (blob);
927 g_clear_error (&error);
928 g_clear_object (&message);
931 * check that we can't serialize messages with various fields set to incorrectly typed values
935 GDBusMessageHeaderField field;
936 const char *invalid_value; /* as a GVariant in text form */
937 const char *expected_error_message;
942 G_DBUS_MESSAGE_HEADER_FIELD_PATH,
943 "'/correct/value/but/wrong/type'",
944 "Cannot serialize message: SIGNAL message: PATH header field is invalid; expected a value of type ‘o’"
947 G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE,
949 "Cannot serialize message: SIGNAL message: INTERFACE header field is invalid; expected a value of type ‘s’"
952 G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE,
953 "'valid type, but not an interface name'",
954 "Cannot serialize message: SIGNAL message: INTERFACE header field does not contain a valid interface name"
957 G_DBUS_MESSAGE_HEADER_FIELD_MEMBER,
959 "Cannot serialize message: SIGNAL message: MEMBER header field is invalid; expected a value of type ‘s’"
962 G_DBUS_MESSAGE_HEADER_FIELD_MEMBER,
963 "'valid type, but not a member name'",
964 "Cannot serialize message: SIGNAL message: MEMBER header field does not contain a valid member name"
967 G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME,
969 "Cannot serialize message: SIGNAL message: ERROR_NAME header field is invalid; expected a value of type ‘s’"
972 G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME,
973 "'valid type, but not an error name'",
974 "Cannot serialize message: SIGNAL message: ERROR_NAME header field does not contain a valid error name"
977 G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL,
979 "Cannot serialize message: SIGNAL message: REPLY_SERIAL header field is invalid; expected a value of type ‘u’"
982 G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION,
984 "Cannot serialize message: SIGNAL message: DESTINATION header field is invalid; expected a value of type ‘s’"
987 G_DBUS_MESSAGE_HEADER_FIELD_SENDER,
989 "Cannot serialize message: SIGNAL message: SENDER header field is invalid; expected a value of type ‘s’"
992 G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE,
994 "Cannot serialize message: SIGNAL message: SIGNATURE header field is invalid; expected a value of type ‘g’"
997 G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS,
999 "Cannot serialize message: SIGNAL message: NUM_UNIX_FDS header field is invalid; expected a value of type ‘u’"
1003 for (size_t i = 0; i < G_N_ELEMENTS (field_type_tests); i++)
1005 message = g_dbus_message_new_signal ("/the/path", "The.Interface", "TheMember");
1006 g_dbus_message_set_header (message, field_type_tests[i].field, g_variant_new_parsed (field_type_tests[i].invalid_value));
1007 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1009 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1010 g_assert_cmpstr (error->message, ==, field_type_tests[i].expected_error_message);
1011 g_assert_null (blob);
1013 g_clear_error (&error);
1014 g_clear_object (&message);
1018 * check we can't serialize signal messages with INTERFACE, PATH or MEMBER unset / set to reserved value
1020 message = g_dbus_message_new_signal ("/the/path", "The.Interface", "TheMember");
1022 /* interface NULL => error */
1023 g_dbus_message_set_interface (message, NULL);
1024 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1025 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1026 g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: INTERFACE header field is missing or invalid");
1027 g_clear_error (&error);
1028 g_assert_null (blob);
1029 /* interface reserved value => error */
1030 g_dbus_message_set_interface (message, "org.freedesktop.DBus.Local");
1031 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1032 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1033 g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: INTERFACE header field is using the reserved value org.freedesktop.DBus.Local");
1034 g_clear_error (&error);
1035 g_assert_null (blob);
1036 /* reset interface */
1037 g_dbus_message_set_interface (message, "The.Interface");
1039 /* path NULL => error */
1040 g_dbus_message_set_path (message, NULL);
1041 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1042 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1043 g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: PATH header field is missing or invalid");
1044 g_clear_error (&error);
1045 g_assert_null (blob);
1046 /* path reserved value => error */
1047 g_dbus_message_set_path (message, "/org/freedesktop/DBus/Local");
1048 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1049 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1050 g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: PATH header field is using the reserved value /org/freedesktop/DBus/Local");
1051 g_clear_error (&error);
1052 g_assert_null (blob);
1054 g_dbus_message_set_path (message, "/the/path");
1056 /* member NULL => error */
1057 g_dbus_message_set_member (message, NULL);
1058 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1059 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1060 g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: MEMBER header field is missing or invalid");
1061 g_clear_error (&error);
1062 g_assert_null (blob);
1064 g_dbus_message_set_member (message, "TheMember");
1067 g_object_unref (message);
1070 * check that we can't serialize method call messages with PATH or MEMBER unset
1072 message = g_dbus_message_new_method_call (NULL, "/the/path", NULL, "TheMember");
1074 /* path NULL => error */
1075 g_dbus_message_set_path (message, NULL);
1076 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1077 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1078 g_assert_cmpstr (error->message, ==, "Cannot serialize message: METHOD_CALL message: PATH header field is missing or invalid");
1079 g_clear_error (&error);
1080 g_assert_null (blob);
1082 g_dbus_message_set_path (message, "/the/path");
1084 /* member NULL => error */
1085 g_dbus_message_set_member (message, NULL);
1086 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1087 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1088 g_assert_cmpstr (error->message, ==, "Cannot serialize message: METHOD_CALL message: MEMBER header field is missing or invalid");
1089 g_clear_error (&error);
1090 g_assert_null (blob);
1092 g_dbus_message_set_member (message, "TheMember");
1095 g_object_unref (message);
1098 * check that we can't serialize method reply messages with REPLY_SERIAL unset
1100 message = g_dbus_message_new_method_call (NULL, "/the/path", NULL, "TheMember");
1101 g_dbus_message_set_serial (message, 42);
1103 reply = g_dbus_message_new_method_reply (message);
1104 g_assert_cmpint (g_dbus_message_get_reply_serial (reply), ==, 42);
1105 g_dbus_message_set_header (reply, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, NULL);
1106 blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1107 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1108 g_assert_cmpstr (error->message, ==, "Cannot serialize message: METHOD_RETURN message: REPLY_SERIAL header field is missing or invalid");
1109 g_clear_error (&error);
1110 g_assert_null (blob);
1111 g_object_unref (reply);
1112 /* method error - first nuke ERROR_NAME, then REPLY_SERIAL */
1113 reply = g_dbus_message_new_method_error (message, "Some.Error.Name", "the message");
1114 g_assert_cmpint (g_dbus_message_get_reply_serial (reply), ==, 42);
1115 /* nuke ERROR_NAME */
1116 g_dbus_message_set_error_name (reply, NULL);
1117 blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1118 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1119 g_assert_cmpstr (error->message, ==, "Cannot serialize message: ERROR message: ERROR_NAME header field is missing or invalid");
1120 g_clear_error (&error);
1121 g_assert_null (blob);
1122 /* reset ERROR_NAME */
1123 g_dbus_message_set_error_name (reply, "Some.Error.Name");
1124 /* nuke REPLY_SERIAL */
1125 g_dbus_message_set_header (reply, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, NULL);
1126 blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1127 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1128 g_assert_cmpstr (error->message, ==, "Cannot serialize message: ERROR message: REPLY_SERIAL header field is missing or invalid");
1129 g_clear_error (&error);
1130 g_assert_null (blob);
1131 g_object_unref (reply);
1132 g_object_unref (message);
1136 test_message_serialize_header_checks_valid (void)
1138 GDBusMessage *message = NULL, *reply = NULL;
1139 GError *local_error = NULL;
1143 g_test_summary ("Test that validation allows well-formed messages of all the different types");
1146 message = g_dbus_message_new_method_call ("Some.Name", "/the/path", "org.some.Interface", "TheMethod");
1147 g_dbus_message_set_serial (message, 666);
1148 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &local_error);
1149 g_assert_no_error (local_error);
1150 g_assert_nonnull (blob);
1154 reply = g_dbus_message_new_method_reply (message);
1155 blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &local_error);
1156 g_assert_no_error (local_error);
1157 g_assert_nonnull (blob);
1159 g_clear_object (&reply);
1162 reply = g_dbus_message_new_method_error (message, "Error.Name", "Some error message");
1163 blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &local_error);
1164 g_assert_no_error (local_error);
1165 g_assert_nonnull (blob);
1168 g_clear_object (&reply);
1169 g_clear_object (&message);
1172 message = g_dbus_message_new_signal ("/the/path", "org.some.Interface", "SignalName");
1173 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &local_error);
1174 g_assert_no_error (local_error);
1175 g_assert_nonnull (blob);
1177 g_clear_object (&message);
1179 /* Also check that an unknown message type is allowed */
1180 message = g_dbus_message_new ();
1181 g_dbus_message_set_message_type (message, 123);
1182 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &local_error);
1183 g_assert_no_error (local_error);
1184 g_assert_nonnull (blob);
1186 g_clear_object (&message);
1188 /* Even one with a well-defined field on it */
1189 message = g_dbus_message_new ();
1190 g_dbus_message_set_message_type (message, 123);
1191 g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS, g_variant_new_uint32 (0));
1192 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &local_error);
1193 g_assert_no_error (local_error);
1194 g_assert_nonnull (blob);
1196 g_clear_object (&message);
1199 /* ---------------------------------------------------------------------------------------------------- */
1202 test_message_parse_empty_arrays_of_arrays (void)
1205 GError *error = NULL;
1207 g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=673612");
1208 /* These three-element array of empty arrays were previously read back as a
1209 * two-element array of empty arrays, due to sometimes erroneously skipping
1210 * four bytes to align for the eight-byte-aligned grandchild types (x and
1213 body = g_variant_parse (G_VARIANT_TYPE ("(aaax)"),
1214 "([@aax [], [], []],)", NULL, NULL, &error);
1215 g_assert_no_error (error);
1216 check_serialization (body,
1221 g_variant_unref (body);
1223 body = g_variant_parse (G_VARIANT_TYPE ("(aaa{uu})"),
1224 "([@aa{uu} [], [], []],)", NULL, NULL, &error);
1225 g_assert_no_error (error);
1226 check_serialization (body,
1231 g_variant_unref (body);
1233 /* Due to the same bug, g_dbus_message_new_from_blob() would fail for this
1234 * message because it would try to read past the end of the string. Hence,
1235 * sending this to an application would make it fall off the bus. */
1236 body = g_variant_parse (G_VARIANT_TYPE ("(a(aa{sv}as))"),
1239 " ([], [])],)", NULL, NULL, &error);
1240 g_assert_no_error (error);
1241 check_serialization (body,
1252 g_variant_unref (body);
1255 /* ---------------------------------------------------------------------------------------------------- */
1258 test_message_serialize_double_array (void)
1260 GVariantBuilder builder;
1263 g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=732754");
1265 g_variant_builder_init (&builder, G_VARIANT_TYPE ("ad"));
1266 g_variant_builder_add (&builder, "d", (gdouble)0.0);
1267 g_variant_builder_add (&builder, "d", (gdouble)8.0);
1268 g_variant_builder_add (&builder, "d", (gdouble)22.0);
1269 g_variant_builder_add (&builder, "d", (gdouble)0.0);
1270 body = g_variant_new ("(@ad)", g_variant_builder_end (&builder));
1271 check_serialization (body,
1273 " double: 0.000000\n"
1274 " double: 8.000000\n"
1275 " double: 22.000000\n"
1276 " double: 0.000000\n");
1279 /* ---------------------------------------------------------------------------------------------------- */
1281 /* Test that an invalid header in a D-Bus message (specifically, with a type
1282 * which doesn’t match what’s expected for the given header) is gracefully
1283 * handled with an error rather than a crash. */
1285 test_message_parse_non_signature_header (void)
1287 const guint8 data[] = {
1288 'l', /* little-endian byte order */
1289 0x02, /* message type (method return) */
1290 0x00, /* message flags (none) */
1291 0x01, /* major protocol version */
1292 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */
1293 0x00, 0x00, 0x00, 0xbc, /* message serial */
1294 /* a{yv} of header fields:
1295 * (things start to be invalid below here) */
1296 0x10, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1297 0x08, /* array key (SIGNATURE) */
1298 /* Variant array value: */
1299 0x04, /* signature length */
1300 'd', 0x00, 0x00, 'F', /* signature (invalid) */
1301 0x00, /* nul terminator */
1302 /* (Variant array value payload missing) */
1303 /* alignment padding before the next header array element, as structs must
1306 0x05, /* array key (REPLY_SERIAL, required for method return messages) */
1307 /* Variant array value: */
1308 0x01, /* signature length */
1309 'u', /* one complete type */
1310 0x00, /* nul terminator */
1311 /* (Variant array value payload) */
1312 0x00, 0x01, 0x02, 0x03,
1313 /* (message body is zero-length) */
1315 gsize size = sizeof (data);
1316 GDBusMessage *message = NULL;
1317 GError *local_error = NULL;
1319 message = g_dbus_message_new_from_blob ((guchar *) data, size,
1320 G_DBUS_CAPABILITY_FLAGS_NONE,
1322 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1323 g_assert_null (message);
1325 g_clear_error (&local_error);
1328 /* ---------------------------------------------------------------------------------------------------- */
1330 /* Test that an invalid header in a D-Bus message (specifically, containing a
1331 * variant with an empty type signature) is gracefully handled with an error
1332 * rather than a crash. */
1334 test_message_parse_empty_signature_header (void)
1336 const guint8 data[] = {
1337 'l', /* little-endian byte order */
1338 0x02, /* message type (method return) */
1339 0x00, /* message flags (none) */
1340 0x01, /* major protocol version */
1341 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */
1342 0x20, 0x20, 0x20, 0x20, /* message serial */
1343 /* a{yv} of header fields:
1344 * (things start to be invalid below here) */
1345 0x10, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1346 0x20, /* array key (this is not currently a valid header field) */
1347 /* Variant array value: */
1348 0x00, /* signature length */
1349 0x00, /* nul terminator */
1350 /* (Variant array value payload missing) */
1351 /* alignment padding before the next header array element, as structs must
1353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1354 0x05, /* array key (REPLY_SERIAL, required for method return messages) */
1355 /* Variant array value: */
1356 0x01, /* signature length */
1357 'u', /* one complete type */
1358 0x00, /* nul terminator */
1359 /* (Variant array value payload) */
1360 0x00, 0x01, 0x02, 0x03,
1361 /* (message body is zero-length) */
1363 gsize size = sizeof (data);
1364 GDBusMessage *message = NULL;
1365 GError *local_error = NULL;
1367 message = g_dbus_message_new_from_blob ((guchar *) data, size,
1368 G_DBUS_CAPABILITY_FLAGS_NONE,
1370 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1371 g_assert_null (message);
1373 g_clear_error (&local_error);
1376 /* ---------------------------------------------------------------------------------------------------- */
1378 /* Test that an invalid header in a D-Bus message (specifically, containing a
1379 * variant with a type signature containing multiple complete types) is
1380 * gracefully handled with an error rather than a crash. */
1382 test_message_parse_multiple_signature_header (void)
1384 const guint8 data[] = {
1385 'l', /* little-endian byte order */
1386 0x02, /* message type (method return) */
1387 0x00, /* message flags (none) */
1388 0x01, /* major protocol version */
1389 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */
1390 0x20, 0x20, 0x20, 0x20, /* message serial */
1391 /* a{yv} of header fields:
1392 * (things start to be invalid below here) */
1393 0x10, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1394 0x20, /* array key (this is not currently a valid header field) */
1395 /* Variant array value: */
1396 0x02, /* signature length */
1397 'b', 'b', /* two complete types */
1398 0x00, /* nul terminator */
1399 /* (Variant array value payload missing) */
1400 /* alignment padding before the next header array element, as structs must
1403 0x05, /* array key (REPLY_SERIAL, required for method return messages) */
1404 /* Variant array value: */
1405 0x01, /* signature length */
1406 'u', /* one complete type */
1407 0x00, /* nul terminator */
1408 /* (Variant array value payload) */
1409 0x00, 0x01, 0x02, 0x03,
1410 /* (message body is zero-length) */
1412 gsize size = sizeof (data);
1413 GDBusMessage *message = NULL;
1414 GError *local_error = NULL;
1416 message = g_dbus_message_new_from_blob ((guchar *) data, size,
1417 G_DBUS_CAPABILITY_FLAGS_NONE,
1419 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1420 g_assert_null (message);
1422 g_clear_error (&local_error);
1425 /* ---------------------------------------------------------------------------------------------------- */
1427 /* Test that an invalid header in a D-Bus message (specifically, containing a
1428 * variant with a valid type signature that is too long to be a valid
1429 * #GVariantType due to exceeding the array nesting limits) is gracefully
1430 * handled with an error rather than a crash. */
1432 test_message_parse_over_long_signature_header (void)
1434 const guint8 data[] = {
1435 'l', /* little-endian byte order */
1436 0x02, /* message type (method return) */
1437 0x00, /* message flags (none) */
1438 0x01, /* major protocol version */
1439 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */
1440 0x20, 0x20, 0x20, 0x20, /* message serial */
1441 /* a{yv} of header fields:
1442 * (things start to be invalid below here) */
1443 0xa0, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1444 0x08, /* array key (SIGNATURE) */
1445 /* Variant array value: */
1446 0x04, /* signature length */
1447 'g', 0x00, 0x20, 0x20, /* one complete type plus some rubbish */
1448 0x00, /* nul terminator */
1449 /* (Variant array value payload) */
1450 /* Critically, this contains 128 nested ‘a’s, which exceeds
1451 * %G_VARIANT_MAX_RECURSION_DEPTH. */
1453 'a', 'b', 'g', 'd', 'u', 'd', 'd', 'd', 'd', 'd', 'd', 'd',
1455 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1456 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1457 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1458 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1459 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1460 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1461 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1462 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1463 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1464 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1465 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1467 /* first header length is a multiple of 8 so no padding is needed */
1468 0x05, /* array key (REPLY_SERIAL, required for method return messages) */
1469 /* Variant array value: */
1470 0x01, /* signature length */
1471 'u', /* one complete type */
1472 0x00, /* nul terminator */
1473 /* (Variant array value payload) */
1474 0x00, 0x01, 0x02, 0x03,
1475 /* (message body is zero-length) */
1477 gsize size = sizeof (data);
1478 GDBusMessage *message = NULL;
1479 GError *local_error = NULL;
1481 message = g_dbus_message_new_from_blob ((guchar *) data, size,
1482 G_DBUS_CAPABILITY_FLAGS_NONE,
1484 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1485 g_assert_null (message);
1487 g_clear_error (&local_error);
1490 /* ---------------------------------------------------------------------------------------------------- */
1492 /* Test that an invalid header in a D-Bus message (specifically, containing too
1493 * many levels of nested variant) is gracefully handled with an error rather
1496 test_message_parse_deep_header_nesting (void)
1498 const guint8 data[] = {
1499 'l', /* little-endian byte order */
1500 0x02, /* message type (method return) */
1501 0x00, /* message flags (none) */
1502 0x01, /* major protocol version */
1503 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */
1504 0x20, 0x20, 0x20, 0x20, /* message serial */
1505 /* a{yv} of header fields:
1506 * (things start to be invalid below here) */
1507 0xd0, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1508 0x20, /* array key (this is not currently a valid header field) */
1509 /* Variant array value: */
1510 0x01, /* signature length */
1511 'v', /* one complete type */
1512 0x00, /* nul terminator */
1513 /* (Variant array value payload) */
1514 /* Critically, this contains 64 nested variants (minus two for the
1515 * ‘arbitrary valid content’ below, but ignoring two for the `a{yv}`
1516 * above), which in total exceeds %G_DBUS_MAX_TYPE_DEPTH. */
1517 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1518 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1519 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1520 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1521 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1522 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1523 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1524 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1525 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1526 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1527 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1528 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1529 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1530 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1531 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1532 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1533 /* Some arbitrary valid content inside the innermost variant: */
1534 0x01, 'y', 0x00, 0xcc,
1535 /* no padding needed as this header element length is a multiple of 8 */
1536 0x05, /* array key (REPLY_SERIAL, required for method return messages) */
1537 /* Variant array value: */
1538 0x01, /* signature length */
1539 'u', /* one complete type */
1540 0x00, /* nul terminator */
1541 /* (Variant array value payload) */
1542 0x00, 0x01, 0x02, 0x03,
1543 /* (message body is zero-length) */
1545 gsize size = sizeof (data);
1546 GDBusMessage *message = NULL;
1547 GError *local_error = NULL;
1549 message = g_dbus_message_new_from_blob ((guchar *) data, size,
1550 G_DBUS_CAPABILITY_FLAGS_NONE,
1552 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1553 g_assert_null (message);
1555 g_clear_error (&local_error);
1558 /* ---------------------------------------------------------------------------------------------------- */
1560 /* Test that an invalid body in a D-Bus message (specifically, containing too
1561 * many levels of nested variant) is gracefully handled with an error rather
1562 * than a crash. The set of bytes here are a modified version of the bytes from
1563 * test_message_parse_deep_header_nesting(). */
1565 test_message_parse_deep_body_nesting (void)
1567 const guint8 data[] = {
1568 'l', /* little-endian byte order */
1569 0x02, /* message type (method return) */
1570 0x00, /* message flags (none) */
1571 0x01, /* major protocol version */
1572 0xc4, 0x00, 0x00, 0x00, /* body length (in bytes) */
1573 0x20, 0x20, 0x20, 0x20, /* message serial */
1574 /* a{yv} of header fields: */
1575 0x10, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1576 0x08, /* array key (SIGNATURE) */
1577 /* Variant array value: */
1578 0x01, /* signature length */
1579 'g', /* one complete type */
1580 0x00, /* nul terminator */
1581 /* (Variant array value payload) */
1583 /* alignment padding before the next header array element, as structs must
1586 0x05, /* array key (REPLY_SERIAL, required for method return messages) */
1587 /* Variant array value: */
1588 0x01, /* signature length */
1589 'u', /* one complete type */
1590 0x00, /* nul terminator */
1591 /* (Variant array value payload) */
1592 0x00, 0x01, 0x02, 0x03,
1593 /* Message body: over 64 levels of nested variant, which is not valid: */
1594 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1595 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1596 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1597 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1598 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1599 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1600 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1601 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1602 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1603 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1604 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1605 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1606 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1607 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1608 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1609 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1610 /* Some arbitrary valid content inside the innermost variant: */
1611 0x01, 'y', 0x00, 0xcc,
1613 gsize size = sizeof (data);
1614 GDBusMessage *message = NULL;
1615 GError *local_error = NULL;
1617 message = g_dbus_message_new_from_blob ((guchar *) data, size,
1618 G_DBUS_CAPABILITY_FLAGS_NONE,
1620 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1621 g_assert_null (message);
1623 g_clear_error (&local_error);
1626 /* ---------------------------------------------------------------------------------------------------- */
1629 test_message_parse_truncated (void)
1631 GDBusMessage *message = NULL;
1632 GDBusMessage *message2 = NULL;
1633 GVariantBuilder builder;
1634 guchar *blob = NULL;
1636 GError *error = NULL;
1638 g_test_summary ("Test that truncated messages are properly rejected.");
1639 g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2528");
1641 message = g_dbus_message_new ();
1642 g_variant_builder_init (&builder, G_VARIANT_TYPE ("(asbynqiuxtd)"));
1643 g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
1644 g_variant_builder_add (&builder, "s", "fourtytwo");
1645 g_variant_builder_close (&builder);
1646 g_variant_builder_add (&builder, "b", TRUE);
1647 g_variant_builder_add (&builder, "y", 42);
1648 g_variant_builder_add (&builder, "n", 42);
1649 g_variant_builder_add (&builder, "q", 42);
1650 g_variant_builder_add (&builder, "i", 42);
1651 g_variant_builder_add (&builder, "u", 42);
1652 g_variant_builder_add (&builder, "x", 42);
1653 g_variant_builder_add (&builder, "t", 42);
1654 g_variant_builder_add (&builder, "d", (gdouble) 42);
1656 g_dbus_message_set_message_type (message, G_DBUS_MESSAGE_TYPE_METHOD_CALL);
1657 g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH,
1658 g_variant_new_object_path ("/foo/bar"));
1659 g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER,
1660 g_variant_new_string ("Member"));
1661 g_dbus_message_set_body (message, g_variant_builder_end (&builder));
1663 blob = g_dbus_message_to_blob (message, &size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1664 g_assert_no_error (error);
1666 g_clear_object (&message);
1668 /* Try parsing all possible prefixes of the full @blob. */
1669 for (gsize i = 0; i < size; i++)
1671 message2 = g_dbus_message_new_from_blob (blob, i, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1672 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1673 g_assert_null (message2);
1674 g_clear_error (&error);
1677 message2 = g_dbus_message_new_from_blob (blob, size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1678 g_assert_no_error (error);
1679 g_assert_true (G_IS_DBUS_MESSAGE (message2));
1680 g_clear_object (&message2);
1686 test_message_parse_empty_structure (void)
1688 const guint8 data[] =
1690 'l', /* little-endian byte order */
1691 0x02, /* message type (method return) */
1692 0x00, /* message flags (none) */
1693 0x01, /* major protocol version */
1694 0x08, 0x00, 0x00, 0x00, /* body length (in bytes) */
1695 0x00, 0x00, 0x00, 0x00, /* message serial */
1696 /* a{yv} of header fields */
1697 0x20, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1698 0x01, /* array key (PATH) */
1699 0x01, /* signature length */
1700 'o', /* type (OBJECT_PATH) */
1701 0x00, /* nul terminator */
1702 0x05, 0x00, 0x00, 0x00, /* length 5 */
1703 '/', 'p', 'a', 't', 'h', 0x00, 0x00, 0x00, /* string '/path' and padding */
1704 0x03, /* array key (MEMBER) */
1705 0x01, /* signature length */
1706 's', /* type (STRING) */
1707 0x00, /* nul terminator */
1708 0x06, 0x00, 0x00, 0x00, /* length 6 */
1709 'M', 'e', 'm', 'b', 'e', 'r', 0x00, 0x00, /* string 'Member' and padding */
1710 0x08, /* array key (SIGNATURE) */
1711 0x01, /* signature length */
1712 'g', /* type (SIGNATURE) */
1713 0x00, /* nul terminator */
1714 0x03, /* length 3 */
1715 'a', '(', ')', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* type 'a()' and padding */
1716 0x08, 0x00, 0x00, 0x00, /* array length: 4 bytes */
1717 0x00, 0x00, 0x00, 0x00, /* padding to 8 bytes */
1718 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* array data */
1721 gsize size = sizeof (data);
1722 GDBusMessage *message = NULL;
1723 GError *local_error = NULL;
1725 g_test_summary ("Test that empty structures are rejected when parsing.");
1726 g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2557");
1728 message = g_dbus_message_new_from_blob ((guchar *) data, size,
1729 G_DBUS_CAPABILITY_FLAGS_NONE,
1731 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1732 g_assert_cmpstr (local_error->message, ==, "Empty structures (tuples) are not allowed in D-Bus");
1733 g_assert_null (message);
1735 g_clear_error (&local_error);
1739 test_message_serialize_empty_structure (void)
1741 GDBusMessage *message;
1742 GVariantBuilder builder;
1744 GError *local_error = NULL;
1746 g_test_summary ("Test that empty structures are rejected when serializing.");
1747 g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2557");
1749 message = g_dbus_message_new ();
1750 g_variant_builder_init (&builder, G_VARIANT_TYPE ("(a())"));
1751 g_variant_builder_open (&builder, G_VARIANT_TYPE ("a()"));
1752 g_variant_builder_add (&builder, "()");
1753 g_variant_builder_close (&builder);
1754 g_dbus_message_set_message_type (message, G_DBUS_MESSAGE_TYPE_METHOD_CALL);
1755 g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH,
1756 g_variant_new_object_path ("/path"));
1757 g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER,
1758 g_variant_new_string ("Member"));
1759 g_dbus_message_set_body (message, g_variant_builder_end (&builder));
1761 g_dbus_message_to_blob (message, &size, G_DBUS_CAPABILITY_FLAGS_NONE, &local_error);
1762 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1763 g_assert_cmpstr (local_error->message, ==, "Empty structures (tuples) are not allowed in D-Bus");
1765 g_clear_error (&local_error);
1766 g_clear_object (&message);
1770 test_message_parse_missing_header (void)
1772 const guint8 data[] = {
1773 'l', /* little-endian byte order */
1774 0x01, /* message type (method call) */
1775 0x00, /* message flags (none) */
1776 0x01, /* major protocol version */
1777 0x12, 0x00, 0x00, 0x00, /* body length (in bytes) */
1778 0x20, 0x20, 0x20, 0x20, /* message serial */
1779 /* a{yv} of header fields: */
1780 0x24, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1781 0x01, /* array key (PATH, required for method call messages) */
1782 /* Variant array value: */
1783 0x01, /* signature length */
1784 'o', /* one complete type */
1785 0x00, /* nul terminator */
1786 /* (Variant array value payload) */
1787 0x01, 0x00, 0x00, 0x00,
1788 '/', 0x00, 0x00, 0x00,
1789 0x00, 0x00, 0x00, 0x00,
1790 0x30, /* array key (MEMBER, required for method call messages; CORRUPTED from 0x03) */
1791 /* Variant array value: */
1792 0x01, /* signature length */
1793 's', /* one complete type */
1794 0x00, /* nul terminator */
1795 /* (Variant array value payload) */
1796 0x03, 0x00, 0x00, 0x00,
1797 'H', 'e', 'y', 0x00,
1798 0x00, 0x00, 0x00, 0x00,
1799 0x08, /* array key (SIGNATURE) */
1800 /* Variant array value: */
1801 0x01, /* signature length */
1802 'g', /* one complete type */
1803 0x00, /* nul terminator */
1804 /* (Variant array value payload) */
1805 0x02, 's', 's', 0x00,
1806 /* Some arbitrary valid content inside the message body: */
1807 0x03, 0x00, 0x00, 0x00,
1808 'h', 'e', 'y', 0x00,
1809 0x05, 0x00, 0x00, 0x00,
1810 't', 'h', 'e', 'r', 'e', 0x00
1813 gsize size = sizeof (data);
1814 GDBusMessage *message = NULL;
1815 GError *local_error = NULL;
1817 g_test_summary ("Test that missing (required) headers prompt an error.");
1818 g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3061");
1820 message = g_dbus_message_new_from_blob ((guchar *) data, size,
1821 G_DBUS_CAPABILITY_FLAGS_NONE,
1823 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1824 g_assert_null (message);
1826 g_clear_error (&local_error);
1830 test_message_parse_invalid_header_type (void)
1832 const guint8 data[] = {
1833 'l', /* little-endian byte order */
1834 0x01, /* message type (method call) */
1835 0x00, /* message flags (none) */
1836 0x01, /* major protocol version */
1837 0x12, 0x00, 0x00, 0x00, /* body length (in bytes) */
1838 0x20, 0x20, 0x20, 0x20, /* message serial */
1839 /* a{yv} of header fields: */
1840 0x24, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1841 0x01, /* array key (PATH, required for method call messages) */
1842 /* Variant array value: */
1843 0x01, /* signature length */
1844 'o', /* one complete type */
1845 0x00, /* nul terminator */
1846 /* (Variant array value payload) */
1847 0x01, 0x00, 0x00, 0x00,
1848 '/', 0x00, 0x00, 0x00,
1849 0x00, 0x00, 0x00, 0x00,
1850 0x03, /* array key (MEMBER, required for method call messages) */
1851 /* Variant array value: */
1852 0x01, /* signature length */
1853 't', /* one complete type; CORRUPTED, MEMBER should be 's' */
1854 0x00, /* nul terminator */
1855 /* (Padding to 64-bit alignment of 't)' */
1856 0x00, 0x00, 0x00, 0x00,
1857 /* (Variant array value payload) */
1858 'H', 'e', 'y', 0x00,
1859 0x00, 0x00, 0x00, 0x00,
1860 0x08, /* array key (SIGNATURE) */
1861 /* Variant array value: */
1862 0x01, /* signature length */
1863 'g', /* one complete type */
1864 0x00, /* nul terminator */
1865 /* (Variant array value payload) */
1866 0x02, 's', 's', 0x00,
1867 /* Some arbitrary valid content inside the message body: */
1868 0x03, 0x00, 0x00, 0x00,
1869 'h', 'e', 'y', 0x00,
1870 0x05, 0x00, 0x00, 0x00,
1871 't', 'h', 'e', 'r', 'e', 0x00
1874 gsize size = sizeof (data);
1875 GDBusMessage *message = NULL;
1876 GError *local_error = NULL;
1878 g_test_summary ("Test that the type of well-known headers is checked.");
1879 g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3061");
1881 message = g_dbus_message_new_from_blob ((guchar *) data, size,
1882 G_DBUS_CAPABILITY_FLAGS_NONE,
1884 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1885 g_assert_null (message);
1887 g_clear_error (&local_error);
1890 /* ---------------------------------------------------------------------------------------------------- */
1896 g_setenv ("LC_ALL", "C", TRUE);
1897 setlocale (LC_ALL, "C");
1899 g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
1901 g_test_add_func ("/gdbus/message-serialize/basic",
1902 test_message_serialize_basic);
1903 g_test_add_func ("/gdbus/message-serialize/complex",
1904 test_message_serialize_complex);
1905 g_test_add_func ("/gdbus/message-serialize/invalid",
1906 test_message_serialize_invalid);
1907 g_test_add_func ("/gdbus/message-serialize/header-checks",
1908 test_message_serialize_header_checks);
1909 g_test_add_func ("/gdbus/message-serialize/header-checks/valid",
1910 test_message_serialize_header_checks_valid);
1911 g_test_add_func ("/gdbus/message-serialize/double-array",
1912 test_message_serialize_double_array);
1913 g_test_add_func ("/gdbus/message-serialize/empty-structure",
1914 test_message_serialize_empty_structure);
1916 g_test_add_func ("/gdbus/message-parse/empty-arrays-of-arrays",
1917 test_message_parse_empty_arrays_of_arrays);
1918 g_test_add_func ("/gdbus/message-parse/non-signature-header",
1919 test_message_parse_non_signature_header);
1920 g_test_add_func ("/gdbus/message-parse/empty-signature-header",
1921 test_message_parse_empty_signature_header);
1922 g_test_add_func ("/gdbus/message-parse/multiple-signature-header",
1923 test_message_parse_multiple_signature_header);
1924 g_test_add_func ("/gdbus/message-parse/over-long-signature-header",
1925 test_message_parse_over_long_signature_header);
1926 g_test_add_func ("/gdbus/message-parse/deep-header-nesting",
1927 test_message_parse_deep_header_nesting);
1928 g_test_add_func ("/gdbus/message-parse/deep-body-nesting",
1929 test_message_parse_deep_body_nesting);
1930 g_test_add_func ("/gdbus/message-parse/truncated",
1931 test_message_parse_truncated);
1932 g_test_add_func ("/gdbus/message-parse/empty-structure",
1933 test_message_parse_empty_structure);
1934 g_test_add_func ("/gdbus/message-parse/missing-header",
1935 test_message_parse_missing_header);
1936 g_test_add_func ("/gdbus/message-parse/invalid-header-type",
1937 test_message_parse_invalid_header_type);
1939 return g_test_run();