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 that we can't serialize messages with SIGNATURE set to a non-signature-typed value
919 message = g_dbus_message_new_signal ("/the/path", "The.Interface", "TheMember");
920 g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, 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, ==, "Signature header found but is not of type signature");
925 g_assert_null (blob);
927 g_clear_error (&error);
928 g_clear_object (&message);
931 * check we can't serialize signal messages with INTERFACE, PATH or MEMBER unset / set to reserved value
933 message = g_dbus_message_new_signal ("/the/path", "The.Interface", "TheMember");
935 /* interface NULL => error */
936 g_dbus_message_set_interface (message, NULL);
937 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
938 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
939 g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: PATH, INTERFACE or MEMBER header field is missing or invalid");
940 g_clear_error (&error);
941 g_assert_null (blob);
942 /* interface reserved value => error */
943 g_dbus_message_set_interface (message, "org.freedesktop.DBus.Local");
944 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
945 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
946 g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: The INTERFACE header field is using the reserved value org.freedesktop.DBus.Local");
947 g_clear_error (&error);
948 g_assert_null (blob);
949 /* reset interface */
950 g_dbus_message_set_interface (message, "The.Interface");
952 /* path NULL => error */
953 g_dbus_message_set_path (message, NULL);
954 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
955 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
956 g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: PATH, INTERFACE or MEMBER header field is missing or invalid");
957 g_clear_error (&error);
958 g_assert_null (blob);
959 /* path reserved value => error */
960 g_dbus_message_set_path (message, "/org/freedesktop/DBus/Local");
961 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
962 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
963 g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: The PATH header field is using the reserved value /org/freedesktop/DBus/Local");
964 g_clear_error (&error);
965 g_assert_null (blob);
967 g_dbus_message_set_path (message, "/the/path");
969 /* member NULL => error */
970 g_dbus_message_set_member (message, NULL);
971 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
972 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
973 g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: PATH, INTERFACE or MEMBER header field is missing or invalid");
974 g_clear_error (&error);
975 g_assert_null (blob);
977 g_dbus_message_set_member (message, "TheMember");
980 g_object_unref (message);
983 * check that we can't serialize method call messages with PATH or MEMBER unset
985 message = g_dbus_message_new_method_call (NULL, "/the/path", NULL, "TheMember");
987 /* path NULL => error */
988 g_dbus_message_set_path (message, NULL);
989 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
990 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
991 g_assert_cmpstr (error->message, ==, "Cannot serialize message: METHOD_CALL message: PATH or MEMBER header field is missing or invalid");
992 g_clear_error (&error);
993 g_assert_null (blob);
995 g_dbus_message_set_path (message, "/the/path");
997 /* member NULL => error */
998 g_dbus_message_set_member (message, NULL);
999 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1000 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1001 g_assert_cmpstr (error->message, ==, "Cannot serialize message: METHOD_CALL message: PATH or MEMBER header field is missing or invalid");
1002 g_clear_error (&error);
1003 g_assert_null (blob);
1005 g_dbus_message_set_member (message, "TheMember");
1008 g_object_unref (message);
1011 * check that we can't serialize method reply messages with REPLY_SERIAL unset
1013 message = g_dbus_message_new_method_call (NULL, "/the/path", NULL, "TheMember");
1014 g_dbus_message_set_serial (message, 42);
1016 reply = g_dbus_message_new_method_reply (message);
1017 g_assert_cmpint (g_dbus_message_get_reply_serial (reply), ==, 42);
1018 g_dbus_message_set_header (reply, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, NULL);
1019 blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1020 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1021 g_assert_cmpstr (error->message, ==, "Cannot serialize message: METHOD_RETURN message: REPLY_SERIAL header field is missing or invalid");
1022 g_clear_error (&error);
1023 g_assert_null (blob);
1024 g_object_unref (reply);
1025 /* method error - first nuke ERROR_NAME, then REPLY_SERIAL */
1026 reply = g_dbus_message_new_method_error (message, "Some.Error.Name", "the message");
1027 g_assert_cmpint (g_dbus_message_get_reply_serial (reply), ==, 42);
1028 /* nuke ERROR_NAME */
1029 g_dbus_message_set_error_name (reply, NULL);
1030 blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1031 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1032 g_assert_cmpstr (error->message, ==, "Cannot serialize message: ERROR message: REPLY_SERIAL or ERROR_NAME header field is missing or invalid");
1033 g_clear_error (&error);
1034 g_assert_null (blob);
1035 /* reset ERROR_NAME */
1036 g_dbus_message_set_error_name (reply, "Some.Error.Name");
1037 /* nuke REPLY_SERIAL */
1038 g_dbus_message_set_header (reply, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, NULL);
1039 blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1040 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1041 g_assert_cmpstr (error->message, ==, "Cannot serialize message: ERROR message: REPLY_SERIAL or ERROR_NAME header field is missing or invalid");
1042 g_clear_error (&error);
1043 g_assert_null (blob);
1044 g_object_unref (reply);
1045 g_object_unref (message);
1048 /* ---------------------------------------------------------------------------------------------------- */
1051 test_message_parse_empty_arrays_of_arrays (void)
1054 GError *error = NULL;
1056 g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=673612");
1057 /* These three-element array of empty arrays were previously read back as a
1058 * two-element array of empty arrays, due to sometimes erroneously skipping
1059 * four bytes to align for the eight-byte-aligned grandchild types (x and
1062 body = g_variant_parse (G_VARIANT_TYPE ("(aaax)"),
1063 "([@aax [], [], []],)", NULL, NULL, &error);
1064 g_assert_no_error (error);
1065 check_serialization (body,
1070 g_variant_unref (body);
1072 body = g_variant_parse (G_VARIANT_TYPE ("(aaa{uu})"),
1073 "([@aa{uu} [], [], []],)", NULL, NULL, &error);
1074 g_assert_no_error (error);
1075 check_serialization (body,
1080 g_variant_unref (body);
1082 /* Due to the same bug, g_dbus_message_new_from_blob() would fail for this
1083 * message because it would try to read past the end of the string. Hence,
1084 * sending this to an application would make it fall off the bus. */
1085 body = g_variant_parse (G_VARIANT_TYPE ("(a(aa{sv}as))"),
1088 " ([], [])],)", NULL, NULL, &error);
1089 g_assert_no_error (error);
1090 check_serialization (body,
1101 g_variant_unref (body);
1104 /* ---------------------------------------------------------------------------------------------------- */
1107 test_message_serialize_double_array (void)
1109 GVariantBuilder builder;
1112 g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=732754");
1114 g_variant_builder_init (&builder, G_VARIANT_TYPE ("ad"));
1115 g_variant_builder_add (&builder, "d", (gdouble)0.0);
1116 g_variant_builder_add (&builder, "d", (gdouble)8.0);
1117 g_variant_builder_add (&builder, "d", (gdouble)22.0);
1118 g_variant_builder_add (&builder, "d", (gdouble)0.0);
1119 body = g_variant_new ("(@ad)", g_variant_builder_end (&builder));
1120 check_serialization (body,
1122 " double: 0.000000\n"
1123 " double: 8.000000\n"
1124 " double: 22.000000\n"
1125 " double: 0.000000\n");
1128 /* ---------------------------------------------------------------------------------------------------- */
1130 /* Test that an invalid header in a D-Bus message (specifically, with a type
1131 * which doesn’t match what’s expected for the given header) is gracefully
1132 * handled with an error rather than a crash. */
1134 test_message_parse_non_signature_header (void)
1136 const guint8 data[] = {
1137 'l', /* little-endian byte order */
1138 0x02, /* message type (method return) */
1139 0x00, /* message flags (none) */
1140 0x01, /* major protocol version */
1141 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */
1142 0x00, 0x00, 0x00, 0xbc, /* message serial */
1143 /* a{yv} of header fields:
1144 * (things start to be invalid below here) */
1145 0x10, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1146 0x08, /* array key (SIGNATURE) */
1147 /* Variant array value: */
1148 0x04, /* signature length */
1149 'd', 0x00, 0x00, 'F', /* signature (invalid) */
1150 0x00, /* nul terminator */
1151 /* (Variant array value payload missing) */
1152 /* alignment padding before the next header array element, as structs must
1155 0x05, /* array key (REPLY_SERIAL, required for method return messages) */
1156 /* Variant array value: */
1157 0x01, /* signature length */
1158 'u', /* one complete type */
1159 0x00, /* nul terminator */
1160 /* (Variant array value payload) */
1161 0x00, 0x01, 0x02, 0x03,
1162 /* (message body is zero-length) */
1164 gsize size = sizeof (data);
1165 GDBusMessage *message = NULL;
1166 GError *local_error = NULL;
1168 message = g_dbus_message_new_from_blob ((guchar *) data, size,
1169 G_DBUS_CAPABILITY_FLAGS_NONE,
1171 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1172 g_assert_null (message);
1174 g_clear_error (&local_error);
1177 /* ---------------------------------------------------------------------------------------------------- */
1179 /* Test that an invalid header in a D-Bus message (specifically, containing a
1180 * variant with an empty type signature) is gracefully handled with an error
1181 * rather than a crash. */
1183 test_message_parse_empty_signature_header (void)
1185 const guint8 data[] = {
1186 'l', /* little-endian byte order */
1187 0x02, /* message type (method return) */
1188 0x00, /* message flags (none) */
1189 0x01, /* major protocol version */
1190 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */
1191 0x20, 0x20, 0x20, 0x20, /* message serial */
1192 /* a{yv} of header fields:
1193 * (things start to be invalid below here) */
1194 0x10, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1195 0x20, /* array key (this is not currently a valid header field) */
1196 /* Variant array value: */
1197 0x00, /* signature length */
1198 0x00, /* nul terminator */
1199 /* (Variant array value payload missing) */
1200 /* alignment padding before the next header array element, as structs must
1202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1203 0x05, /* array key (REPLY_SERIAL, required for method return messages) */
1204 /* Variant array value: */
1205 0x01, /* signature length */
1206 'u', /* one complete type */
1207 0x00, /* nul terminator */
1208 /* (Variant array value payload) */
1209 0x00, 0x01, 0x02, 0x03,
1210 /* (message body is zero-length) */
1212 gsize size = sizeof (data);
1213 GDBusMessage *message = NULL;
1214 GError *local_error = NULL;
1216 message = g_dbus_message_new_from_blob ((guchar *) data, size,
1217 G_DBUS_CAPABILITY_FLAGS_NONE,
1219 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1220 g_assert_null (message);
1222 g_clear_error (&local_error);
1225 /* ---------------------------------------------------------------------------------------------------- */
1227 /* Test that an invalid header in a D-Bus message (specifically, containing a
1228 * variant with a type signature containing multiple complete types) is
1229 * gracefully handled with an error rather than a crash. */
1231 test_message_parse_multiple_signature_header (void)
1233 const guint8 data[] = {
1234 'l', /* little-endian byte order */
1235 0x02, /* message type (method return) */
1236 0x00, /* message flags (none) */
1237 0x01, /* major protocol version */
1238 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */
1239 0x20, 0x20, 0x20, 0x20, /* message serial */
1240 /* a{yv} of header fields:
1241 * (things start to be invalid below here) */
1242 0x10, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1243 0x20, /* array key (this is not currently a valid header field) */
1244 /* Variant array value: */
1245 0x02, /* signature length */
1246 'b', 'b', /* two complete types */
1247 0x00, /* nul terminator */
1248 /* (Variant array value payload missing) */
1249 /* alignment padding before the next header array element, as structs must
1252 0x05, /* array key (REPLY_SERIAL, required for method return messages) */
1253 /* Variant array value: */
1254 0x01, /* signature length */
1255 'u', /* one complete type */
1256 0x00, /* nul terminator */
1257 /* (Variant array value payload) */
1258 0x00, 0x01, 0x02, 0x03,
1259 /* (message body is zero-length) */
1261 gsize size = sizeof (data);
1262 GDBusMessage *message = NULL;
1263 GError *local_error = NULL;
1265 message = g_dbus_message_new_from_blob ((guchar *) data, size,
1266 G_DBUS_CAPABILITY_FLAGS_NONE,
1268 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1269 g_assert_null (message);
1271 g_clear_error (&local_error);
1274 /* ---------------------------------------------------------------------------------------------------- */
1276 /* Test that an invalid header in a D-Bus message (specifically, containing a
1277 * variant with a valid type signature that is too long to be a valid
1278 * #GVariantType due to exceeding the array nesting limits) is gracefully
1279 * handled with an error rather than a crash. */
1281 test_message_parse_over_long_signature_header (void)
1283 const guint8 data[] = {
1284 'l', /* little-endian byte order */
1285 0x02, /* message type (method return) */
1286 0x00, /* message flags (none) */
1287 0x01, /* major protocol version */
1288 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */
1289 0x20, 0x20, 0x20, 0x20, /* message serial */
1290 /* a{yv} of header fields:
1291 * (things start to be invalid below here) */
1292 0xa0, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1293 0x08, /* array key (SIGNATURE) */
1294 /* Variant array value: */
1295 0x04, /* signature length */
1296 'g', 0x00, 0x20, 0x20, /* one complete type plus some rubbish */
1297 0x00, /* nul terminator */
1298 /* (Variant array value payload) */
1299 /* Critically, this contains 128 nested ‘a’s, which exceeds
1300 * %G_VARIANT_MAX_RECURSION_DEPTH. */
1302 'a', 'b', 'g', 'd', 'u', 'd', 'd', 'd', 'd', 'd', 'd', 'd',
1304 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1305 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1306 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1307 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1308 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1309 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1310 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1311 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1312 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1313 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1314 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1316 /* first header length is a multiple of 8 so no padding is needed */
1317 0x05, /* array key (REPLY_SERIAL, required for method return messages) */
1318 /* Variant array value: */
1319 0x01, /* signature length */
1320 'u', /* one complete type */
1321 0x00, /* nul terminator */
1322 /* (Variant array value payload) */
1323 0x00, 0x01, 0x02, 0x03,
1324 /* (message body is zero-length) */
1326 gsize size = sizeof (data);
1327 GDBusMessage *message = NULL;
1328 GError *local_error = NULL;
1330 message = g_dbus_message_new_from_blob ((guchar *) data, size,
1331 G_DBUS_CAPABILITY_FLAGS_NONE,
1333 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1334 g_assert_null (message);
1336 g_clear_error (&local_error);
1339 /* ---------------------------------------------------------------------------------------------------- */
1341 /* Test that an invalid header in a D-Bus message (specifically, containing too
1342 * many levels of nested variant) is gracefully handled with an error rather
1345 test_message_parse_deep_header_nesting (void)
1347 const guint8 data[] = {
1348 'l', /* little-endian byte order */
1349 0x02, /* message type (method return) */
1350 0x00, /* message flags (none) */
1351 0x01, /* major protocol version */
1352 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */
1353 0x20, 0x20, 0x20, 0x20, /* message serial */
1354 /* a{yv} of header fields:
1355 * (things start to be invalid below here) */
1356 0xd0, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1357 0x20, /* array key (this is not currently a valid header field) */
1358 /* Variant array value: */
1359 0x01, /* signature length */
1360 'v', /* one complete type */
1361 0x00, /* nul terminator */
1362 /* (Variant array value payload) */
1363 /* Critically, this contains 64 nested variants (minus two for the
1364 * ‘arbitrary valid content’ below, but ignoring two for the `a{yv}`
1365 * above), which in total exceeds %G_DBUS_MAX_TYPE_DEPTH. */
1366 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1367 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1368 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1369 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1370 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1371 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1372 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1373 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1374 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1375 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1376 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1377 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1378 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1379 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1380 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1381 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1382 /* Some arbitrary valid content inside the innermost variant: */
1383 0x01, 'y', 0x00, 0xcc,
1384 /* no padding needed as this header element length is a multiple of 8 */
1385 0x05, /* array key (REPLY_SERIAL, required for method return messages) */
1386 /* Variant array value: */
1387 0x01, /* signature length */
1388 'u', /* one complete type */
1389 0x00, /* nul terminator */
1390 /* (Variant array value payload) */
1391 0x00, 0x01, 0x02, 0x03,
1392 /* (message body is zero-length) */
1394 gsize size = sizeof (data);
1395 GDBusMessage *message = NULL;
1396 GError *local_error = NULL;
1398 message = g_dbus_message_new_from_blob ((guchar *) data, size,
1399 G_DBUS_CAPABILITY_FLAGS_NONE,
1401 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1402 g_assert_null (message);
1404 g_clear_error (&local_error);
1407 /* ---------------------------------------------------------------------------------------------------- */
1409 /* Test that an invalid body in a D-Bus message (specifically, containing too
1410 * many levels of nested variant) is gracefully handled with an error rather
1411 * than a crash. The set of bytes here are a modified version of the bytes from
1412 * test_message_parse_deep_header_nesting(). */
1414 test_message_parse_deep_body_nesting (void)
1416 const guint8 data[] = {
1417 'l', /* little-endian byte order */
1418 0x02, /* message type (method return) */
1419 0x00, /* message flags (none) */
1420 0x01, /* major protocol version */
1421 0xc4, 0x00, 0x00, 0x00, /* body length (in bytes) */
1422 0x20, 0x20, 0x20, 0x20, /* message serial */
1423 /* a{yv} of header fields: */
1424 0x10, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1425 0x08, /* array key (SIGNATURE) */
1426 /* Variant array value: */
1427 0x01, /* signature length */
1428 'g', /* one complete type */
1429 0x00, /* nul terminator */
1430 /* (Variant array value payload) */
1432 /* alignment padding before the next header array element, as structs must
1435 0x05, /* array key (REPLY_SERIAL, required for method return messages) */
1436 /* Variant array value: */
1437 0x01, /* signature length */
1438 'u', /* one complete type */
1439 0x00, /* nul terminator */
1440 /* (Variant array value payload) */
1441 0x00, 0x01, 0x02, 0x03,
1442 /* Message body: over 64 levels of nested variant, which is not valid: */
1443 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1444 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1445 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1446 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1447 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1448 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1449 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1450 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1451 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1452 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1453 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1454 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1455 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1456 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1457 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1458 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1459 /* Some arbitrary valid content inside the innermost variant: */
1460 0x01, 'y', 0x00, 0xcc,
1462 gsize size = sizeof (data);
1463 GDBusMessage *message = NULL;
1464 GError *local_error = NULL;
1466 message = g_dbus_message_new_from_blob ((guchar *) data, size,
1467 G_DBUS_CAPABILITY_FLAGS_NONE,
1469 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1470 g_assert_null (message);
1472 g_clear_error (&local_error);
1475 /* ---------------------------------------------------------------------------------------------------- */
1478 test_message_parse_truncated (void)
1480 GDBusMessage *message = NULL;
1481 GDBusMessage *message2 = NULL;
1482 GVariantBuilder builder;
1483 guchar *blob = NULL;
1485 GError *error = NULL;
1487 g_test_summary ("Test that truncated messages are properly rejected.");
1488 g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2528");
1490 message = g_dbus_message_new ();
1491 g_variant_builder_init (&builder, G_VARIANT_TYPE ("(asbynqiuxtd)"));
1492 g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
1493 g_variant_builder_add (&builder, "s", "fourtytwo");
1494 g_variant_builder_close (&builder);
1495 g_variant_builder_add (&builder, "b", TRUE);
1496 g_variant_builder_add (&builder, "y", 42);
1497 g_variant_builder_add (&builder, "n", 42);
1498 g_variant_builder_add (&builder, "q", 42);
1499 g_variant_builder_add (&builder, "i", 42);
1500 g_variant_builder_add (&builder, "u", 42);
1501 g_variant_builder_add (&builder, "x", 42);
1502 g_variant_builder_add (&builder, "t", 42);
1503 g_variant_builder_add (&builder, "d", (gdouble) 42);
1505 g_dbus_message_set_message_type (message, G_DBUS_MESSAGE_TYPE_METHOD_CALL);
1506 g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH,
1507 g_variant_new_object_path ("/foo/bar"));
1508 g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER,
1509 g_variant_new_string ("Member"));
1510 g_dbus_message_set_body (message, g_variant_builder_end (&builder));
1512 blob = g_dbus_message_to_blob (message, &size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1513 g_assert_no_error (error);
1515 g_clear_object (&message);
1517 /* Try parsing all possible prefixes of the full @blob. */
1518 for (gsize i = 0; i < size; i++)
1520 message2 = g_dbus_message_new_from_blob (blob, i, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1521 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1522 g_assert_null (message2);
1523 g_clear_error (&error);
1526 message2 = g_dbus_message_new_from_blob (blob, size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1527 g_assert_no_error (error);
1528 g_assert_true (G_IS_DBUS_MESSAGE (message2));
1529 g_clear_object (&message2);
1535 test_message_parse_empty_structure (void)
1537 const guint8 data[] =
1539 'l', /* little-endian byte order */
1540 0x02, /* message type (method return) */
1541 0x00, /* message flags (none) */
1542 0x01, /* major protocol version */
1543 0x08, 0x00, 0x00, 0x00, /* body length (in bytes) */
1544 0x00, 0x00, 0x00, 0x00, /* message serial */
1545 /* a{yv} of header fields */
1546 0x20, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1547 0x01, /* array key (PATH) */
1548 0x01, /* signature length */
1549 'o', /* type (OBJECT_PATH) */
1550 0x00, /* nul terminator */
1551 0x05, 0x00, 0x00, 0x00, /* length 5 */
1552 '/', 'p', 'a', 't', 'h', 0x00, 0x00, 0x00, /* string '/path' and padding */
1553 0x03, /* array key (MEMBER) */
1554 0x01, /* signature length */
1555 's', /* type (STRING) */
1556 0x00, /* nul terminator */
1557 0x06, 0x00, 0x00, 0x00, /* length 6 */
1558 'M', 'e', 'm', 'b', 'e', 'r', 0x00, 0x00, /* string 'Member' and padding */
1559 0x08, /* array key (SIGNATURE) */
1560 0x01, /* signature length */
1561 'g', /* type (SIGNATURE) */
1562 0x00, /* nul terminator */
1563 0x03, /* length 3 */
1564 'a', '(', ')', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* type 'a()' and padding */
1565 0x08, 0x00, 0x00, 0x00, /* array length: 4 bytes */
1566 0x00, 0x00, 0x00, 0x00, /* padding to 8 bytes */
1567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* array data */
1570 gsize size = sizeof (data);
1571 GDBusMessage *message = NULL;
1572 GError *local_error = NULL;
1574 g_test_summary ("Test that empty structures are rejected when parsing.");
1575 g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2557");
1577 message = g_dbus_message_new_from_blob ((guchar *) data, size,
1578 G_DBUS_CAPABILITY_FLAGS_NONE,
1580 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1581 g_assert_cmpstr (local_error->message, ==, "Empty structures (tuples) are not allowed in D-Bus");
1582 g_assert_null (message);
1584 g_clear_error (&local_error);
1588 test_message_serialize_empty_structure (void)
1590 GDBusMessage *message;
1591 GVariantBuilder builder;
1593 GError *local_error = NULL;
1595 g_test_summary ("Test that empty structures are rejected when serializing.");
1596 g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2557");
1598 message = g_dbus_message_new ();
1599 g_variant_builder_init (&builder, G_VARIANT_TYPE ("(a())"));
1600 g_variant_builder_open (&builder, G_VARIANT_TYPE ("a()"));
1601 g_variant_builder_add (&builder, "()");
1602 g_variant_builder_close (&builder);
1603 g_dbus_message_set_message_type (message, G_DBUS_MESSAGE_TYPE_METHOD_CALL);
1604 g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH,
1605 g_variant_new_object_path ("/path"));
1606 g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER,
1607 g_variant_new_string ("Member"));
1608 g_dbus_message_set_body (message, g_variant_builder_end (&builder));
1610 g_dbus_message_to_blob (message, &size, G_DBUS_CAPABILITY_FLAGS_NONE, &local_error);
1611 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1612 g_assert_cmpstr (local_error->message, ==, "Empty structures (tuples) are not allowed in D-Bus");
1614 g_clear_error (&local_error);
1615 g_clear_object (&message);
1619 test_message_parse_missing_header (void)
1621 const guint8 data[] = {
1622 'l', /* little-endian byte order */
1623 0x01, /* message type (method call) */
1624 0x00, /* message flags (none) */
1625 0x01, /* major protocol version */
1626 0x12, 0x00, 0x00, 0x00, /* body length (in bytes) */
1627 0x20, 0x20, 0x20, 0x20, /* message serial */
1628 /* a{yv} of header fields: */
1629 0x24, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1630 0x01, /* array key (PATH, required for method call messages) */
1631 /* Variant array value: */
1632 0x01, /* signature length */
1633 'o', /* one complete type */
1634 0x00, /* nul terminator */
1635 /* (Variant array value payload) */
1636 0x01, 0x00, 0x00, 0x00,
1637 '/', 0x00, 0x00, 0x00,
1638 0x00, 0x00, 0x00, 0x00,
1639 0x30, /* array key (MEMBER, required for method call messages; CORRUPTED from 0x03) */
1640 /* Variant array value: */
1641 0x01, /* signature length */
1642 's', /* one complete type */
1643 0x00, /* nul terminator */
1644 /* (Variant array value payload) */
1645 0x03, 0x00, 0x00, 0x00,
1646 'H', 'e', 'y', 0x00,
1647 0x00, 0x00, 0x00, 0x00,
1648 0x08, /* array key (SIGNATURE) */
1649 /* Variant array value: */
1650 0x01, /* signature length */
1651 'g', /* one complete type */
1652 0x00, /* nul terminator */
1653 /* (Variant array value payload) */
1654 0x02, 's', 's', 0x00,
1655 /* Some arbitrary valid content inside the message body: */
1656 0x03, 0x00, 0x00, 0x00,
1657 'h', 'e', 'y', 0x00,
1658 0x05, 0x00, 0x00, 0x00,
1659 't', 'h', 'e', 'r', 'e', 0x00
1662 gsize size = sizeof (data);
1663 GDBusMessage *message = NULL;
1664 GError *local_error = NULL;
1666 g_test_summary ("Test that missing (required) headers prompt an error.");
1667 g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3061");
1669 message = g_dbus_message_new_from_blob ((guchar *) data, size,
1670 G_DBUS_CAPABILITY_FLAGS_NONE,
1672 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1673 g_assert_null (message);
1675 g_clear_error (&local_error);
1679 test_message_parse_invalid_header_type (void)
1681 const guint8 data[] = {
1682 'l', /* little-endian byte order */
1683 0x01, /* message type (method call) */
1684 0x00, /* message flags (none) */
1685 0x01, /* major protocol version */
1686 0x12, 0x00, 0x00, 0x00, /* body length (in bytes) */
1687 0x20, 0x20, 0x20, 0x20, /* message serial */
1688 /* a{yv} of header fields: */
1689 0x24, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1690 0x01, /* array key (PATH, required for method call messages) */
1691 /* Variant array value: */
1692 0x01, /* signature length */
1693 'o', /* one complete type */
1694 0x00, /* nul terminator */
1695 /* (Variant array value payload) */
1696 0x01, 0x00, 0x00, 0x00,
1697 '/', 0x00, 0x00, 0x00,
1698 0x00, 0x00, 0x00, 0x00,
1699 0x03, /* array key (MEMBER, required for method call messages) */
1700 /* Variant array value: */
1701 0x01, /* signature length */
1702 't', /* one complete type; CORRUPTED, MEMBER should be 's' */
1703 0x00, /* nul terminator */
1704 /* (Padding to 64-bit alignment of 't)' */
1705 0x00, 0x00, 0x00, 0x00,
1706 /* (Variant array value payload) */
1707 'H', 'e', 'y', 0x00,
1708 0x00, 0x00, 0x00, 0x00,
1709 0x08, /* array key (SIGNATURE) */
1710 /* Variant array value: */
1711 0x01, /* signature length */
1712 'g', /* one complete type */
1713 0x00, /* nul terminator */
1714 /* (Variant array value payload) */
1715 0x02, 's', 's', 0x00,
1716 /* Some arbitrary valid content inside the message body: */
1717 0x03, 0x00, 0x00, 0x00,
1718 'h', 'e', 'y', 0x00,
1719 0x05, 0x00, 0x00, 0x00,
1720 't', 'h', 'e', 'r', 'e', 0x00
1723 gsize size = sizeof (data);
1724 GDBusMessage *message = NULL;
1725 GError *local_error = NULL;
1727 g_test_summary ("Test that the type of well-known headers is checked.");
1728 g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3061");
1730 message = g_dbus_message_new_from_blob ((guchar *) data, size,
1731 G_DBUS_CAPABILITY_FLAGS_NONE,
1733 g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1734 g_assert_null (message);
1736 g_clear_error (&local_error);
1739 /* ---------------------------------------------------------------------------------------------------- */
1745 g_setenv ("LC_ALL", "C", TRUE);
1746 setlocale (LC_ALL, "C");
1748 g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
1750 g_test_add_func ("/gdbus/message-serialize/basic",
1751 test_message_serialize_basic);
1752 g_test_add_func ("/gdbus/message-serialize/complex",
1753 test_message_serialize_complex);
1754 g_test_add_func ("/gdbus/message-serialize/invalid",
1755 test_message_serialize_invalid);
1756 g_test_add_func ("/gdbus/message-serialize/header-checks",
1757 test_message_serialize_header_checks);
1758 g_test_add_func ("/gdbus/message-serialize/double-array",
1759 test_message_serialize_double_array);
1760 g_test_add_func ("/gdbus/message-serialize/empty-structure",
1761 test_message_serialize_empty_structure);
1763 g_test_add_func ("/gdbus/message-parse/empty-arrays-of-arrays",
1764 test_message_parse_empty_arrays_of_arrays);
1765 g_test_add_func ("/gdbus/message-parse/non-signature-header",
1766 test_message_parse_non_signature_header);
1767 g_test_add_func ("/gdbus/message-parse/empty-signature-header",
1768 test_message_parse_empty_signature_header);
1769 g_test_add_func ("/gdbus/message-parse/multiple-signature-header",
1770 test_message_parse_multiple_signature_header);
1771 g_test_add_func ("/gdbus/message-parse/over-long-signature-header",
1772 test_message_parse_over_long_signature_header);
1773 g_test_add_func ("/gdbus/message-parse/deep-header-nesting",
1774 test_message_parse_deep_header_nesting);
1775 g_test_add_func ("/gdbus/message-parse/deep-body-nesting",
1776 test_message_parse_deep_body_nesting);
1777 g_test_add_func ("/gdbus/message-parse/truncated",
1778 test_message_parse_truncated);
1779 g_test_add_func ("/gdbus/message-parse/empty-structure",
1780 test_message_parse_empty_structure);
1781 g_test_add_func ("/gdbus/message-parse/missing-header",
1782 test_message_parse_missing_header);
1783 g_test_add_func ("/gdbus/message-parse/invalid-header-type",
1784 test_message_parse_invalid_header_type);
1786 return g_test_run();