gkdbus: Fix underflow and unreachable code bug
[platform/upstream/glib.git] / gio / tests / gdbus-serialization.c
1 /* GLib testing framework examples and tests
2  *
3  * Copyright (C) 2008-2010 Red Hat, Inc.
4  *
5  * SPDX-License-Identifier: LGPL-2.1-or-later
6  *
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.
11  *
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.
16  *
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/>.
19  *
20  * Author: David Zeuthen <davidz@redhat.com>
21  */
22
23 #include <locale.h>
24 #include <gio/gio.h>
25
26 #include <string.h>
27 #ifndef _MSC_VER
28 #include <unistd.h>
29 #endif
30 #include <dbus/dbus.h>
31
32 /* ---------------------------------------------------------------------------------------------------- */
33
34 static void
35 hexdump (const guchar *str, gsize len)
36 {
37   const guchar *data = (const guchar *) str;
38   guint n, m;
39
40   for (n = 0; n < len; n += 16)
41     {
42       g_printerr ("%04x: ", n);
43
44       for (m = n; m < n + 16; m++)
45         {
46           if (m > n && (m%4) == 0)
47             g_printerr (" ");
48           if (m < len)
49             g_printerr ("%02x ", data[m]);
50           else
51             g_printerr ("   ");
52         }
53
54       g_printerr ("   ");
55
56       for (m = n; m < len && m < n + 16; m++)
57         g_printerr ("%c", g_ascii_isprint (data[m]) ? data[m] : '.');
58
59       g_printerr ("\n");
60     }
61 }
62
63 /* ---------------------------------------------------------------------------------------------------- */
64
65 static gboolean
66 append_gv_to_dbus_iter (DBusMessageIter  *iter,
67                         GVariant         *value,
68                         GError          **error)
69 {
70   const GVariantType *type;
71
72   type = g_variant_get_type (value);
73   if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
74     {
75       dbus_bool_t v = g_variant_get_boolean (value);
76       dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &v);
77     }
78   else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
79     {
80       guint8 v = g_variant_get_byte (value);
81       dbus_message_iter_append_basic (iter, DBUS_TYPE_BYTE, &v);
82     }
83   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
84     {
85       gint16 v = g_variant_get_int16 (value);
86       dbus_message_iter_append_basic (iter, DBUS_TYPE_INT16, &v);
87     }
88   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
89     {
90       guint16 v = g_variant_get_uint16 (value);
91       dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT16, &v);
92     }
93   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
94     {
95       gint32 v = g_variant_get_int32 (value);
96       dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &v);
97     }
98   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
99     {
100       guint32 v = g_variant_get_uint32 (value);
101       dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &v);
102     }
103   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
104     {
105       gint64 v = g_variant_get_int64 (value);
106       dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &v);
107     }
108   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
109     {
110       guint64 v = g_variant_get_uint64 (value);
111       dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &v);
112     }
113   else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
114     {
115       gdouble v = g_variant_get_double (value);
116       dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &v);
117     }
118   else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
119     {
120       const gchar *v = g_variant_get_string (value, NULL);
121       dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &v);
122     }
123   else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
124     {
125       const gchar *v = g_variant_get_string (value, NULL);
126       dbus_message_iter_append_basic (iter, DBUS_TYPE_OBJECT_PATH, &v);
127     }
128   else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
129     {
130       const gchar *v = g_variant_get_string (value, NULL);
131       dbus_message_iter_append_basic (iter, DBUS_TYPE_SIGNATURE, &v);
132     }
133   else if (g_variant_type_is_variant (type))
134     {
135       DBusMessageIter sub;
136       GVariant *child;
137
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),
141                                         &sub);
142       if (!append_gv_to_dbus_iter (&sub, child, error))
143         {
144             g_variant_unref (child);
145             goto fail;
146         }
147       dbus_message_iter_close_container (iter, &sub);
148       g_variant_unref (child);
149     }
150   else if (g_variant_type_is_array (type))
151     {
152       DBusMessageIter dbus_iter;
153       const gchar *type_string;
154       GVariantIter gv_iter;
155       GVariant *item;
156
157       type_string = g_variant_get_type_string (value);
158       type_string++; /* skip the 'a' */
159
160       dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY,
161                                         type_string, &dbus_iter);
162       g_variant_iter_init (&gv_iter, value);
163
164       while ((item = g_variant_iter_next_value (&gv_iter)))
165         {
166           if (!append_gv_to_dbus_iter (&dbus_iter, item, error))
167             {
168               goto fail;
169             }
170         }
171
172       dbus_message_iter_close_container (iter, &dbus_iter);
173     }
174   else if (g_variant_type_is_tuple (type))
175     {
176       DBusMessageIter dbus_iter;
177       GVariantIter gv_iter;
178       GVariant *item;
179
180       dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT,
181                                         NULL, &dbus_iter);
182       g_variant_iter_init (&gv_iter, value);
183
184       while ((item = g_variant_iter_next_value (&gv_iter)))
185         {
186           if (!append_gv_to_dbus_iter (&dbus_iter, item, error))
187             goto fail;
188         }
189
190       dbus_message_iter_close_container (iter, &dbus_iter);
191     }
192   else if (g_variant_type_is_dict_entry (type))
193     {
194       DBusMessageIter dbus_iter;
195       GVariant *key, *val;
196
197       dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY,
198                                         NULL, &dbus_iter);
199       key = g_variant_get_child_value (value, 0);
200       if (!append_gv_to_dbus_iter (&dbus_iter, key, error))
201         {
202           g_variant_unref (key);
203           goto fail;
204         }
205       g_variant_unref (key);
206
207       val = g_variant_get_child_value (value, 1);
208       if (!append_gv_to_dbus_iter (&dbus_iter, val, error))
209         {
210           g_variant_unref (val);
211           goto fail;
212         }
213       g_variant_unref (val);
214
215       dbus_message_iter_close_container (iter, &dbus_iter);
216     }
217   else
218     {
219       g_set_error (error,
220                    G_IO_ERROR,
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));
224       goto fail;
225     }
226
227   return TRUE;
228
229  fail:
230   return FALSE;
231 }
232
233 static gboolean
234 append_gv_to_dbus_message (DBusMessage  *message,
235                            GVariant     *value,
236                            GError      **error)
237 {
238   gboolean ret;
239   guint n;
240
241   ret = FALSE;
242
243   if (value != NULL)
244     {
245       DBusMessageIter iter;
246       GVariantIter gv_iter;
247       GVariant *item;
248
249       dbus_message_iter_init_append (message, &iter);
250
251       g_variant_iter_init (&gv_iter, value);
252       n = 0;
253       while ((item = g_variant_iter_next_value (&gv_iter)))
254         {
255           if (!append_gv_to_dbus_iter (&iter, item, error))
256             {
257               g_prefix_error (error,
258                               "Error encoding in-arg %d: ",
259                               n);
260               goto out;
261             }
262           n++;
263         }
264     }
265
266   ret = TRUE;
267
268  out:
269   return ret;
270 }
271
272 static void
273 print_gv_dbus_message (GVariant *value)
274 {
275   DBusMessage *message;
276   char *blob;
277   int blob_len;
278   GError *error;
279
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");
284
285   error = NULL;
286   if (!append_gv_to_dbus_message (message, value, &error))
287     {
288       g_printerr ("Error printing GVariant as DBusMessage: %s", error->message);
289       g_error_free (error);
290       goto out;
291     }
292
293   dbus_message_marshal (message, &blob, &blob_len);
294   g_printerr ("\n");
295   hexdump ((guchar *) blob, blob_len);
296  out:
297   dbus_message_unref (message);
298 }
299
300 /* ---------------------------------------------------------------------------------------------------- */
301
302 static void
303 dbus_1_message_append (GString *s,
304                        guint indent,
305                        DBusMessageIter *iter)
306 {
307   gint arg_type;
308   DBusMessageIter sub;
309
310   g_string_append_printf (s, "%*s", indent, "");
311
312   arg_type = dbus_message_iter_get_arg_type (iter);
313   switch (arg_type)
314     {
315      case DBUS_TYPE_BOOLEAN:
316       {
317         dbus_bool_t value;
318         dbus_message_iter_get_basic (iter, &value);
319         g_string_append_printf (s, "bool: %s\n", value ? "true" : "false");
320         break;
321       }
322
323      case DBUS_TYPE_BYTE:
324       {
325         guchar value;
326         dbus_message_iter_get_basic (iter, &value);
327         g_string_append_printf (s, "byte: 0x%02x\n", (guint) value);
328         break;
329       }
330
331      case DBUS_TYPE_INT16:
332       {
333         gint16 value;
334         dbus_message_iter_get_basic (iter, &value);
335         g_string_append_printf (s, "int16: %" G_GINT16_FORMAT "\n", value);
336         break;
337       }
338
339      case DBUS_TYPE_UINT16:
340       {
341         guint16 value;
342         dbus_message_iter_get_basic (iter, &value);
343         g_string_append_printf (s, "uint16: %" G_GUINT16_FORMAT "\n", value);
344         break;
345       }
346
347      case DBUS_TYPE_INT32:
348       {
349         gint32 value;
350         dbus_message_iter_get_basic (iter, &value);
351         g_string_append_printf (s, "int32: %" G_GINT32_FORMAT "\n", value);
352         break;
353       }
354
355      case DBUS_TYPE_UINT32:
356       {
357         guint32 value;
358         dbus_message_iter_get_basic (iter, &value);
359         g_string_append_printf (s, "uint32: %" G_GUINT32_FORMAT "\n", value);
360         break;
361       }
362
363      case DBUS_TYPE_INT64:
364       {
365         gint64 value;
366         dbus_message_iter_get_basic (iter, &value);
367         g_string_append_printf (s, "int64: %" G_GINT64_FORMAT "\n", value);
368         break;
369       }
370
371      case DBUS_TYPE_UINT64:
372       {
373         guint64 value;
374         dbus_message_iter_get_basic (iter, &value);
375         g_string_append_printf (s, "uint64: %" G_GUINT64_FORMAT "\n", value);
376         break;
377       }
378
379      case DBUS_TYPE_DOUBLE:
380       {
381         gdouble value;
382         dbus_message_iter_get_basic (iter, &value);
383         g_string_append_printf (s, "double: %f\n", value);
384         break;
385       }
386
387      case DBUS_TYPE_STRING:
388       {
389         const gchar *value;
390         dbus_message_iter_get_basic (iter, &value);
391         g_string_append_printf (s, "string: '%s'\n", value);
392         break;
393       }
394
395      case DBUS_TYPE_OBJECT_PATH:
396       {
397         const gchar *value;
398         dbus_message_iter_get_basic (iter, &value);
399         g_string_append_printf (s, "object_path: '%s'\n", value);
400         break;
401       }
402
403      case DBUS_TYPE_SIGNATURE:
404       {
405         const gchar *value;
406         dbus_message_iter_get_basic (iter, &value);
407         g_string_append_printf (s, "signature: '%s'\n", value);
408         break;
409       }
410
411 #ifdef DBUS_TYPE_UNIX_FD
412     case DBUS_TYPE_UNIX_FD:
413       {
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...
417          */
418         g_string_append (s, "unix-fd: (not extracted)\n");
419         break;
420       }
421 #endif
422
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))
427          {
428            dbus_1_message_append (s, indent + 2, &sub);
429            dbus_message_iter_next (&sub);
430          }
431        break;
432
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))
437          {
438            dbus_1_message_append (s, indent + 2, &sub);
439            dbus_message_iter_next (&sub);
440          }
441        break;
442
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))
447          {
448            dbus_1_message_append (s, indent + 2, &sub);
449            dbus_message_iter_next (&sub);
450          }
451        break;
452
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))
457          {
458            dbus_1_message_append (s, indent + 2, &sub);
459            dbus_message_iter_next (&sub);
460          }
461        break;
462
463      default:
464        g_printerr ("Error serializing D-Bus message to GVariant. Unsupported arg type '%c' (%d)",
465                    arg_type,
466                    arg_type);
467        g_assert_not_reached ();
468        break;
469     }
470 }
471
472 static gchar *
473 dbus_1_message_print (DBusMessage *message)
474 {
475   GString *s;
476   guint n;
477   DBusMessageIter iter;
478
479   s = g_string_new (NULL);
480   n = 0;
481   dbus_message_iter_init (message, &iter);
482   while (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID)
483     {
484       g_string_append_printf (s, "value %d: ", n);
485       dbus_1_message_append (s, 2, &iter);
486       dbus_message_iter_next (&iter);
487       n++;
488     }
489
490   return g_string_free (s, FALSE);
491 }
492
493 /* ---------------------------------------------------------------------------------------------------- */
494
495 static gchar *
496 get_body_signature (GVariant *value)
497 {
498   const gchar *s;
499   gsize len;
500   gchar *ret;
501
502   if (value == NULL)
503     {
504       ret = g_strdup ("");
505       goto out;
506     }
507
508   s = g_variant_get_type_string (value);
509   len = strlen (s);
510   g_assert (len >= 2);
511
512   ret = g_strndup (s + 1, len - 2);
513
514  out:
515   return ret;
516 }
517
518 /* If @value is floating, this assumes ownership. */
519 static gchar *
520 get_and_check_serialization (GVariant *value)
521 {
522   guchar *blob;
523   gsize blob_size;
524   DBusMessage *dbus_1_message;
525   GDBusMessage *message;
526   GDBusMessage *recovered_message;
527   GError *error;
528   DBusError dbus_error;
529   gchar *last_serialization = NULL;
530   gchar *s = NULL;
531   guint n;
532
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));
541   g_free (s);
542
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++)
545     {
546       GDBusMessageByteOrder byte_order;
547       switch (n)
548         {
549         case 0:
550           byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
551           break;
552         case 1:
553           byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
554           break;
555         case 2:
556           g_assert_not_reached ();
557           break;
558         }
559       g_dbus_message_set_byte_order (message, byte_order);
560
561       error = NULL;
562       blob = g_dbus_message_to_blob (message,
563                                      &blob_size,
564                                      G_DBUS_CAPABILITY_FLAGS_NONE,
565                                      &error);
566       g_assert_no_error (error);
567       g_assert (blob != NULL);
568
569       switch (byte_order)
570         {
571         case G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN:
572           g_assert_cmpint (blob[0], ==, 'B');
573           break;
574         case G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN:
575           g_assert_cmpint (blob[0], ==, 'l');
576           break;
577         }
578
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))
582         {
583           g_printerr ("Error calling dbus_message_demarshal() on this blob: %s: %s\n",
584                       dbus_error.name,
585                       dbus_error.message);
586           hexdump (blob, blob_size);
587           dbus_error_free (&dbus_error);
588
589           s = g_variant_print (value, TRUE);
590           g_printerr ("\nThe blob was generated from the following GVariant value:\n%s\n\n", s);
591           g_free (s);
592
593           g_printerr ("If the blob was encoded using DBusMessageIter, the payload would have been:\n");
594           print_gv_dbus_message (value);
595
596           g_assert_not_reached ();
597         }
598
599       s = dbus_1_message_print (dbus_1_message);
600       dbus_message_unref (dbus_1_message);
601
602       /* Then serialize back and check that the body is identical */
603
604       error = NULL;
605       recovered_message = g_dbus_message_new_from_blob (blob,
606                                                         blob_size,
607                                                         G_DBUS_CAPABILITY_FLAGS_NONE,
608                                                         &error);
609       g_assert_no_error (error);
610       g_assert (recovered_message != NULL);
611
612       if (value == NULL)
613         {
614           g_assert (g_dbus_message_get_body (recovered_message) == NULL);
615         }
616       else
617         {
618           g_assert (g_dbus_message_get_body (recovered_message) != NULL);
619           g_assert_cmpvariant (g_dbus_message_get_body (recovered_message), value);
620         }
621       g_object_unref (recovered_message);
622       g_free (blob);
623
624       if (last_serialization != NULL)
625         {
626           g_assert_cmpstr (last_serialization, ==, s);
627           g_free (last_serialization);
628         }
629
630       last_serialization = g_steal_pointer (&s);
631     }
632
633   g_object_unref (message);
634
635   return g_steal_pointer (&last_serialization);
636 }
637
638 /* If @value is floating, this assumes ownership. */
639 static void
640 check_serialization (GVariant *value,
641                      const gchar *expected_dbus_1_output)
642 {
643   gchar *s = get_and_check_serialization (value);
644   g_assert_cmpstr (s, ==, expected_dbus_1_output);
645   g_free (s);
646 }
647
648 static void
649 test_message_serialize_basic (void)
650 {
651   check_serialization (NULL, "");
652
653   check_serialization (g_variant_new ("(sogybnqiuxtd)",
654                                       "this is a string",
655                                       "/this/is/a/path",
656                                       "sad",
657                                       42,
658                                       TRUE,
659                                       -42,
660                                       60000,
661                                       -44,
662                                       100000,
663                                       -(G_GUINT64_CONSTANT(2)<<34),
664                                       G_GUINT64_CONSTANT(0xffffffffffffffff),
665                                       42.5),
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");
678 }
679
680 /* ---------------------------------------------------------------------------------------------------- */
681
682 static void
683 test_message_serialize_complex (void)
684 {
685   GError *error;
686   GVariant *value;
687   guint i;
688   gchar *serialization = NULL;
689
690   error = NULL;
691
692   value = g_variant_parse (G_VARIANT_TYPE ("(aia{ss})"),
693                            "([1, 2, 3], {'one': 'white', 'two': 'black'})",
694                            NULL, NULL, &error);
695   g_assert_no_error (error);
696   g_assert (value != NULL);
697   check_serialization (value,
698                        "value 0:   array:\n"
699                        "    int32: 1\n"
700                        "    int32: 2\n"
701                        "    int32: 3\n"
702                        "value 1:   array:\n"
703                        "    dict_entry:\n"
704                        "      string: 'one'\n"
705                        "      string: 'white'\n"
706                        "    dict_entry:\n"
707                        "      string: 'two'\n"
708                        "      string: 'black'\n");
709   g_variant_unref (value);
710
711   value = g_variant_parse (G_VARIANT_TYPE ("(sa{sv}as)"),
712                            "('01234567890123456', {}, ['Something'])",
713                            NULL, NULL, &error);
714   g_assert_no_error (error);
715   g_assert (value != NULL);
716   check_serialization (value,
717                        "value 0:   string: '01234567890123456'\n"
718                        "value 1:   array:\n"
719                        "value 2:   array:\n"
720                        "    string: 'Something'\n");
721   g_variant_unref (value);
722
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'>})"),
725                        "value 0:   array:\n"
726                        "value 1:   array:\n"
727                        "    dict_entry:\n"
728                        "      string: 'cwd'\n"
729                        "      variant:\n"
730                        "        string: '/home/davidz/Hacking/glib/gio/tests'\n");
731
732 #ifdef DBUS_TYPE_UNIX_FD
733   value = g_variant_parse (G_VARIANT_TYPE ("(hah)"),
734                            "(42, [43, 44])",
735                            NULL, NULL, &error);
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.
740    */
741   check_serialization (value,
742                        "value 0:   unix-fd: (not extracted)\n"
743                        "value 1:   array:\n"
744                        "    unix-fd: (not extracted)\n"
745                        "    unix-fd: (not extracted)\n");
746   g_variant_unref (value);
747 #endif
748
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);
754
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"
759                                    "    variant:\n"
760                                    "      variant:\n"));
761   g_free (serialization);
762
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);
771
772   serialization = get_and_check_serialization (value);
773   g_assert_nonnull (serialization);
774   g_assert_true (g_str_has_prefix (serialization,
775                                    "value 0:   array:\n"
776                                    "    array:\n"
777                                    "      array:\n"));
778   g_free (serialization);
779 }
780
781
782 /* ---------------------------------------------------------------------------------------------------- */
783
784 static void
785 replace (char       *blob,
786          gsize       len,
787          const char *before,
788          const char *after)
789 {
790   gsize i;
791   gsize slen = strlen (before) + 1;
792
793   g_assert_cmpuint (strlen (before), ==, strlen (after));
794   g_assert_cmpuint (len, >=, slen);
795
796   for (i = 0; i < (len - slen + 1); i++)
797     {
798       if (memcmp (blob + i, before, slen) == 0)
799         memcpy (blob + i, after, slen);
800     }
801 }
802
803 static void
804 test_message_serialize_invalid (void)
805 {
806   guint n;
807
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)
810    *
811    *  - array exceeding 64 MiB (2^26 bytes) - unfortunately libdbus-1 checks
812    *    this, e.g.
813    *
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)
820    *
821    *  - message exceeding 128 MiB (2^27 bytes)
822    *
823    *  - endianness, message type, flags, protocol version
824    */
825
826   for (n = 0; n < 3; n++)
827     {
828       GDBusMessage *message;
829       GError *error;
830       DBusMessage *dbus_message;
831       char *blob;
832       int blob_len;
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!";
840
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");
845       switch (n)
846         {
847         case 0:
848           /* invalid UTF-8 */
849           dbus_message_append_args (dbus_message,
850                                     DBUS_TYPE_STRING, &valid_utf8_str,
851                                     DBUS_TYPE_INVALID);
852           break;
853
854         case 1:
855           /* invalid object path */
856           dbus_message_append_args (dbus_message,
857                                     DBUS_TYPE_OBJECT_PATH, &valid_object_path,
858                                     DBUS_TYPE_INVALID);
859           break;
860
861         case 2:
862           /* invalid signature */
863           dbus_message_append_args (dbus_message,
864                                     DBUS_TYPE_SIGNATURE, &valid_signature,
865                                     DBUS_TYPE_INVALID);
866           break;
867
868         default:
869           g_assert_not_reached ();
870           break;
871         }
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);
878
879       error = NULL;
880       message = g_dbus_message_new_from_blob ((guchar *) blob,
881                                               blob_len,
882                                               G_DBUS_CAPABILITY_FLAGS_NONE,
883                                               &error);
884       g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
885       g_error_free (error);
886       g_assert (message == NULL);
887
888       dbus_free (blob);
889       dbus_message_unref (dbus_message);
890     }
891
892 }
893
894 /* ---------------------------------------------------------------------------------------------------- */
895
896 static void
897 test_message_serialize_header_checks (void)
898 {
899   GDBusMessage *message;
900   GDBusMessage *reply;
901   GError *error = NULL;
902   guchar *blob;
903   gsize blob_size;
904
905   /*
906    * check we can't serialize messages with INVALID type
907    */
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);
915
916   /*
917    * check that we can't serialize messages with SIGNATURE set to a non-signature-typed value
918    */
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);
922
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);
926
927   g_clear_error (&error);
928   g_clear_object (&message);
929
930   /*
931    * check we can't serialize signal messages with INTERFACE, PATH or MEMBER unset / set to reserved value
932    */
933   message = g_dbus_message_new_signal ("/the/path", "The.Interface", "TheMember");
934   /* ----- */
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");
951   /* ----- */
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);
966   /* reset path */
967   g_dbus_message_set_path (message, "/the/path");
968   /* ----- */
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);
976   /* reset member */
977   g_dbus_message_set_member (message, "TheMember");
978   /* ----- */
979   /* done */
980   g_object_unref (message);
981
982   /*
983    * check that we can't serialize method call messages with PATH or MEMBER unset
984    */
985   message = g_dbus_message_new_method_call (NULL, "/the/path", NULL, "TheMember");
986   /* ----- */
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);
994   /* reset path */
995   g_dbus_message_set_path (message, "/the/path");
996   /* ----- */
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);
1004   /* reset member */
1005   g_dbus_message_set_member (message, "TheMember");
1006   /* ----- */
1007   /* done */
1008   g_object_unref (message);
1009
1010   /*
1011    * check that we can't serialize method reply messages with REPLY_SERIAL unset
1012    */
1013   message = g_dbus_message_new_method_call (NULL, "/the/path", NULL, "TheMember");
1014   g_dbus_message_set_serial (message, 42);
1015   /* method reply */
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);
1046 }
1047
1048 /* ---------------------------------------------------------------------------------------------------- */
1049
1050 static void
1051 test_message_parse_empty_arrays_of_arrays (void)
1052 {
1053   GVariant *body;
1054   GError *error = NULL;
1055
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
1060    * dict_entry).
1061    */
1062   body = g_variant_parse (G_VARIANT_TYPE ("(aaax)"),
1063       "([@aax [], [], []],)", NULL, NULL, &error);
1064   g_assert_no_error (error);
1065   check_serialization (body,
1066       "value 0:   array:\n"
1067       "    array:\n"
1068       "    array:\n"
1069       "    array:\n");
1070   g_variant_unref (body);
1071
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,
1076       "value 0:   array:\n"
1077       "    array:\n"
1078       "    array:\n"
1079       "    array:\n");
1080   g_variant_unref (body);
1081
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))"),
1086       "([ ([], []),"
1087       "   ([], []),"
1088       "   ([], [])],)", NULL, NULL, &error);
1089   g_assert_no_error (error);
1090   check_serialization (body,
1091       "value 0:   array:\n"
1092       "    struct:\n"
1093       "      array:\n"
1094       "      array:\n"
1095       "    struct:\n"
1096       "      array:\n"
1097       "      array:\n"
1098       "    struct:\n"
1099       "      array:\n"
1100       "      array:\n");
1101   g_variant_unref (body);
1102 }
1103
1104 /* ---------------------------------------------------------------------------------------------------- */
1105
1106 static void
1107 test_message_serialize_double_array (void)
1108 {
1109   GVariantBuilder builder;
1110   GVariant *body;
1111
1112   g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=732754");
1113
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,
1121       "value 0:   array:\n"
1122       "    double: 0.000000\n"
1123       "    double: 8.000000\n"
1124       "    double: 22.000000\n"
1125       "    double: 0.000000\n");
1126 }
1127
1128 /* ---------------------------------------------------------------------------------------------------- */
1129
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. */
1133 static void
1134 test_message_parse_non_signature_header (void)
1135 {
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
1153        * be 8-aligned: */
1154       0x00,
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) */
1163   };
1164   gsize size = sizeof (data);
1165   GDBusMessage *message = NULL;
1166   GError *local_error = NULL;
1167
1168   message = g_dbus_message_new_from_blob ((guchar *) data, size,
1169                                           G_DBUS_CAPABILITY_FLAGS_NONE,
1170                                           &local_error);
1171   g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1172   g_assert_null (message);
1173
1174   g_clear_error (&local_error);
1175 }
1176
1177 /* ---------------------------------------------------------------------------------------------------- */
1178
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. */
1182 static void
1183 test_message_parse_empty_signature_header (void)
1184 {
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
1201        * be 8-aligned: */
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) */
1211   };
1212   gsize size = sizeof (data);
1213   GDBusMessage *message = NULL;
1214   GError *local_error = NULL;
1215
1216   message = g_dbus_message_new_from_blob ((guchar *) data, size,
1217                                           G_DBUS_CAPABILITY_FLAGS_NONE,
1218                                           &local_error);
1219   g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1220   g_assert_null (message);
1221
1222   g_clear_error (&local_error);
1223 }
1224
1225 /* ---------------------------------------------------------------------------------------------------- */
1226
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. */
1230 static void
1231 test_message_parse_multiple_signature_header (void)
1232 {
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
1250        * be 8-aligned: */
1251       0x00, 0x00, 0x00,
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) */
1260   };
1261   gsize size = sizeof (data);
1262   GDBusMessage *message = NULL;
1263   GError *local_error = NULL;
1264
1265   message = g_dbus_message_new_from_blob ((guchar *) data, size,
1266                                           G_DBUS_CAPABILITY_FLAGS_NONE,
1267                                           &local_error);
1268   g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1269   g_assert_null (message);
1270
1271   g_clear_error (&local_error);
1272 }
1273
1274 /* ---------------------------------------------------------------------------------------------------- */
1275
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. */
1280 static void
1281 test_message_parse_over_long_signature_header (void)
1282 {
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. */
1301       0xec,
1302       'a', 'b', 'g', 'd', 'u', 'd', 'd', 'd', 'd', 'd', 'd', 'd',
1303       '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',
1315       'v',
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) */
1325   };
1326   gsize size = sizeof (data);
1327   GDBusMessage *message = NULL;
1328   GError *local_error = NULL;
1329
1330   message = g_dbus_message_new_from_blob ((guchar *) data, size,
1331                                           G_DBUS_CAPABILITY_FLAGS_NONE,
1332                                           &local_error);
1333   g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1334   g_assert_null (message);
1335
1336   g_clear_error (&local_error);
1337 }
1338
1339 /* ---------------------------------------------------------------------------------------------------- */
1340
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
1343  * than a crash. */
1344 static void
1345 test_message_parse_deep_header_nesting (void)
1346 {
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) */
1393   };
1394   gsize size = sizeof (data);
1395   GDBusMessage *message = NULL;
1396   GError *local_error = NULL;
1397
1398   message = g_dbus_message_new_from_blob ((guchar *) data, size,
1399                                           G_DBUS_CAPABILITY_FLAGS_NONE,
1400                                           &local_error);
1401   g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1402   g_assert_null (message);
1403
1404   g_clear_error (&local_error);
1405 }
1406
1407 /* ---------------------------------------------------------------------------------------------------- */
1408
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(). */
1413 static void
1414 test_message_parse_deep_body_nesting (void)
1415 {
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) */
1431       0x01, 'v', 0x00,
1432       /* alignment padding before the next header array element, as structs must
1433        * be 8-aligned: */
1434       0x00,
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,
1461   };
1462   gsize size = sizeof (data);
1463   GDBusMessage *message = NULL;
1464   GError *local_error = NULL;
1465
1466   message = g_dbus_message_new_from_blob ((guchar *) data, size,
1467                                           G_DBUS_CAPABILITY_FLAGS_NONE,
1468                                           &local_error);
1469   g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1470   g_assert_null (message);
1471
1472   g_clear_error (&local_error);
1473 }
1474
1475 /* ---------------------------------------------------------------------------------------------------- */
1476
1477 static void
1478 test_message_parse_truncated (void)
1479 {
1480   GDBusMessage *message = NULL;
1481   GDBusMessage *message2 = NULL;
1482   GVariantBuilder builder;
1483   guchar *blob = NULL;
1484   gsize size = 0;
1485   GError *error = NULL;
1486
1487   g_test_summary ("Test that truncated messages are properly rejected.");
1488   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2528");
1489
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);
1504
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));
1511
1512   blob = g_dbus_message_to_blob (message, &size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1513   g_assert_no_error (error);
1514
1515   g_clear_object (&message);
1516
1517   /* Try parsing all possible prefixes of the full @blob. */
1518   for (gsize i = 0; i < size; i++)
1519     {
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);
1524     }
1525
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);
1530
1531   g_free (blob);
1532 }
1533
1534 static void
1535 test_message_parse_empty_structure (void)
1536 {
1537   const guint8 data[] =
1538     {
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 */
1568         0x00
1569     };
1570   gsize size = sizeof (data);
1571   GDBusMessage *message = NULL;
1572   GError *local_error = NULL;
1573
1574   g_test_summary ("Test that empty structures are rejected when parsing.");
1575   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2557");
1576
1577   message = g_dbus_message_new_from_blob ((guchar *) data, size,
1578                                           G_DBUS_CAPABILITY_FLAGS_NONE,
1579                                           &local_error);
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);
1583
1584   g_clear_error (&local_error);
1585 }
1586
1587 static void
1588 test_message_serialize_empty_structure (void)
1589 {
1590   GDBusMessage *message;
1591   GVariantBuilder builder;
1592   gsize size = 0;
1593   GError *local_error = NULL;
1594
1595   g_test_summary ("Test that empty structures are rejected when serializing.");
1596   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2557");
1597
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));
1609
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");
1613
1614   g_clear_error (&local_error);
1615   g_clear_object (&message);
1616 }
1617
1618 static void
1619 test_message_parse_missing_header (void)
1620 {
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
1660   };
1661
1662   gsize size = sizeof (data);
1663   GDBusMessage *message = NULL;
1664   GError *local_error = NULL;
1665
1666   g_test_summary ("Test that missing (required) headers prompt an error.");
1667   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3061");
1668
1669   message = g_dbus_message_new_from_blob ((guchar *) data, size,
1670                                           G_DBUS_CAPABILITY_FLAGS_NONE,
1671                                           &local_error);
1672   g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1673   g_assert_null (message);
1674
1675   g_clear_error (&local_error);
1676 }
1677
1678 static void
1679 test_message_parse_invalid_header_type (void)
1680 {
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
1721   };
1722
1723   gsize size = sizeof (data);
1724   GDBusMessage *message = NULL;
1725   GError *local_error = NULL;
1726
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");
1729
1730   message = g_dbus_message_new_from_blob ((guchar *) data, size,
1731                                           G_DBUS_CAPABILITY_FLAGS_NONE,
1732                                           &local_error);
1733   g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1734   g_assert_null (message);
1735
1736   g_clear_error (&local_error);
1737 }
1738
1739 /* ---------------------------------------------------------------------------------------------------- */
1740
1741 int
1742 main (int   argc,
1743       char *argv[])
1744 {
1745   g_setenv ("LC_ALL", "C", TRUE);
1746   setlocale (LC_ALL, "C");
1747
1748   g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
1749
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);
1762
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);
1785
1786   return g_test_run();
1787 }