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 }