Branch data Line data Source code
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 : 0 : hexdump (const guchar *str, gsize len)
36 : : {
37 : 0 : const guchar *data = (const guchar *) str;
38 : : guint n, m;
39 : :
40 : 0 : for (n = 0; n < len; n += 16)
41 : : {
42 : 0 : g_printerr ("%04x: ", n);
43 : :
44 : 0 : for (m = n; m < n + 16; m++)
45 : : {
46 : 0 : if (m > n && (m%4) == 0)
47 : 0 : g_printerr (" ");
48 : 0 : if (m < len)
49 : 0 : g_printerr ("%02x ", data[m]);
50 : : else
51 : 0 : g_printerr (" ");
52 : : }
53 : :
54 : 0 : g_printerr (" ");
55 : :
56 : 0 : for (m = n; m < len && m < n + 16; m++)
57 : 0 : g_printerr ("%c", g_ascii_isprint (data[m]) ? data[m] : '.');
58 : :
59 : 0 : g_printerr ("\n");
60 : : }
61 : 0 : }
62 : :
63 : : /* ---------------------------------------------------------------------------------------------------- */
64 : :
65 : : static gboolean
66 : 0 : append_gv_to_dbus_iter (DBusMessageIter *iter,
67 : : GVariant *value,
68 : : GError **error)
69 : : {
70 : : const GVariantType *type;
71 : :
72 : 0 : type = g_variant_get_type (value);
73 : 0 : if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
74 : : {
75 : 0 : dbus_bool_t v = g_variant_get_boolean (value);
76 : 0 : dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &v);
77 : : }
78 : 0 : else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
79 : : {
80 : 0 : guint8 v = g_variant_get_byte (value);
81 : 0 : dbus_message_iter_append_basic (iter, DBUS_TYPE_BYTE, &v);
82 : : }
83 : 0 : else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
84 : : {
85 : 0 : gint16 v = g_variant_get_int16 (value);
86 : 0 : dbus_message_iter_append_basic (iter, DBUS_TYPE_INT16, &v);
87 : : }
88 : 0 : else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
89 : : {
90 : 0 : guint16 v = g_variant_get_uint16 (value);
91 : 0 : dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT16, &v);
92 : : }
93 : 0 : else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
94 : : {
95 : 0 : gint32 v = g_variant_get_int32 (value);
96 : 0 : dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &v);
97 : : }
98 : 0 : else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
99 : : {
100 : 0 : guint32 v = g_variant_get_uint32 (value);
101 : 0 : dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &v);
102 : : }
103 : 0 : else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
104 : : {
105 : 0 : gint64 v = g_variant_get_int64 (value);
106 : 0 : dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &v);
107 : : }
108 : 0 : else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
109 : : {
110 : 0 : guint64 v = g_variant_get_uint64 (value);
111 : 0 : dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &v);
112 : : }
113 : 0 : else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
114 : : {
115 : 0 : gdouble v = g_variant_get_double (value);
116 : 0 : dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &v);
117 : : }
118 : 0 : else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
119 : : {
120 : 0 : const gchar *v = g_variant_get_string (value, NULL);
121 : 0 : dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &v);
122 : : }
123 : 0 : else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
124 : : {
125 : 0 : const gchar *v = g_variant_get_string (value, NULL);
126 : 0 : dbus_message_iter_append_basic (iter, DBUS_TYPE_OBJECT_PATH, &v);
127 : : }
128 : 0 : else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
129 : : {
130 : 0 : const gchar *v = g_variant_get_string (value, NULL);
131 : 0 : dbus_message_iter_append_basic (iter, DBUS_TYPE_SIGNATURE, &v);
132 : : }
133 : 0 : else if (g_variant_type_is_variant (type))
134 : : {
135 : : DBusMessageIter sub;
136 : : GVariant *child;
137 : :
138 : 0 : child = g_variant_get_child_value (value, 0);
139 : 0 : dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT,
140 : 0 : g_variant_get_type_string (child),
141 : : &sub);
142 : 0 : if (!append_gv_to_dbus_iter (&sub, child, error))
143 : : {
144 : 0 : g_variant_unref (child);
145 : 0 : goto fail;
146 : : }
147 : 0 : dbus_message_iter_close_container (iter, &sub);
148 : 0 : g_variant_unref (child);
149 : : }
150 : 0 : 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 : 0 : type_string = g_variant_get_type_string (value);
158 : 0 : type_string++; /* skip the 'a' */
159 : :
160 : 0 : dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY,
161 : : type_string, &dbus_iter);
162 : 0 : g_variant_iter_init (&gv_iter, value);
163 : :
164 : 0 : while ((item = g_variant_iter_next_value (&gv_iter)))
165 : : {
166 : 0 : if (!append_gv_to_dbus_iter (&dbus_iter, item, error))
167 : : {
168 : 0 : goto fail;
169 : : }
170 : : }
171 : :
172 : 0 : dbus_message_iter_close_container (iter, &dbus_iter);
173 : : }
174 : 0 : else if (g_variant_type_is_tuple (type))
175 : : {
176 : : DBusMessageIter dbus_iter;
177 : : GVariantIter gv_iter;
178 : : GVariant *item;
179 : :
180 : 0 : dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT,
181 : : NULL, &dbus_iter);
182 : 0 : g_variant_iter_init (&gv_iter, value);
183 : :
184 : 0 : while ((item = g_variant_iter_next_value (&gv_iter)))
185 : : {
186 : 0 : if (!append_gv_to_dbus_iter (&dbus_iter, item, error))
187 : 0 : goto fail;
188 : : }
189 : :
190 : 0 : dbus_message_iter_close_container (iter, &dbus_iter);
191 : : }
192 : 0 : else if (g_variant_type_is_dict_entry (type))
193 : : {
194 : : DBusMessageIter dbus_iter;
195 : : GVariant *key, *val;
196 : :
197 : 0 : dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY,
198 : : NULL, &dbus_iter);
199 : 0 : key = g_variant_get_child_value (value, 0);
200 : 0 : if (!append_gv_to_dbus_iter (&dbus_iter, key, error))
201 : : {
202 : 0 : g_variant_unref (key);
203 : 0 : goto fail;
204 : : }
205 : 0 : g_variant_unref (key);
206 : :
207 : 0 : val = g_variant_get_child_value (value, 1);
208 : 0 : if (!append_gv_to_dbus_iter (&dbus_iter, val, error))
209 : : {
210 : 0 : g_variant_unref (val);
211 : 0 : goto fail;
212 : : }
213 : 0 : g_variant_unref (val);
214 : :
215 : 0 : dbus_message_iter_close_container (iter, &dbus_iter);
216 : : }
217 : : else
218 : : {
219 : 0 : 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 : 0 : goto fail;
225 : : }
226 : :
227 : 0 : return TRUE;
228 : :
229 : 0 : fail:
230 : 0 : return FALSE;
231 : : }
232 : :
233 : : static gboolean
234 : 0 : append_gv_to_dbus_message (DBusMessage *message,
235 : : GVariant *value,
236 : : GError **error)
237 : : {
238 : : gboolean ret;
239 : : guint n;
240 : :
241 : 0 : ret = FALSE;
242 : :
243 : 0 : if (value != NULL)
244 : : {
245 : : DBusMessageIter iter;
246 : : GVariantIter gv_iter;
247 : : GVariant *item;
248 : :
249 : 0 : dbus_message_iter_init_append (message, &iter);
250 : :
251 : 0 : g_variant_iter_init (&gv_iter, value);
252 : 0 : n = 0;
253 : 0 : while ((item = g_variant_iter_next_value (&gv_iter)))
254 : : {
255 : 0 : if (!append_gv_to_dbus_iter (&iter, item, error))
256 : : {
257 : 0 : g_prefix_error (error,
258 : : "Error encoding in-arg %d: ",
259 : : n);
260 : 0 : goto out;
261 : : }
262 : 0 : n++;
263 : : }
264 : : }
265 : :
266 : 0 : ret = TRUE;
267 : :
268 : 0 : out:
269 : 0 : return ret;
270 : : }
271 : :
272 : : static void
273 : 0 : print_gv_dbus_message (GVariant *value)
274 : : {
275 : : DBusMessage *message;
276 : : char *blob;
277 : : int blob_len;
278 : : GError *error;
279 : :
280 : 0 : message = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
281 : 0 : dbus_message_set_serial (message, 0x41);
282 : 0 : dbus_message_set_path (message, "/foo/bar");
283 : 0 : dbus_message_set_member (message, "Member");
284 : :
285 : 0 : error = NULL;
286 : 0 : if (!append_gv_to_dbus_message (message, value, &error))
287 : : {
288 : 0 : g_printerr ("Error printing GVariant as DBusMessage: %s", error->message);
289 : 0 : g_error_free (error);
290 : 0 : goto out;
291 : : }
292 : :
293 : 0 : dbus_message_marshal (message, &blob, &blob_len);
294 : 0 : g_printerr ("\n");
295 : 0 : hexdump ((guchar *) blob, blob_len);
296 : 0 : out:
297 : 0 : dbus_message_unref (message);
298 : 0 : }
299 : :
300 : : /* ---------------------------------------------------------------------------------------------------- */
301 : :
302 : : static void
303 : 380 : dbus_1_message_append (GString *s,
304 : : guint indent,
305 : : DBusMessageIter *iter)
306 : : {
307 : : gint arg_type;
308 : : DBusMessageIter sub;
309 : :
310 : 380 : g_string_append_printf (s, "%*s", indent, "");
311 : :
312 : 380 : arg_type = dbus_message_iter_get_arg_type (iter);
313 : 380 : switch (arg_type)
314 : : {
315 : 2 : case DBUS_TYPE_BOOLEAN:
316 : : {
317 : : dbus_bool_t value;
318 : 2 : dbus_message_iter_get_basic (iter, &value);
319 : 2 : g_string_append_printf (s, "bool: %s\n", value ? "true" : "false");
320 : 2 : break;
321 : : }
322 : :
323 : 2 : case DBUS_TYPE_BYTE:
324 : : {
325 : : guchar value;
326 : 2 : dbus_message_iter_get_basic (iter, &value);
327 : 2 : g_string_append_printf (s, "byte: 0x%02x\n", (guint) value);
328 : 2 : break;
329 : : }
330 : :
331 : 2 : case DBUS_TYPE_INT16:
332 : : {
333 : : gint16 value;
334 : 2 : dbus_message_iter_get_basic (iter, &value);
335 : 2 : g_string_append_printf (s, "int16: %" G_GINT16_FORMAT "\n", value);
336 : 2 : break;
337 : : }
338 : :
339 : 2 : case DBUS_TYPE_UINT16:
340 : : {
341 : : guint16 value;
342 : 2 : dbus_message_iter_get_basic (iter, &value);
343 : 2 : g_string_append_printf (s, "uint16: %" G_GUINT16_FORMAT "\n", value);
344 : 2 : break;
345 : : }
346 : :
347 : 8 : case DBUS_TYPE_INT32:
348 : : {
349 : : gint32 value;
350 : 8 : dbus_message_iter_get_basic (iter, &value);
351 : 8 : g_string_append_printf (s, "int32: %" G_GINT32_FORMAT "\n", value);
352 : 8 : break;
353 : : }
354 : :
355 : 2 : case DBUS_TYPE_UINT32:
356 : : {
357 : : guint32 value;
358 : 2 : dbus_message_iter_get_basic (iter, &value);
359 : 2 : g_string_append_printf (s, "uint32: %" G_GUINT32_FORMAT "\n", value);
360 : 2 : break;
361 : : }
362 : :
363 : 2 : case DBUS_TYPE_INT64:
364 : : {
365 : : gint64 value;
366 : 2 : dbus_message_iter_get_basic (iter, &value);
367 : 2 : g_string_append_printf (s, "int64: %" G_GINT64_FORMAT "\n", value);
368 : 2 : break;
369 : : }
370 : :
371 : 2 : case DBUS_TYPE_UINT64:
372 : : {
373 : : guint64 value;
374 : 2 : dbus_message_iter_get_basic (iter, &value);
375 : 2 : g_string_append_printf (s, "uint64: %" G_GUINT64_FORMAT "\n", value);
376 : 2 : break;
377 : : }
378 : :
379 : 10 : case DBUS_TYPE_DOUBLE:
380 : : {
381 : : gdouble value;
382 : 10 : dbus_message_iter_get_basic (iter, &value);
383 : 10 : g_string_append_printf (s, "double: %f\n", value);
384 : 10 : break;
385 : : }
386 : :
387 : 22 : case DBUS_TYPE_STRING:
388 : : {
389 : : const gchar *value;
390 : 22 : dbus_message_iter_get_basic (iter, &value);
391 : 22 : g_string_append_printf (s, "string: '%s'\n", value);
392 : 22 : break;
393 : : }
394 : :
395 : 2 : case DBUS_TYPE_OBJECT_PATH:
396 : : {
397 : : const gchar *value;
398 : 2 : dbus_message_iter_get_basic (iter, &value);
399 : 2 : g_string_append_printf (s, "object_path: '%s'\n", value);
400 : 2 : break;
401 : : }
402 : :
403 : 2 : case DBUS_TYPE_SIGNATURE:
404 : : {
405 : : const gchar *value;
406 : 2 : dbus_message_iter_get_basic (iter, &value);
407 : 2 : g_string_append_printf (s, "signature: '%s'\n", value);
408 : 2 : break;
409 : : }
410 : :
411 : : #ifdef DBUS_TYPE_UNIX_FD
412 : 6 : 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 : 6 : g_string_append (s, "unix-fd: (not extracted)\n");
419 : 6 : break;
420 : : }
421 : : #endif
422 : :
423 : 130 : case DBUS_TYPE_VARIANT:
424 : 130 : g_string_append_printf (s, "variant:\n");
425 : 130 : dbus_message_iter_recurse (iter, &sub);
426 : 260 : while (dbus_message_iter_get_arg_type (&sub))
427 : : {
428 : 130 : dbus_1_message_append (s, indent + 2, &sub);
429 : 130 : dbus_message_iter_next (&sub);
430 : : }
431 : 130 : break;
432 : :
433 : 110 : case DBUS_TYPE_ARRAY:
434 : 110 : g_string_append_printf (s, "array:\n");
435 : 110 : dbus_message_iter_recurse (iter, &sub);
436 : 218 : while (dbus_message_iter_get_arg_type (&sub))
437 : : {
438 : 108 : dbus_1_message_append (s, indent + 2, &sub);
439 : 108 : dbus_message_iter_next (&sub);
440 : : }
441 : 110 : break;
442 : :
443 : 70 : case DBUS_TYPE_STRUCT:
444 : 70 : g_string_append_printf (s, "struct:\n");
445 : 70 : dbus_message_iter_recurse (iter, &sub);
446 : 146 : while (dbus_message_iter_get_arg_type (&sub))
447 : : {
448 : 76 : dbus_1_message_append (s, indent + 2, &sub);
449 : 76 : dbus_message_iter_next (&sub);
450 : : }
451 : 70 : break;
452 : :
453 : 6 : case DBUS_TYPE_DICT_ENTRY:
454 : 6 : g_string_append_printf (s, "dict_entry:\n");
455 : 6 : dbus_message_iter_recurse (iter, &sub);
456 : 18 : while (dbus_message_iter_get_arg_type (&sub))
457 : : {
458 : 12 : dbus_1_message_append (s, indent + 2, &sub);
459 : 12 : dbus_message_iter_next (&sub);
460 : : }
461 : 6 : break;
462 : :
463 : 0 : default:
464 : 0 : 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 : 380 : }
471 : :
472 : : static gchar *
473 : 24 : dbus_1_message_print (DBusMessage *message)
474 : : {
475 : : GString *s;
476 : : guint n;
477 : : DBusMessageIter iter;
478 : :
479 : 24 : s = g_string_new (NULL);
480 : 24 : n = 0;
481 : 24 : dbus_message_iter_init (message, &iter);
482 : 78 : while (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID)
483 : : {
484 : 54 : g_string_append_printf (s, "value %d: ", n);
485 : 54 : dbus_1_message_append (s, 2, &iter);
486 : 54 : dbus_message_iter_next (&iter);
487 : 54 : n++;
488 : : }
489 : :
490 : 24 : return g_string_free (s, FALSE);
491 : : }
492 : :
493 : : /* ---------------------------------------------------------------------------------------------------- */
494 : :
495 : : static gchar *
496 : 12 : get_body_signature (GVariant *value)
497 : : {
498 : : const gchar *s;
499 : : gsize len;
500 : : gchar *ret;
501 : :
502 : 12 : if (value == NULL)
503 : : {
504 : 1 : ret = g_strdup ("");
505 : 1 : goto out;
506 : : }
507 : :
508 : 11 : s = g_variant_get_type_string (value);
509 : 11 : len = strlen (s);
510 : 11 : g_assert (len >= 2);
511 : :
512 : 11 : ret = g_strndup (s + 1, len - 2);
513 : :
514 : 12 : out:
515 : 12 : return ret;
516 : : }
517 : :
518 : : /* If @value is floating, this assumes ownership. */
519 : : static gchar *
520 : 12 : 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 : 12 : gchar *last_serialization = NULL;
530 : 12 : gchar *s = NULL;
531 : : guint n;
532 : :
533 : 12 : message = g_dbus_message_new ();
534 : 12 : g_dbus_message_set_body (message, value);
535 : 12 : g_dbus_message_set_message_type (message, G_DBUS_MESSAGE_TYPE_METHOD_CALL);
536 : 12 : g_dbus_message_set_serial (message, 0x41);
537 : 12 : s = get_body_signature (value);
538 : 12 : g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, g_variant_new_object_path ("/foo/bar"));
539 : 12 : g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, g_variant_new_string ("Member"));
540 : 12 : g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, g_variant_new_signature (s));
541 : 12 : 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 : 36 : for (n = 0; n < 2; n++)
545 : : {
546 : 24 : GDBusMessageByteOrder byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
547 : 24 : switch (n)
548 : : {
549 : 12 : case 0:
550 : 12 : byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
551 : 12 : break;
552 : 12 : case 1:
553 : 12 : byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
554 : 12 : break;
555 : 0 : case 2:
556 : : g_assert_not_reached ();
557 : : break;
558 : : }
559 : 24 : g_dbus_message_set_byte_order (message, byte_order);
560 : :
561 : 24 : error = NULL;
562 : 24 : blob = g_dbus_message_to_blob (message,
563 : : &blob_size,
564 : : G_DBUS_CAPABILITY_FLAGS_NONE,
565 : : &error);
566 : 24 : g_assert_no_error (error);
567 : 24 : g_assert (blob != NULL);
568 : :
569 : 24 : switch (byte_order)
570 : : {
571 : 12 : case G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN:
572 : 12 : g_assert_cmpint (blob[0], ==, 'B');
573 : 12 : break;
574 : 12 : case G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN:
575 : 12 : g_assert_cmpint (blob[0], ==, 'l');
576 : 12 : break;
577 : : }
578 : :
579 : 24 : dbus_error_init (&dbus_error);
580 : 24 : dbus_1_message = dbus_message_demarshal ((char *) blob, blob_size, &dbus_error);
581 : 24 : if (dbus_error_is_set (&dbus_error))
582 : : {
583 : 0 : g_printerr ("Error calling dbus_message_demarshal() on this blob: %s: %s\n",
584 : : dbus_error.name,
585 : : dbus_error.message);
586 : 0 : hexdump (blob, blob_size);
587 : 0 : dbus_error_free (&dbus_error);
588 : :
589 : 0 : s = g_variant_print (value, TRUE);
590 : 0 : g_printerr ("\nThe blob was generated from the following GVariant value:\n%s\n\n", s);
591 : 0 : g_free (s);
592 : :
593 : 0 : g_printerr ("If the blob was encoded using DBusMessageIter, the payload would have been:\n");
594 : 0 : print_gv_dbus_message (value);
595 : :
596 : : g_assert_not_reached ();
597 : : }
598 : :
599 : 24 : s = dbus_1_message_print (dbus_1_message);
600 : 24 : dbus_message_unref (dbus_1_message);
601 : :
602 : : /* Then serialize back and check that the body is identical */
603 : :
604 : 24 : error = NULL;
605 : 24 : recovered_message = g_dbus_message_new_from_blob (blob,
606 : : blob_size,
607 : : G_DBUS_CAPABILITY_FLAGS_NONE,
608 : : &error);
609 : 24 : g_assert_no_error (error);
610 : 24 : g_assert (recovered_message != NULL);
611 : :
612 : 24 : if (value == NULL)
613 : : {
614 : 2 : g_assert (g_dbus_message_get_body (recovered_message) == NULL);
615 : : }
616 : : else
617 : : {
618 : 22 : g_assert (g_dbus_message_get_body (recovered_message) != NULL);
619 : 22 : g_assert_cmpvariant (g_dbus_message_get_body (recovered_message), value);
620 : : }
621 : 24 : g_object_unref (recovered_message);
622 : 24 : g_free (blob);
623 : :
624 : 24 : if (last_serialization != NULL)
625 : : {
626 : 12 : g_assert_cmpstr (last_serialization, ==, s);
627 : 12 : g_free (last_serialization);
628 : : }
629 : :
630 : 24 : last_serialization = g_steal_pointer (&s);
631 : : }
632 : :
633 : 12 : g_object_unref (message);
634 : :
635 : 12 : return g_steal_pointer (&last_serialization);
636 : : }
637 : :
638 : : /* If @value is floating, this assumes ownership. */
639 : : static void
640 : 10 : check_serialization (GVariant *value,
641 : : const gchar *expected_dbus_1_output)
642 : : {
643 : 10 : gchar *s = get_and_check_serialization (value);
644 : 10 : g_assert_cmpstr (s, ==, expected_dbus_1_output);
645 : 10 : g_free (s);
646 : 10 : }
647 : :
648 : : static void
649 : 1 : test_message_serialize_basic (void)
650 : : {
651 : 1 : check_serialization (NULL, "");
652 : :
653 : 1 : 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 : 1 : }
679 : :
680 : : /* ---------------------------------------------------------------------------------------------------- */
681 : :
682 : : static void
683 : 1 : test_message_serialize_complex (void)
684 : : {
685 : : GError *error;
686 : : GVariant *value;
687 : : guint i;
688 : 1 : gchar *serialization = NULL;
689 : :
690 : 1 : error = NULL;
691 : :
692 : 1 : value = g_variant_parse (G_VARIANT_TYPE ("(aia{ss})"),
693 : : "([1, 2, 3], {'one': 'white', 'two': 'black'})",
694 : : NULL, NULL, &error);
695 : 1 : g_assert_no_error (error);
696 : 1 : g_assert (value != NULL);
697 : 1 : 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 : 1 : g_variant_unref (value);
710 : :
711 : 1 : value = g_variant_parse (G_VARIANT_TYPE ("(sa{sv}as)"),
712 : : "('01234567890123456', {}, ['Something'])",
713 : : NULL, NULL, &error);
714 : 1 : g_assert_no_error (error);
715 : 1 : g_assert (value != NULL);
716 : 1 : check_serialization (value,
717 : : "value 0: string: '01234567890123456'\n"
718 : : "value 1: array:\n"
719 : : "value 2: array:\n"
720 : : " string: 'Something'\n");
721 : 1 : g_variant_unref (value);
722 : :
723 : : /* https://bugzilla.gnome.org/show_bug.cgi?id=621838 */
724 : 1 : 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 : 1 : value = g_variant_parse (G_VARIANT_TYPE ("(hah)"),
734 : : "(42, [43, 44])",
735 : : NULL, NULL, &error);
736 : 1 : g_assert_no_error (error);
737 : 1 : 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 : 1 : 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 : 1 : g_variant_unref (value);
747 : : #endif
748 : :
749 : : /* Deep nesting of variants (just below the recursion limit). */
750 : 1 : value = g_variant_new_string ("buried");
751 : 65 : for (i = 0; i < 64; i++)
752 : 64 : value = g_variant_new_variant (value);
753 : 1 : value = g_variant_new_tuple (&value, 1);
754 : :
755 : 1 : serialization = get_and_check_serialization (value);
756 : 1 : g_assert_nonnull (serialization);
757 : 1 : g_assert_true (g_str_has_prefix (serialization,
758 : : "value 0: variant:\n"
759 : : " variant:\n"
760 : : " variant:\n"));
761 : 1 : 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 : 1 : value = g_variant_new_string ("hello");
766 : 33 : for (i = 0; i < 32; i++)
767 : 32 : value = g_variant_new_tuple (&value, 1);
768 : 33 : for (i = 0; i < 32; i++)
769 : 32 : value = g_variant_new_array (NULL, &value, 1);
770 : 1 : value = g_variant_new_tuple (&value, 1);
771 : :
772 : 1 : serialization = get_and_check_serialization (value);
773 : 1 : g_assert_nonnull (serialization);
774 : 1 : g_assert_true (g_str_has_prefix (serialization,
775 : : "value 0: array:\n"
776 : : " array:\n"
777 : : " array:\n"));
778 : 1 : g_free (serialization);
779 : 1 : }
780 : :
781 : :
782 : : /* ---------------------------------------------------------------------------------------------------- */
783 : :
784 : : static void
785 : 9 : replace (char *blob,
786 : : gsize len,
787 : : const char *before,
788 : : const char *after)
789 : : {
790 : : gsize i;
791 : 9 : gsize slen = strlen (before) + 1;
792 : :
793 : 9 : g_assert_cmpuint (strlen (before), ==, strlen (after));
794 : 9 : g_assert_cmpuint (len, >=, slen);
795 : :
796 : 621 : for (i = 0; i < (len - slen + 1); i++)
797 : : {
798 : 612 : if (memcmp (blob + i, before, slen) == 0)
799 : 3 : memcpy (blob + i, after, slen);
800 : : }
801 : 9 : }
802 : :
803 : : static void
804 : 1 : 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 : 4 : 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 : 3 : const gchar *valid_utf8_str = "this is valid...";
835 : 3 : const gchar *invalid_utf8_str = "this is invalid\xff";
836 : 3 : const gchar *valid_signature = "a{sv}a{sv}a{sv}aiai";
837 : 3 : const gchar *invalid_signature = "not valid signature";
838 : 3 : const gchar *valid_object_path = "/this/is/a/valid/dbus/object/path";
839 : 3 : const gchar *invalid_object_path = "/this/is/not a valid object path!";
840 : :
841 : 3 : dbus_message = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
842 : 3 : dbus_message_set_serial (dbus_message, 0x41);
843 : 3 : dbus_message_set_path (dbus_message, "/foo/bar");
844 : 3 : dbus_message_set_member (dbus_message, "Member");
845 : 3 : switch (n)
846 : : {
847 : 1 : case 0:
848 : : /* invalid UTF-8 */
849 : 1 : dbus_message_append_args (dbus_message,
850 : : DBUS_TYPE_STRING, &valid_utf8_str,
851 : : DBUS_TYPE_INVALID);
852 : 1 : break;
853 : :
854 : 1 : case 1:
855 : : /* invalid object path */
856 : 1 : dbus_message_append_args (dbus_message,
857 : : DBUS_TYPE_OBJECT_PATH, &valid_object_path,
858 : : DBUS_TYPE_INVALID);
859 : 1 : break;
860 : :
861 : 1 : case 2:
862 : : /* invalid signature */
863 : 1 : dbus_message_append_args (dbus_message,
864 : : DBUS_TYPE_SIGNATURE, &valid_signature,
865 : : DBUS_TYPE_INVALID);
866 : 1 : break;
867 : :
868 : 0 : default:
869 : : g_assert_not_reached ();
870 : : break;
871 : : }
872 : 3 : 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 : 3 : replace (blob, blob_len, valid_utf8_str, invalid_utf8_str);
876 : 3 : replace (blob, blob_len, valid_object_path, invalid_object_path);
877 : 3 : replace (blob, blob_len, valid_signature, invalid_signature);
878 : :
879 : 3 : error = NULL;
880 : 3 : message = g_dbus_message_new_from_blob ((guchar *) blob,
881 : : blob_len,
882 : : G_DBUS_CAPABILITY_FLAGS_NONE,
883 : : &error);
884 : 3 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
885 : 3 : g_error_free (error);
886 : 3 : g_assert (message == NULL);
887 : :
888 : 3 : dbus_free (blob);
889 : 3 : dbus_message_unref (dbus_message);
890 : : }
891 : :
892 : 1 : }
893 : :
894 : : /* ---------------------------------------------------------------------------------------------------- */
895 : :
896 : : static void
897 : 1 : test_message_serialize_header_checks (void)
898 : : {
899 : : GDBusMessage *message;
900 : : GDBusMessage *reply;
901 : 1 : GError *error = NULL;
902 : : guchar *blob;
903 : : gsize blob_size;
904 : :
905 : : /*
906 : : * check we can't serialize messages with INVALID type
907 : : */
908 : 1 : message = g_dbus_message_new ();
909 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
910 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
911 : 1 : g_assert_cmpstr (error->message, ==, "Cannot serialize message: type is INVALID");
912 : 1 : g_clear_error (&error);
913 : 1 : g_assert_null (blob);
914 : 1 : g_object_unref (message);
915 : :
916 : : /*
917 : : * check we can't serialize messages with an INVALID header
918 : : */
919 : 1 : message = g_dbus_message_new_signal ("/the/path", "The.Interface", "TheMember");
920 : 1 : g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INVALID, g_variant_new_boolean (FALSE));
921 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
922 : :
923 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
924 : 1 : g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: INVALID header field supplied");
925 : 1 : g_assert_null (blob);
926 : :
927 : 1 : g_clear_error (&error);
928 : 1 : g_clear_object (&message);
929 : :
930 : : /*
931 : : * check that we can't serialize messages with various fields set to incorrectly typed values
932 : : */
933 : : const struct
934 : : {
935 : : GDBusMessageHeaderField field;
936 : : const char *invalid_value; /* as a GVariant in text form */
937 : : const char *expected_error_message;
938 : : }
939 : 1 : field_type_tests[] =
940 : : {
941 : : {
942 : : G_DBUS_MESSAGE_HEADER_FIELD_PATH,
943 : : "'/correct/value/but/wrong/type'",
944 : : "Cannot serialize message: SIGNAL message: PATH header field is invalid; expected a value of type ‘o’"
945 : : },
946 : : {
947 : : G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE,
948 : : "@u 5",
949 : : "Cannot serialize message: SIGNAL message: INTERFACE header field is invalid; expected a value of type ‘s’"
950 : : },
951 : : {
952 : : G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE,
953 : : "'valid type, but not an interface name'",
954 : : "Cannot serialize message: SIGNAL message: INTERFACE header field does not contain a valid interface name"
955 : : },
956 : : {
957 : : G_DBUS_MESSAGE_HEADER_FIELD_MEMBER,
958 : : "@u 5",
959 : : "Cannot serialize message: SIGNAL message: MEMBER header field is invalid; expected a value of type ‘s’"
960 : : },
961 : : {
962 : : G_DBUS_MESSAGE_HEADER_FIELD_MEMBER,
963 : : "'valid type, but not a member name'",
964 : : "Cannot serialize message: SIGNAL message: MEMBER header field does not contain a valid member name"
965 : : },
966 : : {
967 : : G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME,
968 : : "@u 5",
969 : : "Cannot serialize message: SIGNAL message: ERROR_NAME header field is invalid; expected a value of type ‘s’"
970 : : },
971 : : {
972 : : G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME,
973 : : "'valid type, but not an error name'",
974 : : "Cannot serialize message: SIGNAL message: ERROR_NAME header field does not contain a valid error name"
975 : : },
976 : : {
977 : : G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL,
978 : : "'oops'",
979 : : "Cannot serialize message: SIGNAL message: REPLY_SERIAL header field is invalid; expected a value of type ‘u’"
980 : : },
981 : : {
982 : : G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION,
983 : : "@u 5",
984 : : "Cannot serialize message: SIGNAL message: DESTINATION header field is invalid; expected a value of type ‘s’"
985 : : },
986 : : {
987 : : G_DBUS_MESSAGE_HEADER_FIELD_SENDER,
988 : : "@u 5",
989 : : "Cannot serialize message: SIGNAL message: SENDER header field is invalid; expected a value of type ‘s’"
990 : : },
991 : : {
992 : : G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE,
993 : : "false",
994 : : "Cannot serialize message: SIGNAL message: SIGNATURE header field is invalid; expected a value of type ‘g’"
995 : : },
996 : : {
997 : : G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS,
998 : : "'five'",
999 : : "Cannot serialize message: SIGNAL message: NUM_UNIX_FDS header field is invalid; expected a value of type ‘u’"
1000 : : },
1001 : : };
1002 : :
1003 : 13 : for (size_t i = 0; i < G_N_ELEMENTS (field_type_tests); i++)
1004 : : {
1005 : 12 : message = g_dbus_message_new_signal ("/the/path", "The.Interface", "TheMember");
1006 : 12 : g_dbus_message_set_header (message, field_type_tests[i].field, g_variant_new_parsed (field_type_tests[i].invalid_value));
1007 : 12 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1008 : :
1009 : 12 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1010 : 12 : g_assert_cmpstr (error->message, ==, field_type_tests[i].expected_error_message);
1011 : 12 : g_assert_null (blob);
1012 : :
1013 : 12 : g_clear_error (&error);
1014 : 12 : g_clear_object (&message);
1015 : : }
1016 : :
1017 : : /*
1018 : : * check we can't serialize signal messages with INTERFACE, PATH or MEMBER unset / set to reserved value
1019 : : */
1020 : 1 : message = g_dbus_message_new_signal ("/the/path", "The.Interface", "TheMember");
1021 : : /* ----- */
1022 : : /* interface NULL => error */
1023 : 1 : g_dbus_message_set_interface (message, NULL);
1024 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1025 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1026 : 1 : g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: INTERFACE header field is missing or invalid");
1027 : 1 : g_clear_error (&error);
1028 : 1 : g_assert_null (blob);
1029 : : /* interface reserved value => error */
1030 : 1 : g_dbus_message_set_interface (message, DBUS_INTERFACE_LOCAL);
1031 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1032 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1033 : 1 : g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: INTERFACE header field is using the reserved value " DBUS_INTERFACE_LOCAL);
1034 : 1 : g_clear_error (&error);
1035 : 1 : g_assert_null (blob);
1036 : : /* reset interface */
1037 : 1 : g_dbus_message_set_interface (message, "The.Interface");
1038 : : /* ----- */
1039 : : /* path NULL => error */
1040 : 1 : g_dbus_message_set_path (message, NULL);
1041 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1042 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1043 : 1 : g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: PATH header field is missing or invalid");
1044 : 1 : g_clear_error (&error);
1045 : 1 : g_assert_null (blob);
1046 : : /* path reserved value => error */
1047 : 1 : g_dbus_message_set_path (message, DBUS_PATH_LOCAL);
1048 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1049 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1050 : 1 : g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: PATH header field is using the reserved value " DBUS_PATH_LOCAL);
1051 : 1 : g_clear_error (&error);
1052 : 1 : g_assert_null (blob);
1053 : : /* reset path */
1054 : 1 : g_dbus_message_set_path (message, "/the/path");
1055 : : /* ----- */
1056 : : /* member NULL => error */
1057 : 1 : g_dbus_message_set_member (message, NULL);
1058 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1059 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1060 : 1 : g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: MEMBER header field is missing or invalid");
1061 : 1 : g_clear_error (&error);
1062 : 1 : g_assert_null (blob);
1063 : : /* reset member */
1064 : 1 : g_dbus_message_set_member (message, "TheMember");
1065 : : /* ----- */
1066 : : /* done */
1067 : 1 : g_object_unref (message);
1068 : :
1069 : : /*
1070 : : * check that we can't serialize method call messages with PATH or MEMBER unset
1071 : : */
1072 : 1 : message = g_dbus_message_new_method_call (NULL, "/the/path", NULL, "TheMember");
1073 : : /* ----- */
1074 : : /* path NULL => error */
1075 : 1 : g_dbus_message_set_path (message, NULL);
1076 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1077 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1078 : 1 : g_assert_cmpstr (error->message, ==, "Cannot serialize message: METHOD_CALL message: PATH header field is missing or invalid");
1079 : 1 : g_clear_error (&error);
1080 : 1 : g_assert_null (blob);
1081 : : /* reset path */
1082 : 1 : g_dbus_message_set_path (message, "/the/path");
1083 : : /* ----- */
1084 : : /* member NULL => error */
1085 : 1 : g_dbus_message_set_member (message, NULL);
1086 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1087 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1088 : 1 : g_assert_cmpstr (error->message, ==, "Cannot serialize message: METHOD_CALL message: MEMBER header field is missing or invalid");
1089 : 1 : g_clear_error (&error);
1090 : 1 : g_assert_null (blob);
1091 : : /* reset member */
1092 : 1 : g_dbus_message_set_member (message, "TheMember");
1093 : : /* ----- */
1094 : : /* done */
1095 : 1 : g_object_unref (message);
1096 : :
1097 : : /*
1098 : : * check that we can't serialize method reply messages with REPLY_SERIAL unset
1099 : : */
1100 : 1 : message = g_dbus_message_new_method_call (NULL, "/the/path", NULL, "TheMember");
1101 : 1 : g_dbus_message_set_serial (message, 42);
1102 : : /* method reply */
1103 : 1 : reply = g_dbus_message_new_method_reply (message);
1104 : 1 : g_assert_cmpint (g_dbus_message_get_reply_serial (reply), ==, 42);
1105 : 1 : g_dbus_message_set_header (reply, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, NULL);
1106 : 1 : blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1107 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1108 : 1 : g_assert_cmpstr (error->message, ==, "Cannot serialize message: METHOD_RETURN message: REPLY_SERIAL header field is missing or invalid");
1109 : 1 : g_clear_error (&error);
1110 : 1 : g_assert_null (blob);
1111 : 1 : g_object_unref (reply);
1112 : : /* method error - first nuke ERROR_NAME, then REPLY_SERIAL */
1113 : 1 : reply = g_dbus_message_new_method_error (message, "Some.Error.Name", "the message");
1114 : 1 : g_assert_cmpint (g_dbus_message_get_reply_serial (reply), ==, 42);
1115 : : /* nuke ERROR_NAME */
1116 : 1 : g_dbus_message_set_error_name (reply, NULL);
1117 : 1 : blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1118 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1119 : 1 : g_assert_cmpstr (error->message, ==, "Cannot serialize message: ERROR message: ERROR_NAME header field is missing or invalid");
1120 : 1 : g_clear_error (&error);
1121 : 1 : g_assert_null (blob);
1122 : : /* reset ERROR_NAME */
1123 : 1 : g_dbus_message_set_error_name (reply, "Some.Error.Name");
1124 : : /* nuke REPLY_SERIAL */
1125 : 1 : g_dbus_message_set_header (reply, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, NULL);
1126 : 1 : blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1127 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1128 : 1 : g_assert_cmpstr (error->message, ==, "Cannot serialize message: ERROR message: REPLY_SERIAL header field is missing or invalid");
1129 : 1 : g_clear_error (&error);
1130 : 1 : g_assert_null (blob);
1131 : 1 : g_object_unref (reply);
1132 : 1 : g_object_unref (message);
1133 : 1 : }
1134 : :
1135 : : static void
1136 : 1 : test_message_serialize_header_checks_valid (void)
1137 : : {
1138 : 1 : GDBusMessage *message = NULL, *reply = NULL;
1139 : 1 : GError *local_error = NULL;
1140 : : guchar *blob;
1141 : : gsize blob_size;
1142 : :
1143 : 1 : g_test_summary ("Test that validation allows well-formed messages of all the different types");
1144 : :
1145 : : /* Method call */
1146 : 1 : message = g_dbus_message_new_method_call ("Some.Name", "/the/path", "org.some.Interface", "TheMethod");
1147 : 1 : g_dbus_message_set_serial (message, 666);
1148 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &local_error);
1149 : 1 : g_assert_no_error (local_error);
1150 : 1 : g_assert_nonnull (blob);
1151 : 1 : g_free (blob);
1152 : :
1153 : : /* Method return */
1154 : 1 : reply = g_dbus_message_new_method_reply (message);
1155 : 1 : blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &local_error);
1156 : 1 : g_assert_no_error (local_error);
1157 : 1 : g_assert_nonnull (blob);
1158 : 1 : g_free (blob);
1159 : 1 : g_clear_object (&reply);
1160 : :
1161 : : /* Error */
1162 : 1 : reply = g_dbus_message_new_method_error (message, "Error.Name", "Some error message");
1163 : 1 : blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &local_error);
1164 : 1 : g_assert_no_error (local_error);
1165 : 1 : g_assert_nonnull (blob);
1166 : 1 : g_free (blob);
1167 : :
1168 : 1 : g_clear_object (&reply);
1169 : 1 : g_clear_object (&message);
1170 : :
1171 : : /* Signal */
1172 : 1 : message = g_dbus_message_new_signal ("/the/path", "org.some.Interface", "SignalName");
1173 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &local_error);
1174 : 1 : g_assert_no_error (local_error);
1175 : 1 : g_assert_nonnull (blob);
1176 : 1 : g_free (blob);
1177 : 1 : g_clear_object (&message);
1178 : :
1179 : : /* Also check that an unknown message type is allowed */
1180 : 1 : message = g_dbus_message_new ();
1181 : 1 : g_dbus_message_set_message_type (message, 123);
1182 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &local_error);
1183 : 1 : g_assert_no_error (local_error);
1184 : 1 : g_assert_nonnull (blob);
1185 : 1 : g_free (blob);
1186 : 1 : g_clear_object (&message);
1187 : :
1188 : : /* Even one with a well-defined field on it */
1189 : 1 : message = g_dbus_message_new ();
1190 : 1 : g_dbus_message_set_message_type (message, 123);
1191 : 1 : g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS, g_variant_new_uint32 (0));
1192 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &local_error);
1193 : 1 : g_assert_no_error (local_error);
1194 : 1 : g_assert_nonnull (blob);
1195 : 1 : g_free (blob);
1196 : 1 : g_clear_object (&message);
1197 : 1 : }
1198 : :
1199 : : static void
1200 : 1 : test_message_serialize_over_long_signature (void)
1201 : : {
1202 : 1 : GDBusMessage *message = NULL;
1203 : 1 : GError *error = NULL;
1204 : 1 : guchar *blob = NULL;
1205 : 1 : gsize blob_size = 0;
1206 : 1 : char *long_signature = NULL;
1207 : :
1208 : 1 : long_signature = g_strnfill (256, 'y');
1209 : :
1210 : 1 : message = g_dbus_message_new_signal ("/the/path", "The.Interface", "TheMember");
1211 : 1 : g_dbus_message_set_header (message,
1212 : : G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE,
1213 : : g_variant_new_signature (long_signature));
1214 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1215 : :
1216 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1217 : 1 : g_assert_cmpstr (error->message, ==,
1218 : : "Cannot serialize message: D-Bus signature exceeds maximum length of 255 bytes");
1219 : 1 : g_assert_null (blob);
1220 : :
1221 : 1 : g_clear_error (&error);
1222 : 1 : g_clear_object (&message);
1223 : :
1224 : 1 : message = g_dbus_message_new_signal ("/the/path", "The.Interface", "TheMember");
1225 : 1 : g_dbus_message_set_body (message, g_variant_new ("(g)", long_signature));
1226 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1227 : :
1228 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1229 : 1 : g_assert_cmpstr (error->message, ==,
1230 : : "D-Bus signature exceeds maximum length of 255 bytes");
1231 : 1 : g_assert_null (blob);
1232 : :
1233 : 1 : g_free (long_signature);
1234 : 1 : g_clear_error (&error);
1235 : 1 : g_clear_object (&message);
1236 : 1 : }
1237 : :
1238 : : static void
1239 : 1 : test_message_serialize_over_long_variant_signature (void)
1240 : : {
1241 : 1 : GDBusMessage *message = NULL;
1242 : 1 : GError *error = NULL;
1243 : 1 : GVariantType *long_tuple_type = NULL;
1244 : 1 : guchar *blob = NULL;
1245 : 1 : gsize blob_size = 0;
1246 : 1 : char *long_signature = NULL;
1247 : 1 : char *long_tuple_type_string = NULL;
1248 : 1 : guint8 *data = NULL;
1249 : :
1250 : 1 : long_signature = g_strnfill (256, 'y');
1251 : 1 : long_tuple_type_string = g_strdup_printf ("(%s)", long_signature);
1252 : 1 : long_tuple_type = g_variant_type_new (long_tuple_type_string);
1253 : 1 : data = g_malloc0 (256);
1254 : :
1255 : 1 : message = g_dbus_message_new_method_call (NULL, "/the/path", NULL, "TheMember");
1256 : 1 : g_dbus_message_set_body (message,
1257 : : g_variant_new ("(@v)",
1258 : : g_variant_new_variant (
1259 : : g_variant_new_from_data (long_tuple_type,
1260 : : data,
1261 : : 256,
1262 : : TRUE,
1263 : : NULL,
1264 : : NULL))));
1265 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1266 : :
1267 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1268 : 1 : g_assert_cmpstr (error->message, ==,
1269 : : "D-Bus signature exceeds maximum length of 255 bytes");
1270 : 1 : g_assert_null (blob);
1271 : :
1272 : 1 : g_free (data);
1273 : 1 : g_free (long_tuple_type_string);
1274 : 1 : g_free (long_signature);
1275 : 1 : g_clear_error (&error);
1276 : 1 : g_clear_object (&message);
1277 : 1 : g_variant_type_free (long_tuple_type);
1278 : 1 : }
1279 : :
1280 : : static void
1281 : 1 : test_message_serialize_body_signature_checks (void)
1282 : : {
1283 : 1 : GDBusMessage *message = NULL;
1284 : 1 : GError *error = NULL;
1285 : 1 : guchar *blob = NULL;
1286 : 1 : gsize blob_size = 0;
1287 : :
1288 : 1 : message = g_dbus_message_new_method_call (NULL, "/the/path", NULL, "TheMember");
1289 : 1 : g_dbus_message_set_body (message, g_variant_new ("(s)", "hello"));
1290 : 1 : g_dbus_message_set_signature (message, NULL);
1291 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1292 : :
1293 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1294 : 1 : g_assert_cmpstr (error->message, ==,
1295 : : "Message body has signature “(s)” but there is no signature header");
1296 : 1 : g_assert_null (blob);
1297 : :
1298 : 1 : g_clear_error (&error);
1299 : 1 : g_clear_object (&message);
1300 : :
1301 : 1 : message = g_dbus_message_new_method_call (NULL, "/the/path", NULL, "TheMember");
1302 : 1 : g_dbus_message_set_body (message, g_variant_new ("(s)", "hello"));
1303 : 1 : g_dbus_message_set_signature (message, "u");
1304 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1305 : :
1306 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1307 : 1 : g_assert_cmpstr (error->message, ==,
1308 : : "Message body has type signature “(s)” but signature in the header field is “(u)”");
1309 : 1 : g_assert_null (blob);
1310 : :
1311 : 1 : g_clear_error (&error);
1312 : 1 : g_clear_object (&message);
1313 : :
1314 : 1 : message = g_dbus_message_new_method_call (NULL, "/the/path", NULL, "TheMember");
1315 : 1 : g_dbus_message_set_signature (message, "s");
1316 : 1 : blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1317 : :
1318 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1319 : 1 : g_assert_cmpstr (error->message, ==,
1320 : : "Message body is empty but signature in the header field is “(s)”");
1321 : 1 : g_assert_null (blob);
1322 : :
1323 : 1 : g_clear_error (&error);
1324 : 1 : g_clear_object (&message);
1325 : 1 : }
1326 : :
1327 : : /* ---------------------------------------------------------------------------------------------------- */
1328 : :
1329 : : static void
1330 : 1 : test_message_parse_empty_arrays_of_arrays (void)
1331 : : {
1332 : : GVariant *body;
1333 : 1 : GError *error = NULL;
1334 : :
1335 : 1 : g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=673612");
1336 : : /* These three-element array of empty arrays were previously read back as a
1337 : : * two-element array of empty arrays, due to sometimes erroneously skipping
1338 : : * four bytes to align for the eight-byte-aligned grandchild types (x and
1339 : : * dict_entry).
1340 : : */
1341 : 1 : body = g_variant_parse (G_VARIANT_TYPE ("(aaax)"),
1342 : : "([@aax [], [], []],)", NULL, NULL, &error);
1343 : 1 : g_assert_no_error (error);
1344 : 1 : check_serialization (body,
1345 : : "value 0: array:\n"
1346 : : " array:\n"
1347 : : " array:\n"
1348 : : " array:\n");
1349 : 1 : g_variant_unref (body);
1350 : :
1351 : 1 : body = g_variant_parse (G_VARIANT_TYPE ("(aaa{uu})"),
1352 : : "([@aa{uu} [], [], []],)", NULL, NULL, &error);
1353 : 1 : g_assert_no_error (error);
1354 : 1 : check_serialization (body,
1355 : : "value 0: array:\n"
1356 : : " array:\n"
1357 : : " array:\n"
1358 : : " array:\n");
1359 : 1 : g_variant_unref (body);
1360 : :
1361 : : /* Due to the same bug, g_dbus_message_new_from_blob() would fail for this
1362 : : * message because it would try to read past the end of the string. Hence,
1363 : : * sending this to an application would make it fall off the bus. */
1364 : 1 : body = g_variant_parse (G_VARIANT_TYPE ("(a(aa{sv}as))"),
1365 : : "([ ([], []),"
1366 : : " ([], []),"
1367 : : " ([], [])],)", NULL, NULL, &error);
1368 : 1 : g_assert_no_error (error);
1369 : 1 : check_serialization (body,
1370 : : "value 0: array:\n"
1371 : : " struct:\n"
1372 : : " array:\n"
1373 : : " array:\n"
1374 : : " struct:\n"
1375 : : " array:\n"
1376 : : " array:\n"
1377 : : " struct:\n"
1378 : : " array:\n"
1379 : : " array:\n");
1380 : 1 : g_variant_unref (body);
1381 : 1 : }
1382 : :
1383 : : /* ---------------------------------------------------------------------------------------------------- */
1384 : :
1385 : : static void
1386 : 1 : test_message_serialize_double_array (void)
1387 : : {
1388 : : GVariantBuilder builder;
1389 : : GVariant *body;
1390 : :
1391 : 1 : g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=732754");
1392 : :
1393 : 1 : g_variant_builder_init_static (&builder, G_VARIANT_TYPE ("ad"));
1394 : 1 : g_variant_builder_add (&builder, "d", (gdouble)0.0);
1395 : 1 : g_variant_builder_add (&builder, "d", (gdouble)8.0);
1396 : 1 : g_variant_builder_add (&builder, "d", (gdouble)22.0);
1397 : 1 : g_variant_builder_add (&builder, "d", (gdouble)0.0);
1398 : 1 : body = g_variant_new ("(@ad)", g_variant_builder_end (&builder));
1399 : 1 : check_serialization (body,
1400 : : "value 0: array:\n"
1401 : : " double: 0.000000\n"
1402 : : " double: 8.000000\n"
1403 : : " double: 22.000000\n"
1404 : : " double: 0.000000\n");
1405 : 1 : }
1406 : :
1407 : : /* ---------------------------------------------------------------------------------------------------- */
1408 : :
1409 : : /* Test that an invalid header in a D-Bus message (specifically, with a type
1410 : : * which doesn’t match what’s expected for the given header) is gracefully
1411 : : * handled with an error rather than a crash. */
1412 : : static void
1413 : 1 : test_message_parse_non_signature_header (void)
1414 : : {
1415 : 1 : const guint8 data[] = {
1416 : : 'l', /* little-endian byte order */
1417 : : 0x02, /* message type (method return) */
1418 : : 0x00, /* message flags (none) */
1419 : : 0x01, /* major protocol version */
1420 : : 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */
1421 : : 0x00, 0x00, 0x00, 0xbc, /* message serial */
1422 : : /* a{yv} of header fields:
1423 : : * (things start to be invalid below here) */
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 : : 0x04, /* signature length */
1428 : : 'd', 0x00, 0x00, 'F', /* signature (invalid) */
1429 : : 0x00, /* nul terminator */
1430 : : /* (Variant array value payload missing) */
1431 : : /* alignment padding before the next header array element, as structs must
1432 : : * be 8-aligned: */
1433 : : 0x00,
1434 : : 0x05, /* array key (REPLY_SERIAL, required for method return messages) */
1435 : : /* Variant array value: */
1436 : : 0x01, /* signature length */
1437 : : 'u', /* one complete type */
1438 : : 0x00, /* nul terminator */
1439 : : /* (Variant array value payload) */
1440 : : 0x00, 0x01, 0x02, 0x03,
1441 : : /* (message body is zero-length) */
1442 : : };
1443 : 1 : gsize size = sizeof (data);
1444 : 1 : GDBusMessage *message = NULL;
1445 : 1 : GError *local_error = NULL;
1446 : :
1447 : 1 : message = g_dbus_message_new_from_blob ((guchar *) data, size,
1448 : : G_DBUS_CAPABILITY_FLAGS_NONE,
1449 : : &local_error);
1450 : 1 : g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1451 : 1 : g_assert_null (message);
1452 : :
1453 : 1 : g_clear_error (&local_error);
1454 : 1 : }
1455 : :
1456 : : /* ---------------------------------------------------------------------------------------------------- */
1457 : :
1458 : : /* Test that an invalid header in a D-Bus message (specifically, containing a
1459 : : * variant with an empty type signature) is gracefully handled with an error
1460 : : * rather than a crash. */
1461 : : static void
1462 : 1 : test_message_parse_empty_signature_header (void)
1463 : : {
1464 : 1 : const guint8 data[] = {
1465 : : 'l', /* little-endian byte order */
1466 : : 0x02, /* message type (method return) */
1467 : : 0x00, /* message flags (none) */
1468 : : 0x01, /* major protocol version */
1469 : : 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */
1470 : : 0x20, 0x20, 0x20, 0x20, /* message serial */
1471 : : /* a{yv} of header fields:
1472 : : * (things start to be invalid below here) */
1473 : : 0x10, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1474 : : 0x20, /* array key (this is not currently a valid header field) */
1475 : : /* Variant array value: */
1476 : : 0x00, /* signature length */
1477 : : 0x00, /* nul terminator */
1478 : : /* (Variant array value payload missing) */
1479 : : /* alignment padding before the next header array element, as structs must
1480 : : * be 8-aligned: */
1481 : : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1482 : : 0x05, /* array key (REPLY_SERIAL, required for method return messages) */
1483 : : /* Variant array value: */
1484 : : 0x01, /* signature length */
1485 : : 'u', /* one complete type */
1486 : : 0x00, /* nul terminator */
1487 : : /* (Variant array value payload) */
1488 : : 0x00, 0x01, 0x02, 0x03,
1489 : : /* (message body is zero-length) */
1490 : : };
1491 : 1 : gsize size = sizeof (data);
1492 : 1 : GDBusMessage *message = NULL;
1493 : 1 : GError *local_error = NULL;
1494 : :
1495 : 1 : message = g_dbus_message_new_from_blob ((guchar *) data, size,
1496 : : G_DBUS_CAPABILITY_FLAGS_NONE,
1497 : : &local_error);
1498 : 1 : g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1499 : 1 : g_assert_null (message);
1500 : :
1501 : 1 : g_clear_error (&local_error);
1502 : 1 : }
1503 : :
1504 : : /* ---------------------------------------------------------------------------------------------------- */
1505 : :
1506 : : /* Test that an invalid header in a D-Bus message (specifically, containing a
1507 : : * variant with a type signature containing multiple complete types) is
1508 : : * gracefully handled with an error rather than a crash. */
1509 : : static void
1510 : 1 : test_message_parse_multiple_signature_header (void)
1511 : : {
1512 : 1 : const guint8 data[] = {
1513 : : 'l', /* little-endian byte order */
1514 : : 0x02, /* message type (method return) */
1515 : : 0x00, /* message flags (none) */
1516 : : 0x01, /* major protocol version */
1517 : : 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */
1518 : : 0x20, 0x20, 0x20, 0x20, /* message serial */
1519 : : /* a{yv} of header fields:
1520 : : * (things start to be invalid below here) */
1521 : : 0x10, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1522 : : 0x20, /* array key (this is not currently a valid header field) */
1523 : : /* Variant array value: */
1524 : : 0x02, /* signature length */
1525 : : 'b', 'b', /* two complete types */
1526 : : 0x00, /* nul terminator */
1527 : : /* (Variant array value payload missing) */
1528 : : /* alignment padding before the next header array element, as structs must
1529 : : * be 8-aligned: */
1530 : : 0x00, 0x00, 0x00,
1531 : : 0x05, /* array key (REPLY_SERIAL, required for method return messages) */
1532 : : /* Variant array value: */
1533 : : 0x01, /* signature length */
1534 : : 'u', /* one complete type */
1535 : : 0x00, /* nul terminator */
1536 : : /* (Variant array value payload) */
1537 : : 0x00, 0x01, 0x02, 0x03,
1538 : : /* (message body is zero-length) */
1539 : : };
1540 : 1 : gsize size = sizeof (data);
1541 : 1 : GDBusMessage *message = NULL;
1542 : 1 : GError *local_error = NULL;
1543 : :
1544 : 1 : message = g_dbus_message_new_from_blob ((guchar *) data, size,
1545 : : G_DBUS_CAPABILITY_FLAGS_NONE,
1546 : : &local_error);
1547 : 1 : g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1548 : 1 : g_assert_null (message);
1549 : :
1550 : 1 : g_clear_error (&local_error);
1551 : 1 : }
1552 : :
1553 : : /* ---------------------------------------------------------------------------------------------------- */
1554 : :
1555 : : /* Test that an invalid header in a D-Bus message (specifically, containing a
1556 : : * variant with a valid type signature that is too long to be a valid
1557 : : * #GVariantType due to exceeding the array nesting limits) is gracefully
1558 : : * handled with an error rather than a crash. */
1559 : : static void
1560 : 1 : test_message_parse_over_long_signature_header (void)
1561 : : {
1562 : 1 : const guint8 data[] = {
1563 : : 'l', /* little-endian byte order */
1564 : : 0x02, /* message type (method return) */
1565 : : 0x00, /* message flags (none) */
1566 : : 0x01, /* major protocol version */
1567 : : 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */
1568 : : 0x20, 0x20, 0x20, 0x20, /* message serial */
1569 : : /* a{yv} of header fields:
1570 : : * (things start to be invalid below here) */
1571 : : 0xa0, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1572 : : 0x08, /* array key (SIGNATURE) */
1573 : : /* Variant array value: */
1574 : : 0x04, /* signature length */
1575 : : 'g', 0x00, 0x20, 0x20, /* one complete type plus some rubbish */
1576 : : 0x00, /* nul terminator */
1577 : : /* (Variant array value payload) */
1578 : : /* Critically, this contains 128 nested ‘a’s, which exceeds
1579 : : * %G_VARIANT_MAX_RECURSION_DEPTH. */
1580 : : 0xec,
1581 : : 'a', 'b', 'g', 'd', 'u', 'd', 'd', 'd', 'd', 'd', 'd', 'd',
1582 : : 'd', 'd', 'd',
1583 : : 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1584 : : 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1585 : : 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1586 : : 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1587 : : 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1588 : : 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1589 : : 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1590 : : 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1591 : : 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1592 : : 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1593 : : 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
1594 : : 'v',
1595 : : /* first header length is a multiple of 8 so no padding is needed */
1596 : : 0x05, /* array key (REPLY_SERIAL, required for method return messages) */
1597 : : /* Variant array value: */
1598 : : 0x01, /* signature length */
1599 : : 'u', /* one complete type */
1600 : : 0x00, /* nul terminator */
1601 : : /* (Variant array value payload) */
1602 : : 0x00, 0x01, 0x02, 0x03,
1603 : : /* (message body is zero-length) */
1604 : : };
1605 : 1 : gsize size = sizeof (data);
1606 : 1 : GDBusMessage *message = NULL;
1607 : 1 : GError *local_error = NULL;
1608 : :
1609 : 1 : message = g_dbus_message_new_from_blob ((guchar *) data, size,
1610 : : G_DBUS_CAPABILITY_FLAGS_NONE,
1611 : : &local_error);
1612 : 1 : g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1613 : 1 : g_assert_null (message);
1614 : :
1615 : 1 : g_clear_error (&local_error);
1616 : 1 : }
1617 : :
1618 : : /* ---------------------------------------------------------------------------------------------------- */
1619 : :
1620 : : /* Test that an invalid header in a D-Bus message (specifically, containing too
1621 : : * many levels of nested variant) is gracefully handled with an error rather
1622 : : * than a crash. */
1623 : : static void
1624 : 1 : test_message_parse_deep_header_nesting (void)
1625 : : {
1626 : 1 : const guint8 data[] = {
1627 : : 'l', /* little-endian byte order */
1628 : : 0x02, /* message type (method return) */
1629 : : 0x00, /* message flags (none) */
1630 : : 0x01, /* major protocol version */
1631 : : 0x00, 0x00, 0x00, 0x00, /* body length (in bytes) */
1632 : : 0x20, 0x20, 0x20, 0x20, /* message serial */
1633 : : /* a{yv} of header fields:
1634 : : * (things start to be invalid below here) */
1635 : : 0xd0, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1636 : : 0x20, /* array key (this is not currently a valid header field) */
1637 : : /* Variant array value: */
1638 : : 0x01, /* signature length */
1639 : : 'v', /* one complete type */
1640 : : 0x00, /* nul terminator */
1641 : : /* (Variant array value payload) */
1642 : : /* Critically, this contains 64 nested variants (minus two for the
1643 : : * ‘arbitrary valid content’ below, but ignoring two for the `a{yv}`
1644 : : * above), which in total exceeds %G_DBUS_MAX_TYPE_DEPTH. */
1645 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1646 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1647 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1648 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1649 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1650 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1651 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1652 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1653 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1654 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1655 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1656 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1657 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1658 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1659 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1660 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1661 : : /* Some arbitrary valid content inside the innermost variant: */
1662 : : 0x01, 'y', 0x00, 0xcc,
1663 : : /* no padding needed as this header element length is a multiple of 8 */
1664 : : 0x05, /* array key (REPLY_SERIAL, required for method return messages) */
1665 : : /* Variant array value: */
1666 : : 0x01, /* signature length */
1667 : : 'u', /* one complete type */
1668 : : 0x00, /* nul terminator */
1669 : : /* (Variant array value payload) */
1670 : : 0x00, 0x01, 0x02, 0x03,
1671 : : /* (message body is zero-length) */
1672 : : };
1673 : 1 : gsize size = sizeof (data);
1674 : 1 : GDBusMessage *message = NULL;
1675 : 1 : GError *local_error = NULL;
1676 : :
1677 : 1 : message = g_dbus_message_new_from_blob ((guchar *) data, size,
1678 : : G_DBUS_CAPABILITY_FLAGS_NONE,
1679 : : &local_error);
1680 : 1 : g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1681 : 1 : g_assert_null (message);
1682 : :
1683 : 1 : g_clear_error (&local_error);
1684 : 1 : }
1685 : :
1686 : : /* ---------------------------------------------------------------------------------------------------- */
1687 : :
1688 : : /* Test that an invalid body in a D-Bus message (specifically, containing too
1689 : : * many levels of nested variant) is gracefully handled with an error rather
1690 : : * than a crash. The set of bytes here are a modified version of the bytes from
1691 : : * test_message_parse_deep_header_nesting(). */
1692 : : static void
1693 : 1 : test_message_parse_deep_body_nesting (void)
1694 : : {
1695 : 1 : const guint8 data[] = {
1696 : : 'l', /* little-endian byte order */
1697 : : 0x02, /* message type (method return) */
1698 : : 0x00, /* message flags (none) */
1699 : : 0x01, /* major protocol version */
1700 : : 0xc4, 0x00, 0x00, 0x00, /* body length (in bytes) */
1701 : : 0x20, 0x20, 0x20, 0x20, /* message serial */
1702 : : /* a{yv} of header fields: */
1703 : : 0x10, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1704 : : 0x08, /* array key (SIGNATURE) */
1705 : : /* Variant array value: */
1706 : : 0x01, /* signature length */
1707 : : 'g', /* one complete type */
1708 : : 0x00, /* nul terminator */
1709 : : /* (Variant array value payload) */
1710 : : 0x01, 'v', 0x00,
1711 : : /* alignment padding before the next header array element, as structs must
1712 : : * be 8-aligned: */
1713 : : 0x00,
1714 : : 0x05, /* array key (REPLY_SERIAL, required for method return messages) */
1715 : : /* Variant array value: */
1716 : : 0x01, /* signature length */
1717 : : 'u', /* one complete type */
1718 : : 0x00, /* nul terminator */
1719 : : /* (Variant array value payload) */
1720 : : 0x00, 0x01, 0x02, 0x03,
1721 : : /* Message body: over 64 levels of nested variant, which is not valid: */
1722 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1723 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1724 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1725 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1726 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1727 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1728 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1729 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1730 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1731 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1732 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1733 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1734 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1735 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1736 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1737 : : 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00, 0x01, 'v', 0x00,
1738 : : /* Some arbitrary valid content inside the innermost variant: */
1739 : : 0x01, 'y', 0x00, 0xcc,
1740 : : };
1741 : 1 : gsize size = sizeof (data);
1742 : 1 : GDBusMessage *message = NULL;
1743 : 1 : GError *local_error = NULL;
1744 : :
1745 : 1 : message = g_dbus_message_new_from_blob ((guchar *) data, size,
1746 : : G_DBUS_CAPABILITY_FLAGS_NONE,
1747 : : &local_error);
1748 : 1 : g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1749 : 1 : g_assert_null (message);
1750 : :
1751 : 1 : g_clear_error (&local_error);
1752 : 1 : }
1753 : :
1754 : : /* ---------------------------------------------------------------------------------------------------- */
1755 : :
1756 : : static void
1757 : 1 : test_message_parse_truncated (void)
1758 : : {
1759 : 1 : GDBusMessage *message = NULL;
1760 : 1 : GDBusMessage *message2 = NULL;
1761 : : GVariantBuilder builder;
1762 : 1 : guchar *blob = NULL;
1763 : 1 : gsize size = 0;
1764 : 1 : GError *error = NULL;
1765 : :
1766 : 1 : g_test_summary ("Test that truncated messages are properly rejected.");
1767 : 1 : g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2528");
1768 : :
1769 : 1 : message = g_dbus_message_new ();
1770 : 1 : g_variant_builder_init_static (&builder, G_VARIANT_TYPE ("(asbynqiuxtd)"));
1771 : 1 : g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
1772 : 1 : g_variant_builder_add (&builder, "s", "fourtytwo");
1773 : 1 : g_variant_builder_close (&builder);
1774 : 1 : g_variant_builder_add (&builder, "b", TRUE);
1775 : 1 : g_variant_builder_add (&builder, "y", 42);
1776 : 1 : g_variant_builder_add (&builder, "n", 42);
1777 : 1 : g_variant_builder_add (&builder, "q", 42);
1778 : 1 : g_variant_builder_add (&builder, "i", 42);
1779 : 1 : g_variant_builder_add (&builder, "u", 42);
1780 : 1 : g_variant_builder_add (&builder, "x", 42);
1781 : 1 : g_variant_builder_add (&builder, "t", 42);
1782 : 1 : g_variant_builder_add (&builder, "d", (gdouble) 42);
1783 : :
1784 : 1 : g_dbus_message_set_message_type (message, G_DBUS_MESSAGE_TYPE_METHOD_CALL);
1785 : 1 : g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH,
1786 : : g_variant_new_object_path ("/foo/bar"));
1787 : 1 : g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER,
1788 : : g_variant_new_string ("Member"));
1789 : 1 : g_dbus_message_set_body (message, g_variant_builder_end (&builder));
1790 : :
1791 : 1 : blob = g_dbus_message_to_blob (message, &size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1792 : 1 : g_assert_no_error (error);
1793 : :
1794 : 1 : g_clear_object (&message);
1795 : :
1796 : : /* Try parsing all possible prefixes of the full @blob. */
1797 : 145 : for (gsize i = 0; i < size; i++)
1798 : : {
1799 : 144 : message2 = g_dbus_message_new_from_blob (blob, i, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1800 : 144 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1801 : 144 : g_assert_null (message2);
1802 : 144 : g_clear_error (&error);
1803 : : }
1804 : :
1805 : 1 : message2 = g_dbus_message_new_from_blob (blob, size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
1806 : 1 : g_assert_no_error (error);
1807 : 1 : g_assert_true (G_IS_DBUS_MESSAGE (message2));
1808 : 1 : g_clear_object (&message2);
1809 : :
1810 : 1 : g_free (blob);
1811 : 1 : }
1812 : :
1813 : : static void
1814 : 1 : test_message_parse_empty_structure (void)
1815 : : {
1816 : 1 : const guint8 data[] =
1817 : : {
1818 : : 'l', /* little-endian byte order */
1819 : : 0x02, /* message type (method return) */
1820 : : 0x00, /* message flags (none) */
1821 : : 0x01, /* major protocol version */
1822 : : 0x08, 0x00, 0x00, 0x00, /* body length (in bytes) */
1823 : : 0x00, 0x00, 0x00, 0x00, /* message serial */
1824 : : /* a{yv} of header fields */
1825 : : 0x20, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1826 : : 0x01, /* array key (PATH) */
1827 : : 0x01, /* signature length */
1828 : : 'o', /* type (OBJECT_PATH) */
1829 : : 0x00, /* nul terminator */
1830 : : 0x05, 0x00, 0x00, 0x00, /* length 5 */
1831 : : '/', 'p', 'a', 't', 'h', 0x00, 0x00, 0x00, /* string '/path' and padding */
1832 : : 0x03, /* array key (MEMBER) */
1833 : : 0x01, /* signature length */
1834 : : 's', /* type (STRING) */
1835 : : 0x00, /* nul terminator */
1836 : : 0x06, 0x00, 0x00, 0x00, /* length 6 */
1837 : : 'M', 'e', 'm', 'b', 'e', 'r', 0x00, 0x00, /* string 'Member' and padding */
1838 : : 0x08, /* array key (SIGNATURE) */
1839 : : 0x01, /* signature length */
1840 : : 'g', /* type (SIGNATURE) */
1841 : : 0x00, /* nul terminator */
1842 : : 0x03, /* length 3 */
1843 : : 'a', '(', ')', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* type 'a()' and padding */
1844 : : 0x08, 0x00, 0x00, 0x00, /* array length: 4 bytes */
1845 : : 0x00, 0x00, 0x00, 0x00, /* padding to 8 bytes */
1846 : : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* array data */
1847 : : 0x00
1848 : : };
1849 : 1 : gsize size = sizeof (data);
1850 : 1 : GDBusMessage *message = NULL;
1851 : 1 : GError *local_error = NULL;
1852 : :
1853 : 1 : g_test_summary ("Test that empty structures are rejected when parsing.");
1854 : 1 : g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2557");
1855 : :
1856 : 1 : message = g_dbus_message_new_from_blob ((guchar *) data, size,
1857 : : G_DBUS_CAPABILITY_FLAGS_NONE,
1858 : : &local_error);
1859 : 1 : g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1860 : 1 : g_assert_cmpstr (local_error->message, ==, "Empty structures (tuples) are not allowed in D-Bus");
1861 : 1 : g_assert_null (message);
1862 : :
1863 : 1 : g_clear_error (&local_error);
1864 : 1 : }
1865 : :
1866 : : static void
1867 : 1 : test_message_serialize_empty_structure (void)
1868 : : {
1869 : : GDBusMessage *message;
1870 : : GVariantBuilder builder;
1871 : 1 : gsize size = 0;
1872 : 1 : GError *local_error = NULL;
1873 : :
1874 : 1 : g_test_summary ("Test that empty structures are rejected when serializing.");
1875 : 1 : g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2557");
1876 : :
1877 : 1 : message = g_dbus_message_new ();
1878 : 1 : g_variant_builder_init_static (&builder, G_VARIANT_TYPE ("(a())"));
1879 : 1 : g_variant_builder_open (&builder, G_VARIANT_TYPE ("a()"));
1880 : 1 : g_variant_builder_add (&builder, "()");
1881 : 1 : g_variant_builder_close (&builder);
1882 : 1 : g_dbus_message_set_message_type (message, G_DBUS_MESSAGE_TYPE_METHOD_CALL);
1883 : 1 : g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH,
1884 : : g_variant_new_object_path ("/path"));
1885 : 1 : g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER,
1886 : : g_variant_new_string ("Member"));
1887 : 1 : g_dbus_message_set_body (message, g_variant_builder_end (&builder));
1888 : :
1889 : 1 : g_dbus_message_to_blob (message, &size, G_DBUS_CAPABILITY_FLAGS_NONE, &local_error);
1890 : 1 : g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1891 : 1 : g_assert_cmpstr (local_error->message, ==, "Empty structures (tuples) are not allowed in D-Bus");
1892 : :
1893 : 1 : g_clear_error (&local_error);
1894 : 1 : g_clear_object (&message);
1895 : 1 : }
1896 : :
1897 : : static void
1898 : 1 : test_message_parse_missing_header (void)
1899 : : {
1900 : 1 : const guint8 data[] = {
1901 : : 'l', /* little-endian byte order */
1902 : : 0x01, /* message type (method call) */
1903 : : 0x00, /* message flags (none) */
1904 : : 0x01, /* major protocol version */
1905 : : 0x12, 0x00, 0x00, 0x00, /* body length (in bytes) */
1906 : : 0x20, 0x20, 0x20, 0x20, /* message serial */
1907 : : /* a{yv} of header fields: */
1908 : : 0x24, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1909 : : 0x01, /* array key (PATH, required for method call messages) */
1910 : : /* Variant array value: */
1911 : : 0x01, /* signature length */
1912 : : 'o', /* one complete type */
1913 : : 0x00, /* nul terminator */
1914 : : /* (Variant array value payload) */
1915 : : 0x01, 0x00, 0x00, 0x00,
1916 : : '/', 0x00, 0x00, 0x00,
1917 : : 0x00, 0x00, 0x00, 0x00,
1918 : : 0x30, /* array key (MEMBER, required for method call messages; CORRUPTED from 0x03) */
1919 : : /* Variant array value: */
1920 : : 0x01, /* signature length */
1921 : : 's', /* one complete type */
1922 : : 0x00, /* nul terminator */
1923 : : /* (Variant array value payload) */
1924 : : 0x03, 0x00, 0x00, 0x00,
1925 : : 'H', 'e', 'y', 0x00,
1926 : : 0x00, 0x00, 0x00, 0x00,
1927 : : 0x08, /* array key (SIGNATURE) */
1928 : : /* Variant array value: */
1929 : : 0x01, /* signature length */
1930 : : 'g', /* one complete type */
1931 : : 0x00, /* nul terminator */
1932 : : /* (Variant array value payload) */
1933 : : 0x02, 's', 's', 0x00,
1934 : : /* Some arbitrary valid content inside the message body: */
1935 : : 0x03, 0x00, 0x00, 0x00,
1936 : : 'h', 'e', 'y', 0x00,
1937 : : 0x05, 0x00, 0x00, 0x00,
1938 : : 't', 'h', 'e', 'r', 'e', 0x00
1939 : : };
1940 : :
1941 : 1 : gsize size = sizeof (data);
1942 : 1 : GDBusMessage *message = NULL;
1943 : 1 : GError *local_error = NULL;
1944 : :
1945 : 1 : g_test_summary ("Test that missing (required) headers prompt an error.");
1946 : 1 : g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3061");
1947 : :
1948 : 1 : message = g_dbus_message_new_from_blob ((guchar *) data, size,
1949 : : G_DBUS_CAPABILITY_FLAGS_NONE,
1950 : : &local_error);
1951 : 1 : g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1952 : 1 : g_assert_null (message);
1953 : :
1954 : 1 : g_clear_error (&local_error);
1955 : 1 : }
1956 : :
1957 : : static void
1958 : 1 : test_message_parse_invalid_header_type (void)
1959 : : {
1960 : 1 : const guint8 data[] = {
1961 : : 'l', /* little-endian byte order */
1962 : : 0x01, /* message type (method call) */
1963 : : 0x00, /* message flags (none) */
1964 : : 0x01, /* major protocol version */
1965 : : 0x12, 0x00, 0x00, 0x00, /* body length (in bytes) */
1966 : : 0x20, 0x20, 0x20, 0x20, /* message serial */
1967 : : /* a{yv} of header fields: */
1968 : : 0x24, 0x00, 0x00, 0x00, /* array length (in bytes), must be a multiple of 8 */
1969 : : 0x01, /* array key (PATH, required for method call messages) */
1970 : : /* Variant array value: */
1971 : : 0x01, /* signature length */
1972 : : 'o', /* one complete type */
1973 : : 0x00, /* nul terminator */
1974 : : /* (Variant array value payload) */
1975 : : 0x01, 0x00, 0x00, 0x00,
1976 : : '/', 0x00, 0x00, 0x00,
1977 : : 0x00, 0x00, 0x00, 0x00,
1978 : : 0x03, /* array key (MEMBER, required for method call messages) */
1979 : : /* Variant array value: */
1980 : : 0x01, /* signature length */
1981 : : 't', /* one complete type; CORRUPTED, MEMBER should be 's' */
1982 : : 0x00, /* nul terminator */
1983 : : /* (Padding to 64-bit alignment of 't)' */
1984 : : 0x00, 0x00, 0x00, 0x00,
1985 : : /* (Variant array value payload) */
1986 : : 'H', 'e', 'y', 0x00,
1987 : : 0x00, 0x00, 0x00, 0x00,
1988 : : 0x08, /* array key (SIGNATURE) */
1989 : : /* Variant array value: */
1990 : : 0x01, /* signature length */
1991 : : 'g', /* one complete type */
1992 : : 0x00, /* nul terminator */
1993 : : /* (Variant array value payload) */
1994 : : 0x02, 's', 's', 0x00,
1995 : : /* Some arbitrary valid content inside the message body: */
1996 : : 0x03, 0x00, 0x00, 0x00,
1997 : : 'h', 'e', 'y', 0x00,
1998 : : 0x05, 0x00, 0x00, 0x00,
1999 : : 't', 'h', 'e', 'r', 'e', 0x00
2000 : : };
2001 : :
2002 : 1 : gsize size = sizeof (data);
2003 : 1 : GDBusMessage *message = NULL;
2004 : 1 : GError *local_error = NULL;
2005 : :
2006 : 1 : g_test_summary ("Test that the type of well-known headers is checked.");
2007 : 1 : g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3061");
2008 : :
2009 : 1 : message = g_dbus_message_new_from_blob ((guchar *) data, size,
2010 : : G_DBUS_CAPABILITY_FLAGS_NONE,
2011 : : &local_error);
2012 : 1 : g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
2013 : 1 : g_assert_null (message);
2014 : :
2015 : 1 : g_clear_error (&local_error);
2016 : 1 : }
2017 : :
2018 : : /* ---------------------------------------------------------------------------------------------------- */
2019 : :
2020 : : int
2021 : 1 : main (int argc,
2022 : : char *argv[])
2023 : : {
2024 : 1 : g_setenv ("LC_ALL", "C", TRUE);
2025 : 1 : setlocale (LC_ALL, "C");
2026 : :
2027 : 1 : g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
2028 : :
2029 : 1 : g_test_add_func ("/gdbus/message-serialize/basic",
2030 : : test_message_serialize_basic);
2031 : 1 : g_test_add_func ("/gdbus/message-serialize/complex",
2032 : : test_message_serialize_complex);
2033 : 1 : g_test_add_func ("/gdbus/message-serialize/invalid",
2034 : : test_message_serialize_invalid);
2035 : 1 : g_test_add_func ("/gdbus/message-serialize/header-checks",
2036 : : test_message_serialize_header_checks);
2037 : 1 : g_test_add_func ("/gdbus/message-serialize/header-checks/valid",
2038 : : test_message_serialize_header_checks_valid);
2039 : 1 : g_test_add_func ("/gdbus/message-serialize/over-long-signature",
2040 : : test_message_serialize_over_long_signature);
2041 : 1 : g_test_add_func ("/gdbus/message-serialize/over-long-variant-signature",
2042 : : test_message_serialize_over_long_variant_signature);
2043 : 1 : g_test_add_func ("/gdbus/message-serialize/body-signature-checks",
2044 : : test_message_serialize_body_signature_checks);
2045 : 1 : g_test_add_func ("/gdbus/message-serialize/double-array",
2046 : : test_message_serialize_double_array);
2047 : 1 : g_test_add_func ("/gdbus/message-serialize/empty-structure",
2048 : : test_message_serialize_empty_structure);
2049 : :
2050 : 1 : g_test_add_func ("/gdbus/message-parse/empty-arrays-of-arrays",
2051 : : test_message_parse_empty_arrays_of_arrays);
2052 : 1 : g_test_add_func ("/gdbus/message-parse/non-signature-header",
2053 : : test_message_parse_non_signature_header);
2054 : 1 : g_test_add_func ("/gdbus/message-parse/empty-signature-header",
2055 : : test_message_parse_empty_signature_header);
2056 : 1 : g_test_add_func ("/gdbus/message-parse/multiple-signature-header",
2057 : : test_message_parse_multiple_signature_header);
2058 : 1 : g_test_add_func ("/gdbus/message-parse/over-long-signature-header",
2059 : : test_message_parse_over_long_signature_header);
2060 : 1 : g_test_add_func ("/gdbus/message-parse/deep-header-nesting",
2061 : : test_message_parse_deep_header_nesting);
2062 : 1 : g_test_add_func ("/gdbus/message-parse/deep-body-nesting",
2063 : : test_message_parse_deep_body_nesting);
2064 : 1 : g_test_add_func ("/gdbus/message-parse/truncated",
2065 : : test_message_parse_truncated);
2066 : 1 : g_test_add_func ("/gdbus/message-parse/empty-structure",
2067 : : test_message_parse_empty_structure);
2068 : 1 : g_test_add_func ("/gdbus/message-parse/missing-header",
2069 : : test_message_parse_missing_header);
2070 : 1 : g_test_add_func ("/gdbus/message-parse/invalid-header-type",
2071 : : test_message_parse_invalid_header_type);
2072 : :
2073 : 1 : return g_test_run();
2074 : : }
|