1 /*
2  * Copyright © 2010 Codethink Limited
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * See the included COPYING file for more information.
10  *
11  * Author: Ryan Lortie <desrt@desrt.ca>
12  */
13 
14 #include "config.h"
15 
16 #include <glib/gvariant-internal.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include <glib.h>
20 
21 #define BASIC "bynqiuxthdsog?"
22 #define N_BASIC (G_N_ELEMENTS (BASIC) - 1)
23 
24 #define INVALIDS "cefjklpwz&@^$"
25 #define N_INVALIDS (G_N_ELEMENTS (INVALIDS) - 1)
26 
27 /* see comment in gvariant-serialiser.c about this madness.
28  *
29  * we use this to get testing of non-strictly-aligned GVariant instances
30  * on machines that can tolerate it.  it is necessary to support this
31  * because some systems have malloc() that returns non-8-aligned
32  * pointers.  it is necessary to have special support in the tests
33  * because on most machines malloc() is 8-aligned.
34  */
35 #define ALIGN_BITS (sizeof (struct { char a; union {                       \
36                       guint64 x; void *y; gdouble z; } b; }) - 9)
37 
38 static gboolean
randomly(gdouble prob)39 randomly (gdouble prob)
40 {
41   return g_test_rand_double_range (0, 1) < prob;
42 }
43 
44 /* corecursion */
45 static GVariantType *
46 append_tuple_type_string (GString *, GString *, gboolean, gint);
47 
48 /* append a random GVariantType to a GString
49  * append a description of the type to another GString
50  * return what the type is
51  */
52 static GVariantType *
append_type_string(GString * string,GString * description,gboolean definite,gint depth)53 append_type_string (GString  *string,
54                     GString  *description,
55                     gboolean  definite,
56                     gint      depth)
57 {
58   if (!depth-- || randomly (0.3))
59     {
60       gchar b = BASIC[g_test_rand_int_range (0, N_BASIC - definite)];
61       g_string_append_c (string, b);
62       g_string_append_c (description, b);
63 
64       switch (b)
65         {
66         case 'b':
67           return g_variant_type_copy (G_VARIANT_TYPE_BOOLEAN);
68         case 'y':
69           return g_variant_type_copy (G_VARIANT_TYPE_BYTE);
70         case 'n':
71           return g_variant_type_copy (G_VARIANT_TYPE_INT16);
72         case 'q':
73           return g_variant_type_copy (G_VARIANT_TYPE_UINT16);
74         case 'i':
75           return g_variant_type_copy (G_VARIANT_TYPE_INT32);
76         case 'u':
77           return g_variant_type_copy (G_VARIANT_TYPE_UINT32);
78         case 'x':
79           return g_variant_type_copy (G_VARIANT_TYPE_INT64);
80         case 't':
81           return g_variant_type_copy (G_VARIANT_TYPE_UINT64);
82         case 'h':
83           return g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
84         case 'd':
85           return g_variant_type_copy (G_VARIANT_TYPE_DOUBLE);
86         case 's':
87           return g_variant_type_copy (G_VARIANT_TYPE_STRING);
88         case 'o':
89           return g_variant_type_copy (G_VARIANT_TYPE_OBJECT_PATH);
90         case 'g':
91           return g_variant_type_copy (G_VARIANT_TYPE_SIGNATURE);
92         case '?':
93           return g_variant_type_copy (G_VARIANT_TYPE_BASIC);
94         default:
95           g_assert_not_reached ();
96         }
97     }
98   else
99     {
100       GVariantType *result;
101 
102       switch (g_test_rand_int_range (0, definite ? 5 : 7))
103         {
104         case 0:
105           {
106             GVariantType *element;
107 
108             g_string_append_c (string, 'a');
109             g_string_append (description, "a of ");
110             element = append_type_string (string, description,
111                                           definite, depth);
112             result = g_variant_type_new_array (element);
113             g_variant_type_free (element);
114           }
115 
116           g_assert_true (g_variant_type_is_array (result));
117           break;
118 
119         case 1:
120           {
121             GVariantType *element;
122 
123             g_string_append_c (string, 'm');
124             g_string_append (description, "m of ");
125             element = append_type_string (string, description,
126                                           definite, depth);
127             result = g_variant_type_new_maybe (element);
128             g_variant_type_free (element);
129           }
130 
131           g_assert_true (g_variant_type_is_maybe (result));
132           break;
133 
134         case 2:
135           result = append_tuple_type_string (string, description,
136                                              definite, depth);
137 
138           g_assert_true (g_variant_type_is_tuple (result));
139           break;
140 
141         case 3:
142           {
143             GVariantType *key, *value;
144 
145             g_string_append_c (string, '{');
146             g_string_append (description, "e of [");
147             key = append_type_string (string, description, definite, 0);
148             g_string_append (description, ", ");
149             value = append_type_string (string, description, definite, depth);
150             g_string_append_c (description, ']');
151             g_string_append_c (string, '}');
152             result = g_variant_type_new_dict_entry (key, value);
153             g_variant_type_free (key);
154             g_variant_type_free (value);
155           }
156 
157           g_assert_true (g_variant_type_is_dict_entry (result));
158           break;
159 
160         case 4:
161           g_string_append_c (string, 'v');
162           g_string_append_c (description, 'V');
163           result = g_variant_type_copy (G_VARIANT_TYPE_VARIANT);
164           g_assert_true (g_variant_type_equal (result, G_VARIANT_TYPE_VARIANT));
165           break;
166 
167         case 5:
168           g_string_append_c (string, '*');
169           g_string_append_c (description, 'S');
170           result = g_variant_type_copy (G_VARIANT_TYPE_ANY);
171           g_assert_true (g_variant_type_equal (result, G_VARIANT_TYPE_ANY));
172           break;
173 
174         case 6:
175           g_string_append_c (string, 'r');
176           g_string_append_c (description, 'R');
177           result = g_variant_type_copy (G_VARIANT_TYPE_TUPLE);
178           g_assert_true (g_variant_type_is_tuple (result));
179           break;
180 
181         default:
182           g_assert_not_reached ();
183         }
184 
185       return result;
186     }
187 }
188 
189 static GVariantType *
append_tuple_type_string(GString * string,GString * description,gboolean definite,gint depth)190 append_tuple_type_string (GString  *string,
191                           GString  *description,
192                           gboolean  definite,
193                           gint      depth)
194 {
195   GVariantType *result, *other_result;
196   GVariantType **types;
197   gsize i, size;
198 
199   g_string_append_c (string, '(');
200   g_string_append (description, "t of [");
201 
202   size = g_test_rand_int_range (0, 20);
203   types = g_new (GVariantType *, size + 1);
204 
205   for (i = 0; i < size; i++)
206     {
207       types[i] = append_type_string (string, description, definite, depth);
208 
209       if (i < size - 1)
210         g_string_append (description, ", ");
211     }
212 
213   types[i] = NULL;
214 
215   g_string_append_c (description, ']');
216   g_string_append_c (string, ')');
217 
218   result = g_variant_type_new_tuple ((gpointer) types, size);
219   other_result = g_variant_type_new_tuple ((gpointer) types, -1);
220   g_assert_true (g_variant_type_equal (result, other_result));
221   g_variant_type_free (other_result);
222   for (i = 0; i < size; i++)
223     g_variant_type_free (types[i]);
224   g_free (types);
225 
226   return result;
227 }
228 
229 /* given a valid type string, make it invalid */
230 static gchar *
invalid_mutation(const gchar * type_string)231 invalid_mutation (const gchar *type_string)
232 {
233   gboolean have_parens, have_braces;
234 
235   /* it's valid, so '(' implies ')' and same for '{' and '}' */
236   have_parens = strchr (type_string, '(') != NULL;
237   have_braces = strchr (type_string, '{') != NULL;
238 
239   if (have_parens && have_braces && randomly (0.3))
240     {
241       /* swap a paren and a brace */
242       gchar *pp, *bp;
243       gint np, nb;
244       gchar p, b;
245       gchar *new;
246 
247       new = g_strdup (type_string);
248 
249       if (randomly (0.5))
250         p = '(', b = '{';
251       else
252         p = ')', b = '}';
253 
254       np = nb = 0;
255       pp = bp = new - 1;
256 
257       /* count number of parens/braces */
258       while ((pp = strchr (pp + 1, p))) np++;
259       while ((bp = strchr (bp + 1, b))) nb++;
260 
261       /* randomly pick one of each */
262       np = g_test_rand_int_range (0, np) + 1;
263       nb = g_test_rand_int_range (0, nb) + 1;
264 
265       /* find it */
266       pp = bp = new - 1;
267       while (np--) pp = strchr (pp + 1, p);
268       while (nb--) bp = strchr (bp + 1, b);
269 
270       /* swap */
271       g_assert_true (*bp == b && *pp == p);
272       *bp = p;
273       *pp = b;
274 
275       return new;
276     }
277 
278   if ((have_parens || have_braces) && randomly (0.3))
279     {
280       /* drop a paren/brace */
281       gchar *new;
282       gchar *pp;
283       gint np;
284       gchar p;
285 
286       if (have_parens)
287         if (randomly (0.5)) p = '('; else p = ')';
288       else
289         if (randomly (0.5)) p = '{'; else p = '}';
290 
291       new = g_strdup (type_string);
292 
293       np = 0;
294       pp = new - 1;
295       while ((pp = strchr (pp + 1, p))) np++;
296       np = g_test_rand_int_range (0, np) + 1;
297       pp = new - 1;
298       while (np--) pp = strchr (pp + 1, p);
299       g_assert_cmpint (*pp, ==, p);
300 
301       while (*pp)
302         {
303           *pp = *(pp + 1);
304           pp++;
305         }
306 
307       return new;
308     }
309 
310   /* else, perform a random mutation at a random point */
311   {
312     gint length, n;
313     gchar *new;
314     gchar p;
315 
316     if (randomly (0.3))
317       {
318         /* insert a paren/brace */
319         if (randomly (0.5))
320           if (randomly (0.5)) p = '('; else p = ')';
321         else
322           if (randomly (0.5)) p = '{'; else p = '}';
323       }
324     else if (randomly (0.5))
325       {
326         /* insert junk */
327         p = INVALIDS[g_test_rand_int_range (0, N_INVALIDS)];
328       }
329     else
330       {
331         /* truncate */
332         p = '\0';
333       }
334 
335 
336     length = strlen (type_string);
337     new = g_malloc (length + 2);
338     n = g_test_rand_int_range (0, length);
339     memcpy (new, type_string, n);
340     new[n] = p;
341     memcpy (new + n + 1, type_string + n, length - n);
342     new[length + 1] = '\0';
343 
344     return new;
345   }
346 }
347 
348 /* describe a type using the same language as is generated
349  * while generating the type with append_type_string
350  */
351 static gchar *
describe_type(const GVariantType * type)352 describe_type (const GVariantType *type)
353 {
354   gchar *result;
355 
356   if (g_variant_type_is_container (type))
357     {
358       g_assert_false (g_variant_type_is_basic (type));
359 
360       if (g_variant_type_is_array (type))
361         {
362           gchar *subtype = describe_type (g_variant_type_element (type));
363           result = g_strdup_printf ("a of %s", subtype);
364           g_free (subtype);
365         }
366       else if (g_variant_type_is_maybe (type))
367         {
368           gchar *subtype = describe_type (g_variant_type_element (type));
369           result = g_strdup_printf ("m of %s", subtype);
370           g_free (subtype);
371         }
372       else if (g_variant_type_is_tuple (type))
373         {
374           if (!g_variant_type_equal (type, G_VARIANT_TYPE_TUPLE))
375             {
376               const GVariantType *sub;
377               GString *string;
378               gsize i, length;
379 
380               string = g_string_new ("t of [");
381 
382               length = g_variant_type_n_items (type);
383               sub = g_variant_type_first (type);
384               for (i = 0; i < length; i++)
385                 {
386                   gchar *subtype = describe_type (sub);
387                   g_string_append (string, subtype);
388                   g_free (subtype);
389 
390                   if ((sub = g_variant_type_next (sub)))
391                     g_string_append (string, ", ");
392                 }
393               g_assert_null (sub);
394               g_string_append_c (string, ']');
395 
396               result = g_string_free (string, FALSE);
397             }
398           else
399             result = g_strdup ("R");
400         }
401       else if (g_variant_type_is_dict_entry (type))
402         {
403           gchar *key, *value, *key2, *value2;
404 
405           key = describe_type (g_variant_type_key (type));
406           value = describe_type (g_variant_type_value (type));
407           key2 = describe_type (g_variant_type_first (type));
408           value2 = describe_type (
409             g_variant_type_next (g_variant_type_first (type)));
410           g_assert_null (g_variant_type_next (g_variant_type_next (
411             g_variant_type_first (type))));
412           g_assert_cmpstr (key, ==, key2);
413           g_assert_cmpstr (value, ==, value2);
414           result = g_strjoin ("", "e of [", key, ", ", value, "]", NULL);
415           g_free (key2);
416           g_free (value2);
417           g_free (key);
418           g_free (value);
419         }
420       else if (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
421         {
422           result = g_strdup ("V");
423         }
424       else
425         g_assert_not_reached ();
426     }
427   else
428     {
429       if (g_variant_type_is_definite (type))
430         {
431           g_assert_true (g_variant_type_is_basic (type));
432 
433           if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
434             result = g_strdup ("b");
435           else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
436             result = g_strdup ("y");
437           else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
438             result = g_strdup ("n");
439           else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
440             result = g_strdup ("q");
441           else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
442             result = g_strdup ("i");
443           else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
444             result = g_strdup ("u");
445           else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
446             result = g_strdup ("x");
447           else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
448             result = g_strdup ("t");
449           else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
450             result = g_strdup ("h");
451           else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
452             result = g_strdup ("d");
453           else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
454             result = g_strdup ("s");
455           else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
456             result = g_strdup ("o");
457           else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
458             result = g_strdup ("g");
459           else
460             g_assert_not_reached ();
461         }
462       else
463         {
464           if (g_variant_type_equal (type, G_VARIANT_TYPE_ANY))
465             {
466               result = g_strdup ("S");
467             }
468           else if (g_variant_type_equal (type, G_VARIANT_TYPE_BASIC))
469             {
470               result = g_strdup ("?");
471             }
472           else
473             g_assert_not_reached ();
474         }
475     }
476 
477   return result;
478 }
479 
480 /* given a type string, replace one of the indefinite type characters in
481  * it with a matching type (possibly the same type).
482  */
483 static gchar *
generate_subtype(const gchar * type_string)484 generate_subtype (const gchar *type_string)
485 {
486   GVariantType *replacement;
487   GString *result, *junk;
488   gint l;
489   gsize length, n = 0;
490 
491   result = g_string_new (NULL);
492   junk = g_string_new (NULL);
493 
494   /* count the number of indefinite type characters */
495   for (length = 0; type_string[length]; length++)
496     n += type_string[length] == 'r' ||
497          type_string[length] == '?' ||
498          type_string[length] == '*';
499   /* length now is strlen (type_string) */
500 
501   /* pick one at random to replace */
502   n = g_test_rand_int_range (0, n) + 1;
503 
504   /* find it */
505   l = -1;
506   while (n--) l += strcspn (type_string + l + 1, "r?*") + 1;
507   g_assert_true (type_string[l] == 'r' ||
508                  type_string[l] == '?' ||
509                  type_string[l] == '*');
510 
511   /* store up to that point in a GString */
512   g_string_append_len (result, type_string, l);
513 
514   /* then store the replacement in the GString */
515   if (type_string[l] == 'r')
516     replacement = append_tuple_type_string (result, junk, FALSE, 3);
517 
518   else if (type_string[l] == '?')
519     replacement = append_type_string (result, junk, FALSE, 0);
520 
521   else if (type_string[l] == '*')
522     replacement = append_type_string (result, junk, FALSE, 3);
523 
524   else
525     g_assert_not_reached ();
526 
527   /* ensure the replacement has the proper type */
528   g_assert_true (g_variant_type_is_subtype_of (replacement,
529                                                (gpointer) &type_string[l]));
530 
531   /* store the rest from the original type string */
532   g_string_append (result, type_string + l + 1);
533 
534   g_variant_type_free (replacement);
535   g_string_free (junk, TRUE);
536 
537   return g_string_free (result, FALSE);
538 }
539 
540 struct typestack
541 {
542   const GVariantType *type;
543   struct typestack *parent;
544 };
545 
546 /* given an indefinite type string, replace one of the indefinite
547  * characters in it with a matching type and ensure that the result is a
548  * subtype of the original.  repeat.
549  */
550 static void
subtype_check(const gchar * type_string,struct typestack * parent_ts)551 subtype_check (const gchar      *type_string,
552                struct typestack *parent_ts)
553 {
554   struct typestack ts, *node;
555   gchar *subtype;
556   gint depth = 0;
557 
558   subtype = generate_subtype (type_string);
559 
560   ts.type = G_VARIANT_TYPE (subtype);
561   ts.parent = parent_ts;
562 
563   for (node = &ts; node; node = node->parent)
564     {
565       /* this type should be a subtype of each parent type */
566       g_assert_true (g_variant_type_is_subtype_of (ts.type, node->type));
567 
568       /* it should only be a supertype when it is exactly equal */
569       g_assert_true (g_variant_type_is_subtype_of (node->type, ts.type) ==
570                      g_variant_type_equal (ts.type, node->type));
571 
572       depth++;
573     }
574 
575   if (!g_variant_type_is_definite (ts.type) && depth < 5)
576     {
577       /* the type is still indefinite and we haven't repeated too many
578        * times.  go once more.
579        */
580 
581       subtype_check (subtype, &ts);
582     }
583 
584   g_free (subtype);
585 }
586 
587 static void
test_gvarianttype(void)588 test_gvarianttype (void)
589 {
590   gsize i;
591 
592   for (i = 0; i < 2000; i++)
593     {
594       GString *type_string, *description;
595       GVariantType *type, *other_type;
596       const GVariantType *ctype;
597       gchar *invalid;
598       gchar *desc;
599 
600       type_string = g_string_new (NULL);
601       description = g_string_new (NULL);
602 
603       /* generate a random type, its type string and a description
604        *
605        * exercises type constructor functions and g_variant_type_copy()
606        */
607       type = append_type_string (type_string, description, FALSE, 6);
608 
609       /* convert the type string to a type and ensure that it is equal
610        * to the one produced with the type constructor routines
611        */
612       ctype = G_VARIANT_TYPE (type_string->str);
613       g_assert_true (g_variant_type_equal (ctype, type));
614       g_assert_cmpuint (g_variant_type_hash (ctype), ==, g_variant_type_hash (type));
615       g_assert_true (g_variant_type_is_subtype_of (ctype, type));
616       g_assert_true (g_variant_type_is_subtype_of (type, ctype));
617 
618       /* check if the type is indefinite */
619       if (!g_variant_type_is_definite (type))
620         {
621           struct typestack ts = { type, NULL };
622 
623           /* if it is indefinite, then replace one of the indefinite
624            * characters with a matching type and ensure that the result
625            * is a subtype of the original type.  repeat.
626            */
627           subtype_check (type_string->str, &ts);
628         }
629       else
630         /* ensure that no indefinite characters appear */
631         g_assert_cmpint (strcspn (type_string->str, "r?*"), ==, type_string->len);
632 
633 
634       /* describe the type.
635        *
636        * exercises the type iterator interface
637        */
638       desc = describe_type (type);
639 
640       /* make sure the description matches */
641       g_assert_cmpstr (desc, ==, description->str);
642       g_free (desc);
643 
644       /* make an invalid mutation to the type and make sure the type
645        * validation routines catch it */
646       invalid = invalid_mutation (type_string->str);
647       g_assert_true (g_variant_type_string_is_valid (type_string->str));
648       g_assert_false (g_variant_type_string_is_valid (invalid));
649       g_free (invalid);
650 
651       /* concatenate another type to the type string and ensure that
652        * the result is recognised as being invalid
653        */
654       other_type = append_type_string (type_string, description, FALSE, 2);
655 
656       g_string_free (description, TRUE);
657       g_string_free (type_string, TRUE);
658       g_variant_type_free (other_type);
659       g_variant_type_free (type);
660     }
661 }
662 
663 /* Test that scanning a deeply recursive type string doesn’t exhaust our
664  * stack space (which it would if the type string scanner was recursive). */
665 static void
test_gvarianttype_string_scan_recursion_tuple(void)666 test_gvarianttype_string_scan_recursion_tuple (void)
667 {
668   gchar *type_string = NULL;
669   gsize type_string_len = 1000001;  /* not including nul terminator */
670   gsize i;
671 
672   /* Build a long type string of ‘((…u…))’. */
673   type_string = g_new0 (gchar, type_string_len + 1);
674   for (i = 0; i < type_string_len; i++)
675     {
676       if (i < type_string_len / 2)
677         type_string[i] = '(';
678       else if (i == type_string_len / 2)
679         type_string[i] = 'u';
680       else
681         type_string[i] = ')';
682     }
683 
684   /* Goes (way) over allowed recursion limit. */
685   g_assert_false (g_variant_type_string_is_valid (type_string));
686 
687   g_free (type_string);
688 }
689 
690 /* Same as above, except with an array rather than a tuple. */
691 static void
test_gvarianttype_string_scan_recursion_array(void)692 test_gvarianttype_string_scan_recursion_array (void)
693 {
694   gchar *type_string = NULL;
695   gsize type_string_len = 1000001;  /* not including nul terminator */
696   gsize i;
697 
698   /* Build a long type string of ‘aaa…aau’. */
699   type_string = g_new0 (gchar, type_string_len + 1);
700   for (i = 0; i < type_string_len; i++)
701     {
702       if (i < type_string_len - 1)
703         type_string[i] = 'a';
704       else
705         type_string[i] = 'u';
706     }
707 
708   /* Goes (way) over allowed recursion limit. */
709   g_assert_false (g_variant_type_string_is_valid (type_string));
710 
711   g_free (type_string);
712 }
713 
714 #define ALIGNED(x, y)   (((x + (y - 1)) / y) * y)
715 
716 /* do our own calculation of the fixed_size and alignment of a type
717  * using a simple algorithm to make sure the "fancy" one in the
718  * implementation is correct.
719  */
720 static void
calculate_type_info(const GVariantType * type,gsize * fixed_size,guint * alignment)721 calculate_type_info (const GVariantType *type,
722                      gsize              *fixed_size,
723                      guint              *alignment)
724 {
725   if (g_variant_type_is_array (type) ||
726       g_variant_type_is_maybe (type))
727     {
728       calculate_type_info (g_variant_type_element (type), NULL, alignment);
729 
730       if (fixed_size)
731         *fixed_size = 0;
732     }
733   else if (g_variant_type_is_tuple (type) ||
734            g_variant_type_is_dict_entry (type))
735     {
736       if (g_variant_type_n_items (type))
737         {
738           const GVariantType *sub;
739           gboolean variable;
740           gsize size;
741           guint al;
742 
743           variable = FALSE;
744           size = 0;
745           al = 0;
746 
747           sub = g_variant_type_first (type);
748           do
749             {
750               gsize this_fs;
751               guint this_al;
752 
753               calculate_type_info (sub, &this_fs, &this_al);
754 
755               al = MAX (al, this_al);
756 
757               if (!this_fs)
758                 {
759                   variable = TRUE;
760                   size = 0;
761                 }
762 
763               if (!variable)
764                 {
765                   size = ALIGNED (size, this_al);
766                   size += this_fs;
767                 }
768             }
769           while ((sub = g_variant_type_next (sub)));
770 
771           size = ALIGNED (size, al);
772 
773           if (alignment)
774             *alignment = al;
775 
776           if (fixed_size)
777             *fixed_size = size;
778         }
779       else
780         {
781           if (fixed_size)
782             *fixed_size = 1;
783 
784           if (alignment)
785             *alignment = 1;
786         }
787     }
788   else
789     {
790       gint fs, al;
791 
792       if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN) ||
793           g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
794         {
795           al = fs = 1;
796         }
797 
798       else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16) ||
799                g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
800         {
801           al = fs = 2;
802         }
803 
804       else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32) ||
805                g_variant_type_equal (type, G_VARIANT_TYPE_UINT32) ||
806                g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
807         {
808           al = fs = 4;
809         }
810 
811       else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64) ||
812                g_variant_type_equal (type, G_VARIANT_TYPE_UINT64) ||
813                g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
814         {
815           al = fs = 8;
816         }
817       else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING) ||
818                g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH) ||
819                g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
820         {
821           al = 1;
822           fs = 0;
823         }
824       else if (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
825         {
826           al = 8;
827           fs = 0;
828         }
829       else
830         g_assert_not_reached ();
831 
832       if (fixed_size)
833         *fixed_size = fs;
834 
835       if (alignment)
836         *alignment = al;
837     }
838 }
839 
840 /* same as the describe_type() function above, but iterates over
841  * typeinfo instead of types.
842  */
843 static gchar *
describe_info(GVariantTypeInfo * info)844 describe_info (GVariantTypeInfo *info)
845 {
846   gchar *result;
847 
848   switch (g_variant_type_info_get_type_char (info))
849     {
850     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
851       {
852         gchar *element;
853 
854         element = describe_info (g_variant_type_info_element (info));
855         result = g_strdup_printf ("m of %s", element);
856         g_free (element);
857       }
858       break;
859 
860     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
861       {
862         gchar *element;
863 
864         element = describe_info (g_variant_type_info_element (info));
865         result = g_strdup_printf ("a of %s", element);
866         g_free (element);
867       }
868       break;
869 
870     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
871       {
872         const gchar *sep = "";
873         GString *string;
874         gsize i, length;
875 
876         string = g_string_new ("t of [");
877         length = g_variant_type_info_n_members (info);
878 
879         for (i = 0; i < length; i++)
880           {
881             const GVariantMemberInfo *minfo;
882             gchar *subtype;
883 
884             g_string_append (string, sep);
885             sep = ", ";
886 
887             minfo = g_variant_type_info_member_info (info, i);
888             subtype = describe_info (minfo->type_info);
889             g_string_append (string, subtype);
890             g_free (subtype);
891           }
892 
893         g_string_append_c (string, ']');
894 
895         result = g_string_free (string, FALSE);
896       }
897       break;
898 
899     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
900       {
901         const GVariantMemberInfo *keyinfo, *valueinfo;
902         gchar *key, *value;
903 
904         g_assert_cmpint (g_variant_type_info_n_members (info), ==, 2);
905         keyinfo = g_variant_type_info_member_info (info, 0);
906         valueinfo = g_variant_type_info_member_info (info, 1);
907         key = describe_info (keyinfo->type_info);
908         value = describe_info (valueinfo->type_info);
909         result = g_strjoin ("", "e of [", key, ", ", value, "]", NULL);
910         g_free (key);
911         g_free (value);
912       }
913       break;
914 
915     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
916       result = g_strdup ("V");
917       break;
918 
919     default:
920       result = g_strdup (g_variant_type_info_get_type_string (info));
921       g_assert_cmpint (strlen (result), ==, 1);
922       break;
923     }
924 
925   return result;
926 }
927 
928 /* check that the O(1) method of calculating offsets meshes with the
929  * results of simple iteration.
930  */
931 static void
check_offsets(GVariantTypeInfo * info,const GVariantType * type)932 check_offsets (GVariantTypeInfo   *info,
933                const GVariantType *type)
934 {
935   gsize flavour, length;
936 
937   length = g_variant_type_info_n_members (info);
938   g_assert_cmpuint (length, ==, g_variant_type_n_items (type));
939 
940   /* the 'flavour' is the low order bits of the ending point of
941    * variable-size items in the tuple.  this lets us test that the type
942    * info is correct for various starting alignments.
943    */
944   for (flavour = 0; flavour < 8; flavour++)
945     {
946       const GVariantType *subtype;
947       gsize last_offset_index;
948       gsize last_offset;
949       gsize position;
950       gsize i;
951 
952       subtype = g_variant_type_first (type);
953       last_offset_index = -1;
954       last_offset = 0;
955       position = 0;
956 
957       /* go through the tuple, keeping track of our position */
958       for (i = 0; i < length; i++)
959         {
960           gsize fixed_size;
961           guint alignment;
962 
963           calculate_type_info (subtype, &fixed_size, &alignment);
964 
965           position = ALIGNED (position, alignment);
966 
967           /* compare our current aligned position (ie: the start of this
968            * item) to the start offset that would be calculated if we
969            * used the type info
970            */
971           {
972             const GVariantMemberInfo *member;
973             gsize start;
974 
975             member = g_variant_type_info_member_info (info, i);
976             g_assert_cmpint (member->i, ==, last_offset_index);
977 
978             /* do the calculation using the typeinfo */
979             start = last_offset;
980             start += member->a;
981             start &= member->b;
982             start |= member->c;
983 
984             /* did we reach the same spot? */
985             g_assert_cmpint (start, ==, position);
986           }
987 
988           if (fixed_size)
989             {
990               /* fixed size.  add that size. */
991               position += fixed_size;
992             }
993           else
994             {
995               /* variable size.  do the flavouring. */
996               while ((position & 0x7) != flavour)
997                 position++;
998 
999               /* and store the offset, just like it would be in the
1000                * serialized data.
1001                */
1002               last_offset = position;
1003               last_offset_index++;
1004             }
1005 
1006           /* next type */
1007           subtype = g_variant_type_next (subtype);
1008         }
1009 
1010       /* make sure we used up exactly all the types */
1011       g_assert_null (subtype);
1012     }
1013 }
1014 
1015 static void
test_gvarianttypeinfo(void)1016 test_gvarianttypeinfo (void)
1017 {
1018   gsize i;
1019 
1020   for (i = 0; i < 2000; i++)
1021     {
1022       GString *type_string, *description;
1023       gsize fixed_size1, fixed_size2;
1024       guint alignment1, alignment2;
1025       GVariantTypeInfo *info;
1026       GVariantType *type;
1027       gchar *desc;
1028 
1029       type_string = g_string_new (NULL);
1030       description = g_string_new (NULL);
1031 
1032       /* random type */
1033       type = append_type_string (type_string, description, TRUE, 6);
1034 
1035       /* create a typeinfo for it */
1036       info = g_variant_type_info_get (type);
1037 
1038       /* make sure the typeinfo has the right type string */
1039       g_assert_cmpstr (g_variant_type_info_get_type_string (info), ==,
1040                        type_string->str);
1041 
1042       /* calculate the alignment and fixed size, compare to the
1043        * typeinfo's calculations
1044        */
1045       calculate_type_info (type, &fixed_size1, &alignment1);
1046       g_variant_type_info_query (info, &alignment2, &fixed_size2);
1047       g_assert_cmpint (fixed_size1, ==, fixed_size2);
1048       g_assert_cmpint (alignment1, ==, alignment2 + 1);
1049 
1050       /* test the iteration functions over typeinfo structures by
1051        * "describing" the typeinfo and verifying equality.
1052        */
1053       desc = describe_info (info);
1054       g_assert_cmpstr (desc, ==, description->str);
1055 
1056       /* do extra checks for containers */
1057       if (g_variant_type_is_array (type) ||
1058           g_variant_type_is_maybe (type))
1059         {
1060           const GVariantType *element;
1061           gsize efs1, efs2;
1062           guint ea1, ea2;
1063 
1064           element = g_variant_type_element (type);
1065           calculate_type_info (element, &efs1, &ea1);
1066           g_variant_type_info_query_element (info, &ea2, &efs2);
1067           g_assert_cmpint (efs1, ==, efs2);
1068           g_assert_cmpint (ea1, ==, ea2 + 1);
1069 
1070           g_assert_cmpint (ea1, ==, alignment1);
1071           g_assert_cmpint (0, ==, fixed_size1);
1072         }
1073       else if (g_variant_type_is_tuple (type) ||
1074                g_variant_type_is_dict_entry (type))
1075         {
1076           /* make sure the "magic constants" are working */
1077           check_offsets (info, type);
1078         }
1079 
1080       g_string_free (type_string, TRUE);
1081       g_string_free (description, TRUE);
1082       g_variant_type_info_unref (info);
1083       g_variant_type_free (type);
1084       g_free (desc);
1085     }
1086 
1087   g_variant_type_info_assert_no_infos ();
1088 }
1089 
1090 #define MAX_FIXED_MULTIPLIER    256
1091 #define MAX_INSTANCE_SIZE       1024
1092 #define MAX_ARRAY_CHILDREN      128
1093 #define MAX_TUPLE_CHILDREN      128
1094 
1095 /* this function generates a random type such that all characteristics
1096  * that are "interesting" to the serializer are tested.
1097  *
1098  * this basically means:
1099  *   - test different alignments
1100  *   - test variable sized items and fixed sized items
1101  *   - test different fixed sizes
1102  */
1103 static gchar *
random_type_string(void)1104 random_type_string (void)
1105 {
1106   const guchar base_types[] = "ynix";
1107   guchar base_type;
1108 
1109   base_type = base_types[g_test_rand_int_range (0, 4)];
1110 
1111   if (g_test_rand_bit ())
1112     /* construct a fixed-sized type */
1113     {
1114       char type_string[MAX_FIXED_MULTIPLIER];
1115       guint multiplier;
1116       gsize i = 0;
1117 
1118       multiplier = g_test_rand_int_range (1, sizeof type_string - 1);
1119 
1120       type_string[i++] = '(';
1121       while (multiplier--)
1122         type_string[i++] = base_type;
1123       type_string[i++] = ')';
1124 
1125       return g_strndup (type_string, i);
1126     }
1127   else
1128     /* construct a variable-sized type */
1129     {
1130       char type_string[2] = { 'a', base_type };
1131 
1132       return g_strndup (type_string, 2);
1133     }
1134 }
1135 
1136 typedef struct
1137 {
1138   GVariantTypeInfo *type_info;
1139   guint alignment;
1140   gsize size;
1141   gboolean is_fixed_sized;
1142 
1143   guint32 seed;
1144 
1145 #define INSTANCE_MAGIC    1287582829
1146   guint magic;
1147 } RandomInstance;
1148 
1149 static RandomInstance *
random_instance(GVariantTypeInfo * type_info)1150 random_instance (GVariantTypeInfo *type_info)
1151 {
1152   RandomInstance *instance;
1153 
1154   instance = g_slice_new (RandomInstance);
1155 
1156   if (type_info == NULL)
1157     {
1158       gchar *str = random_type_string ();
1159       instance->type_info = g_variant_type_info_get (G_VARIANT_TYPE (str));
1160       g_free (str);
1161     }
1162   else
1163     instance->type_info = g_variant_type_info_ref (type_info);
1164 
1165   instance->seed = g_test_rand_int ();
1166 
1167   g_variant_type_info_query (instance->type_info,
1168                              &instance->alignment,
1169                              &instance->size);
1170 
1171   instance->is_fixed_sized = instance->size != 0;
1172 
1173   if (!instance->is_fixed_sized)
1174     instance->size = g_test_rand_int_range (0, MAX_INSTANCE_SIZE);
1175 
1176   instance->magic = INSTANCE_MAGIC;
1177 
1178   return instance;
1179 }
1180 
1181 static void
random_instance_free(RandomInstance * instance)1182 random_instance_free (RandomInstance *instance)
1183 {
1184   g_variant_type_info_unref (instance->type_info);
1185   g_slice_free (RandomInstance, instance);
1186 }
1187 
1188 static void
append_instance_size(RandomInstance * instance,gsize * offset)1189 append_instance_size (RandomInstance *instance,
1190                       gsize          *offset)
1191 {
1192   *offset += (-*offset) & instance->alignment;
1193   *offset += instance->size;
1194 }
1195 
1196 static void
random_instance_write(RandomInstance * instance,guchar * buffer)1197 random_instance_write (RandomInstance *instance,
1198                        guchar         *buffer)
1199 {
1200   GRand *rand;
1201   gsize i;
1202 
1203   g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
1204 
1205   rand = g_rand_new_with_seed (instance->seed);
1206   for (i = 0; i < instance->size; i++)
1207     buffer[i] = g_rand_int (rand);
1208   g_rand_free (rand);
1209 }
1210 
1211 static void
append_instance_data(RandomInstance * instance,guchar ** buffer)1212 append_instance_data (RandomInstance  *instance,
1213                       guchar         **buffer)
1214 {
1215   while (((gsize) *buffer) & instance->alignment)
1216     *(*buffer)++ = '\0';
1217 
1218   random_instance_write (instance, *buffer);
1219   *buffer += instance->size;
1220 }
1221 
1222 static gboolean
random_instance_assert(RandomInstance * instance,guchar * buffer,gsize size)1223 random_instance_assert (RandomInstance *instance,
1224                         guchar         *buffer,
1225                         gsize           size)
1226 {
1227   GRand *rand;
1228   gsize i;
1229 
1230   g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
1231   g_assert_cmpint (size, ==, instance->size);
1232 
1233   rand = g_rand_new_with_seed (instance->seed);
1234   for (i = 0; i < instance->size; i++)
1235     {
1236       guchar byte = g_rand_int (rand);
1237 
1238       g_assert_cmpuint (buffer[i], ==, byte);
1239     }
1240   g_rand_free (rand);
1241 
1242   return i == instance->size;
1243 }
1244 
1245 static gboolean
random_instance_check(RandomInstance * instance,guchar * buffer,gsize size)1246 random_instance_check (RandomInstance *instance,
1247                        guchar         *buffer,
1248                        gsize           size)
1249 {
1250   GRand *rand;
1251   gsize i;
1252 
1253   g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
1254 
1255   if (size != instance->size)
1256     return FALSE;
1257 
1258   rand = g_rand_new_with_seed (instance->seed);
1259   for (i = 0; i < instance->size; i++)
1260     if (buffer[i] != (guchar) g_rand_int (rand))
1261       break;
1262   g_rand_free (rand);
1263 
1264   return i == instance->size;
1265 }
1266 
1267 static void
random_instance_filler(GVariantSerialised * serialised,gpointer data)1268 random_instance_filler (GVariantSerialised *serialised,
1269                         gpointer            data)
1270 {
1271   RandomInstance *instance = data;
1272 
1273   g_assert_cmpuint (instance->magic, ==, INSTANCE_MAGIC);
1274 
1275   if (serialised->type_info == NULL)
1276     serialised->type_info = instance->type_info;
1277 
1278   if (serialised->size == 0)
1279     serialised->size = instance->size;
1280 
1281   serialised->depth = 0;
1282 
1283   g_assert_true (serialised->type_info == instance->type_info);
1284   g_assert_cmpuint (serialised->size, ==, instance->size);
1285 
1286   if (serialised->data)
1287     random_instance_write (instance, serialised->data);
1288 }
1289 
1290 static gsize
calculate_offset_size(gsize body_size,gsize n_offsets)1291 calculate_offset_size (gsize body_size,
1292                        gsize n_offsets)
1293 {
1294   if (body_size == 0)
1295     return 0;
1296 
1297   if (body_size + n_offsets <= G_MAXUINT8)
1298     return 1;
1299 
1300   if (body_size + 2 * n_offsets <= G_MAXUINT16)
1301     return 2;
1302 
1303   if (body_size + 4 * n_offsets <= G_MAXUINT32)
1304     return 4;
1305 
1306   /* the test case won't generate anything bigger */
1307   g_assert_not_reached ();
1308 }
1309 
1310 static gpointer
flavoured_malloc(gsize size,gsize flavour)1311 flavoured_malloc (gsize size, gsize flavour)
1312 {
1313   g_assert_cmpuint (flavour, <, 8);
1314 
1315   if (size == 0)
1316     return NULL;
1317 
1318   return ((gchar *) g_malloc (size + flavour)) + flavour;
1319 }
1320 
1321 static void
flavoured_free(gpointer data,gsize flavour)1322 flavoured_free (gpointer data,
1323                 gsize flavour)
1324 {
1325   if (!data)
1326     return;
1327   g_free (((gchar *) data) - flavour);
1328 }
1329 
1330 static gpointer
align_malloc(gsize size)1331 align_malloc (gsize size)
1332 {
1333   gpointer mem;
1334 
1335 #ifdef HAVE_POSIX_MEMALIGN
1336   if (posix_memalign (&mem, 8, size))
1337     g_error ("posix_memalign failed");
1338 #else
1339   /* NOTE: there may be platforms that lack posix_memalign() and also
1340    * have malloc() that returns non-8-aligned.  if so, we need to try
1341    * harder here.
1342    */
1343   mem = malloc (size);
1344 #endif
1345 
1346   return mem;
1347 }
1348 
1349 static void
align_free(gpointer mem)1350 align_free (gpointer mem)
1351 {
1352   free (mem);
1353 }
1354 
1355 static void
append_offset(guchar ** offset_ptr,gsize offset,guint offset_size)1356 append_offset (guchar **offset_ptr,
1357                gsize    offset,
1358                guint    offset_size)
1359 {
1360   union
1361   {
1362     guchar bytes[sizeof (gsize)];
1363     gsize integer;
1364   } tmpvalue;
1365 
1366   tmpvalue.integer = GSIZE_TO_LE (offset);
1367   memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
1368   *offset_ptr += offset_size;
1369 }
1370 
1371 static void
prepend_offset(guchar ** offset_ptr,gsize offset,guint offset_size)1372 prepend_offset (guchar **offset_ptr,
1373                 gsize    offset,
1374                 guint    offset_size)
1375 {
1376   union
1377   {
1378     guchar bytes[sizeof (gsize)];
1379     gsize integer;
1380   } tmpvalue;
1381 
1382   *offset_ptr -= offset_size;
1383   tmpvalue.integer = GSIZE_TO_LE (offset);
1384   memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
1385 }
1386 
1387 static void
test_maybe(void)1388 test_maybe (void)
1389 {
1390   GVariantTypeInfo *type_info;
1391   RandomInstance *instance;
1392   gsize needed_size;
1393   guchar *data;
1394 
1395   instance = random_instance (NULL);
1396 
1397   {
1398     const gchar *element;
1399     gchar *tmp;
1400 
1401     element = g_variant_type_info_get_type_string (instance->type_info);
1402     tmp = g_strdup_printf ("m%s", element);
1403     type_info = g_variant_type_info_get (G_VARIANT_TYPE (tmp));
1404     g_free (tmp);
1405   }
1406 
1407   needed_size = g_variant_serialiser_needed_size (type_info,
1408                                                   random_instance_filler,
1409                                                   NULL, 0);
1410   g_assert_cmpint (needed_size, ==, 0);
1411 
1412   needed_size = g_variant_serialiser_needed_size (type_info,
1413                                                   random_instance_filler,
1414                                                   (gpointer *) &instance, 1);
1415 
1416   if (instance->is_fixed_sized)
1417     g_assert_cmpint (needed_size, ==, instance->size);
1418   else
1419     g_assert_cmpint (needed_size, ==, instance->size + 1);
1420 
1421   {
1422     guchar *ptr;
1423 
1424     ptr = data = align_malloc (needed_size);
1425     append_instance_data (instance, &ptr);
1426 
1427     if (!instance->is_fixed_sized)
1428       *ptr++ = '\0';
1429 
1430     g_assert_cmpint (ptr - data, ==, needed_size);
1431   }
1432 
1433   {
1434     guint alignment;
1435     gsize flavour;
1436 
1437     alignment = (instance->alignment & ALIGN_BITS) + 1;
1438 
1439     for (flavour = 0; flavour < 8; flavour += alignment)
1440       {
1441         GVariantSerialised serialised;
1442         GVariantSerialised child;
1443 
1444         serialised.type_info = type_info;
1445         serialised.data = flavoured_malloc (needed_size, flavour);
1446         serialised.size = needed_size;
1447         serialised.depth = 0;
1448 
1449         g_variant_serialiser_serialise (serialised,
1450                                         random_instance_filler,
1451                                         (gpointer *) &instance, 1);
1452         child = g_variant_serialised_get_child (serialised, 0);
1453         g_assert_true (child.type_info == instance->type_info);
1454         random_instance_assert (instance, child.data, child.size);
1455         g_variant_type_info_unref (child.type_info);
1456         flavoured_free (serialised.data, flavour);
1457       }
1458   }
1459 
1460   g_variant_type_info_unref (type_info);
1461   random_instance_free (instance);
1462   align_free (data);
1463 }
1464 
1465 static void
test_maybes(void)1466 test_maybes (void)
1467 {
1468   gsize i;
1469 
1470   for (i = 0; i < 1000; i++)
1471     test_maybe ();
1472 
1473   g_variant_type_info_assert_no_infos ();
1474 }
1475 
1476 static void
test_array(void)1477 test_array (void)
1478 {
1479   GVariantTypeInfo *element_info;
1480   GVariantTypeInfo *array_info;
1481   RandomInstance **instances;
1482   gsize needed_size;
1483   gsize offset_size;
1484   guint n_children;
1485   guchar *data;
1486 
1487   {
1488     gchar *element_type, *array_type;
1489 
1490     element_type = random_type_string ();
1491     array_type = g_strdup_printf ("a%s", element_type);
1492 
1493     element_info = g_variant_type_info_get (G_VARIANT_TYPE (element_type));
1494     array_info = g_variant_type_info_get (G_VARIANT_TYPE (array_type));
1495     g_assert_true (g_variant_type_info_element (array_info) == element_info);
1496 
1497     g_free (element_type);
1498     g_free (array_type);
1499   }
1500 
1501   {
1502     gsize i;
1503 
1504     n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
1505     instances = g_new (RandomInstance *, n_children);
1506     for (i = 0; i < n_children; i++)
1507       instances[i] = random_instance (element_info);
1508   }
1509 
1510   needed_size = g_variant_serialiser_needed_size (array_info,
1511                                                   random_instance_filler,
1512                                                   (gpointer *) instances,
1513                                                   n_children);
1514 
1515   {
1516     gsize element_fixed_size;
1517     gsize body_size = 0;
1518     gsize i;
1519 
1520     for (i = 0; i < n_children; i++)
1521       append_instance_size (instances[i], &body_size);
1522 
1523     g_variant_type_info_query (element_info, NULL, &element_fixed_size);
1524 
1525     if (!element_fixed_size)
1526       {
1527         offset_size = calculate_offset_size (body_size, n_children);
1528 
1529         if (offset_size == 0)
1530           offset_size = 1;
1531       }
1532     else
1533       offset_size = 0;
1534 
1535     g_assert_cmpint (needed_size, ==, body_size + n_children * offset_size);
1536   }
1537 
1538   {
1539     guchar *offset_ptr, *body_ptr;
1540     gsize i;
1541 
1542     body_ptr = data = align_malloc (needed_size);
1543     offset_ptr = body_ptr + needed_size - offset_size * n_children;
1544 
1545     for (i = 0; i < n_children; i++)
1546       {
1547         append_instance_data (instances[i], &body_ptr);
1548         append_offset (&offset_ptr, body_ptr - data, offset_size);
1549       }
1550 
1551     g_assert_true (body_ptr == data + needed_size - offset_size * n_children);
1552     g_assert_true (offset_ptr == data + needed_size);
1553   }
1554 
1555   {
1556     guint alignment;
1557     gsize flavour;
1558     gsize i;
1559 
1560     g_variant_type_info_query (array_info, &alignment, NULL);
1561     alignment = (alignment & ALIGN_BITS) + 1;
1562 
1563     for (flavour = 0; flavour < 8; flavour += alignment)
1564       {
1565         GVariantSerialised serialised;
1566 
1567         serialised.type_info = array_info;
1568         serialised.data = flavoured_malloc (needed_size, flavour);
1569         serialised.size = needed_size;
1570         serialised.depth = 0;
1571 
1572         g_variant_serialiser_serialise (serialised, random_instance_filler,
1573                                         (gpointer *) instances, n_children);
1574 
1575         if (serialised.size)
1576           g_assert_cmpint (memcmp (serialised.data, data, serialised.size), ==, 0);
1577 
1578         g_assert_cmpuint (g_variant_serialised_n_children (serialised), ==, n_children);
1579 
1580         for (i = 0; i < n_children; i++)
1581           {
1582             GVariantSerialised child;
1583 
1584             child = g_variant_serialised_get_child (serialised, i);
1585             g_assert_true (child.type_info == instances[i]->type_info);
1586             random_instance_assert (instances[i], child.data, child.size);
1587             g_variant_type_info_unref (child.type_info);
1588           }
1589 
1590         flavoured_free (serialised.data, flavour);
1591       }
1592   }
1593 
1594   {
1595     gsize i;
1596 
1597     for (i = 0; i < n_children; i++)
1598       random_instance_free (instances[i]);
1599     g_free (instances);
1600   }
1601 
1602   g_variant_type_info_unref (element_info);
1603   g_variant_type_info_unref (array_info);
1604   align_free (data);
1605 }
1606 
1607 static void
test_arrays(void)1608 test_arrays (void)
1609 {
1610   gsize i;
1611 
1612   for (i = 0; i < 100; i++)
1613     test_array ();
1614 
1615   g_variant_type_info_assert_no_infos ();
1616 }
1617 
1618 static void
test_tuple(void)1619 test_tuple (void)
1620 {
1621   GVariantTypeInfo *type_info;
1622   RandomInstance **instances;
1623   gboolean fixed_size;
1624   gsize needed_size;
1625   gsize offset_size;
1626   guint n_children;
1627   guint alignment;
1628   guchar *data;
1629 
1630   n_children = g_test_rand_int_range (0, MAX_TUPLE_CHILDREN);
1631   instances = g_new (RandomInstance *, n_children);
1632 
1633   {
1634     GString *type_string;
1635     gsize i;
1636 
1637     fixed_size = TRUE;
1638     alignment = 0;
1639 
1640     type_string = g_string_new ("(");
1641     for (i = 0; i < n_children; i++)
1642       {
1643         const gchar *str;
1644 
1645         instances[i] = random_instance (NULL);
1646 
1647         alignment |= instances[i]->alignment;
1648         if (!instances[i]->is_fixed_sized)
1649           fixed_size = FALSE;
1650 
1651         str = g_variant_type_info_get_type_string (instances[i]->type_info);
1652         g_string_append (type_string, str);
1653       }
1654     g_string_append_c (type_string, ')');
1655 
1656     type_info = g_variant_type_info_get (G_VARIANT_TYPE (type_string->str));
1657     g_string_free (type_string, TRUE);
1658   }
1659 
1660   needed_size = g_variant_serialiser_needed_size (type_info,
1661                                                   random_instance_filler,
1662                                                   (gpointer *) instances,
1663                                                   n_children);
1664   {
1665     gsize body_size = 0;
1666     gsize offsets = 0;
1667     gsize i;
1668 
1669     for (i = 0; i < n_children; i++)
1670       {
1671         append_instance_size (instances[i], &body_size);
1672 
1673         if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1674           offsets++;
1675       }
1676 
1677     if (fixed_size)
1678       {
1679         body_size += (-body_size) & alignment;
1680 
1681         g_assert_true ((body_size == 0) == (n_children == 0));
1682         if (n_children == 0)
1683           body_size = 1;
1684       }
1685 
1686     offset_size = calculate_offset_size (body_size, offsets);
1687     g_assert_cmpint (needed_size, ==, body_size + offsets * offset_size);
1688   }
1689 
1690   {
1691     guchar *body_ptr;
1692     guchar *ofs_ptr;
1693     gsize i;
1694 
1695     body_ptr = data = align_malloc (needed_size);
1696     ofs_ptr = body_ptr + needed_size;
1697 
1698     for (i = 0; i < n_children; i++)
1699       {
1700         append_instance_data (instances[i], &body_ptr);
1701 
1702         if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1703           prepend_offset (&ofs_ptr, body_ptr - data, offset_size);
1704       }
1705 
1706     if (fixed_size)
1707       {
1708         while (((gsize) body_ptr) & alignment)
1709           *body_ptr++ = '\0';
1710 
1711         g_assert_true ((body_ptr == data) == (n_children == 0));
1712         if (n_children == 0)
1713           *body_ptr++ = '\0';
1714 
1715       }
1716 
1717 
1718     g_assert_true (body_ptr == ofs_ptr);
1719   }
1720 
1721   {
1722     gsize flavour;
1723     gsize i;
1724 
1725     alignment = (alignment & ALIGN_BITS) + 1;
1726 
1727     for (flavour = 0; flavour < 8; flavour += alignment)
1728       {
1729         GVariantSerialised serialised;
1730 
1731         serialised.type_info = type_info;
1732         serialised.data = flavoured_malloc (needed_size, flavour);
1733         serialised.size = needed_size;
1734         serialised.depth = 0;
1735 
1736         g_variant_serialiser_serialise (serialised, random_instance_filler,
1737                                         (gpointer *) instances, n_children);
1738 
1739         if (serialised.size)
1740           g_assert_cmpint (memcmp (serialised.data, data, serialised.size), ==, 0);
1741 
1742         g_assert_cmpuint (g_variant_serialised_n_children (serialised), ==, n_children);
1743 
1744         for (i = 0; i < n_children; i++)
1745           {
1746             GVariantSerialised child;
1747 
1748             child = g_variant_serialised_get_child (serialised, i);
1749             g_assert_true (child.type_info == instances[i]->type_info);
1750             random_instance_assert (instances[i], child.data, child.size);
1751             g_variant_type_info_unref (child.type_info);
1752           }
1753 
1754         flavoured_free (serialised.data, flavour);
1755       }
1756   }
1757 
1758   {
1759     gsize i;
1760 
1761     for (i = 0; i < n_children; i++)
1762       random_instance_free (instances[i]);
1763     g_free (instances);
1764   }
1765 
1766   g_variant_type_info_unref (type_info);
1767   align_free (data);
1768 }
1769 
1770 static void
test_tuples(void)1771 test_tuples (void)
1772 {
1773   gsize i;
1774 
1775   for (i = 0; i < 100; i++)
1776     test_tuple ();
1777 
1778   g_variant_type_info_assert_no_infos ();
1779 }
1780 
1781 static void
test_variant(void)1782 test_variant (void)
1783 {
1784   GVariantTypeInfo *type_info;
1785   RandomInstance *instance;
1786   const gchar *type_string;
1787   gsize needed_size;
1788   guchar *data;
1789   gsize len;
1790 
1791   type_info = g_variant_type_info_get (G_VARIANT_TYPE_VARIANT);
1792   instance = random_instance (NULL);
1793 
1794   type_string = g_variant_type_info_get_type_string (instance->type_info);
1795   len = strlen (type_string);
1796 
1797   needed_size = g_variant_serialiser_needed_size (type_info,
1798                                                   random_instance_filler,
1799                                                   (gpointer *) &instance, 1);
1800 
1801   g_assert_cmpint (needed_size, ==, instance->size + 1 + len);
1802 
1803   {
1804     guchar *ptr;
1805 
1806     ptr = data = align_malloc (needed_size);
1807     append_instance_data (instance, &ptr);
1808     *ptr++ = '\0';
1809     memcpy (ptr, type_string, len);
1810     ptr += len;
1811 
1812     g_assert_true (data + needed_size == ptr);
1813   }
1814 
1815   {
1816     gsize alignment;
1817     gsize flavour;
1818 
1819     /* variants are always 8-aligned */
1820     alignment = ALIGN_BITS + 1;
1821 
1822     for (flavour = 0; flavour < 8; flavour += alignment)
1823       {
1824         GVariantSerialised serialised;
1825         GVariantSerialised child;
1826 
1827         serialised.type_info = type_info;
1828         serialised.data = flavoured_malloc (needed_size, flavour);
1829         serialised.size = needed_size;
1830         serialised.depth = 0;
1831 
1832         g_variant_serialiser_serialise (serialised, random_instance_filler,
1833                                         (gpointer *) &instance, 1);
1834 
1835         if (serialised.size)
1836           g_assert_cmpint (memcmp (serialised.data, data, serialised.size), ==, 0);
1837 
1838         g_assert_cmpuint (g_variant_serialised_n_children (serialised), ==, 1);
1839 
1840         child = g_variant_serialised_get_child (serialised, 0);
1841         g_assert_true (child.type_info == instance->type_info);
1842         random_instance_check (instance, child.data, child.size);
1843 
1844         g_variant_type_info_unref (child.type_info);
1845         flavoured_free (serialised.data, flavour);
1846       }
1847   }
1848 
1849   g_variant_type_info_unref (type_info);
1850   random_instance_free (instance);
1851   align_free (data);
1852 }
1853 
1854 static void
test_variants(void)1855 test_variants (void)
1856 {
1857   gsize i;
1858 
1859   for (i = 0; i < 100; i++)
1860     test_variant ();
1861 
1862   g_variant_type_info_assert_no_infos ();
1863 }
1864 
1865 static void
test_strings(void)1866 test_strings (void)
1867 {
1868   struct {
1869     guint flags;
1870     guint size;
1871     gconstpointer data;
1872   } test_cases[] = {
1873 #define is_nval           0
1874 #define is_string         1
1875 #define is_objpath        is_string | 2
1876 #define is_sig            is_string | 4
1877     { is_sig,       1, "" },
1878     { is_nval,      0, NULL },
1879     { is_nval,     13, "hello\xffworld!" },
1880     { is_string,   13, "hello world!" },
1881     { is_nval,     13, "hello world\0" },
1882     { is_nval,     13, "hello\0world!" },
1883     { is_nval,     12, "hello world!" },
1884     { is_nval,     13, "hello world!\xff" },
1885 
1886     { is_objpath,   2, "/" },
1887     { is_objpath,   3, "/a" },
1888     { is_string,    3, "//" },
1889     { is_objpath,  11, "/some/path" },
1890     { is_string,   12, "/some/path/" },
1891     { is_nval,     11, "/some\0path" },
1892     { is_string,   11, "/some\\path" },
1893     { is_string,   12, "/some//path" },
1894     { is_string,   12, "/some-/path" },
1895 
1896     { is_sig,       2, "i" },
1897     { is_sig,       2, "s" },
1898     { is_sig,       5, "(si)" },
1899     { is_string,    4, "(si" },
1900     { is_string,    2, "*" },
1901     { is_sig,       3, "ai" },
1902     { is_string,    3, "mi" },
1903     { is_string,    2, "r" },
1904     { is_sig,      15, "(yyy{sv}ssiai)" },
1905     { is_string,   16, "(yyy{yv}ssiai))" },
1906     { is_string,   15, "(yyy{vv}ssiai)" },
1907     { is_string,   15, "(yyy{sv)ssiai}" }
1908   };
1909   gsize i;
1910 
1911   for (i = 0; i < G_N_ELEMENTS (test_cases); i++)
1912     {
1913       guint flags;
1914 
1915       flags = g_variant_serialiser_is_string (test_cases[i].data,
1916                                               test_cases[i].size)
1917         ? 1 : 0;
1918 
1919       flags |= g_variant_serialiser_is_object_path (test_cases[i].data,
1920                                                     test_cases[i].size)
1921         ? 2 : 0;
1922 
1923       flags |= g_variant_serialiser_is_signature (test_cases[i].data,
1924                                                   test_cases[i].size)
1925         ? 4 : 0;
1926 
1927       g_assert_cmpuint (flags, ==, test_cases[i].flags);
1928     }
1929 }
1930 
1931 typedef struct _TreeInstance TreeInstance;
1932 struct _TreeInstance
1933 {
1934   GVariantTypeInfo *info;
1935 
1936   TreeInstance **children;
1937   gsize n_children;
1938 
1939   union {
1940     guint64 integer;
1941     gdouble floating;
1942     gchar string[200];
1943   } data;
1944   gsize data_size;
1945 };
1946 
1947 static GVariantType *
make_random_definite_type(int depth)1948 make_random_definite_type (int depth)
1949 {
1950   GString *description;
1951   GString *type_string;
1952   GVariantType *type;
1953 
1954   description = g_string_new (NULL);
1955   type_string = g_string_new (NULL);
1956   type = append_type_string (type_string, description, TRUE, depth);
1957   g_string_free (description, TRUE);
1958   g_string_free (type_string, TRUE);
1959 
1960   return type;
1961 }
1962 
1963 static void
make_random_string(gchar * string,gsize size,const GVariantType * type)1964 make_random_string (gchar              *string,
1965                     gsize               size,
1966                     const GVariantType *type)
1967 {
1968   gsize i;
1969 
1970   /* create strings that are valid signature strings */
1971 #define good_chars "bynqiuxthdsog"
1972 
1973   for (i = 0; i < size - 1; i++)
1974     string[i] = good_chars[g_test_rand_int_range (0, strlen (good_chars))];
1975   string[i] = '\0';
1976 
1977   /* in case we need an object path, prefix a '/' */
1978   if (*g_variant_type_peek_string (type) == 'o')
1979     string[0] = '/';
1980 
1981 #undef good_chars
1982 }
1983 
1984 static TreeInstance *
tree_instance_new(const GVariantType * type,int depth)1985 tree_instance_new (const GVariantType *type,
1986                    int                 depth)
1987 {
1988   const GVariantType *child_type = NULL;
1989   GVariantType *mytype = NULL;
1990   TreeInstance *instance;
1991   gboolean is_tuple_type;
1992 
1993   if (type == NULL)
1994     type = mytype = make_random_definite_type (depth);
1995 
1996   instance = g_slice_new (TreeInstance);
1997   instance->info = g_variant_type_info_get (type);
1998   instance->children = NULL;
1999   instance->n_children = 0;
2000   instance->data_size = 0;
2001 
2002   is_tuple_type = FALSE;
2003 
2004   switch (*g_variant_type_peek_string (type))
2005     {
2006     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2007       instance->n_children = g_test_rand_int_range (0, 2);
2008       child_type = g_variant_type_element (type);
2009       break;
2010 
2011     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2012       instance->n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
2013       child_type = g_variant_type_element (type);
2014       break;
2015 
2016     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2017     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2018       instance->n_children = g_variant_type_n_items (type);
2019       child_type = g_variant_type_first (type);
2020       is_tuple_type = TRUE;
2021       break;
2022 
2023     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2024       instance->n_children = 1;
2025       child_type = NULL;
2026       break;
2027 
2028     case 'b':
2029       instance->data.integer = g_test_rand_int_range (0, 2);
2030       instance->data_size = 1;
2031       break;
2032 
2033     case 'y':
2034       instance->data.integer = g_test_rand_int ();
2035       instance->data_size = 1;
2036       break;
2037 
2038     case 'n': case 'q':
2039       instance->data.integer = g_test_rand_int ();
2040       instance->data_size = 2;
2041       break;
2042 
2043     case 'i': case 'u': case 'h':
2044       instance->data.integer = g_test_rand_int ();
2045       instance->data_size = 4;
2046       break;
2047 
2048     case 'x': case 't':
2049       instance->data.integer = g_test_rand_int ();
2050       instance->data.integer <<= 32;
2051       instance->data.integer |= (guint32) g_test_rand_int ();
2052       instance->data_size = 8;
2053       break;
2054 
2055     case 'd':
2056       instance->data.floating = g_test_rand_double ();
2057       instance->data_size = 8;
2058       break;
2059 
2060     case 's': case 'o': case 'g':
2061       instance->data_size = g_test_rand_int_range (10, 200);
2062       make_random_string (instance->data.string, instance->data_size, type);
2063       break;
2064     }
2065 
2066   if (instance->data_size == 0)
2067     /* no data -> it is a container */
2068     {
2069       gsize i;
2070 
2071       instance->children = g_new (TreeInstance *, instance->n_children);
2072 
2073       for (i = 0; i < instance->n_children; i++)
2074         {
2075           instance->children[i] = tree_instance_new (child_type, depth - 1);
2076 
2077           if (is_tuple_type)
2078             child_type = g_variant_type_next (child_type);
2079         }
2080 
2081       g_assert_true (!is_tuple_type || child_type == NULL);
2082     }
2083 
2084   g_variant_type_free (mytype);
2085 
2086   return instance;
2087 }
2088 
2089 static void
tree_instance_free(TreeInstance * instance)2090 tree_instance_free (TreeInstance *instance)
2091 {
2092   gsize i;
2093 
2094   g_variant_type_info_unref (instance->info);
2095   for (i = 0; i < instance->n_children; i++)
2096     tree_instance_free (instance->children[i]);
2097   g_free (instance->children);
2098   g_slice_free (TreeInstance, instance);
2099 }
2100 
2101 static gboolean i_am_writing_byteswapped;
2102 
2103 static void
tree_filler(GVariantSerialised * serialised,gpointer data)2104 tree_filler (GVariantSerialised *serialised,
2105              gpointer            data)
2106 {
2107   TreeInstance *instance = data;
2108 
2109   if (serialised->type_info == NULL)
2110     serialised->type_info = instance->info;
2111 
2112   serialised->depth = 0;
2113 
2114   if (instance->data_size == 0)
2115     /* is a container */
2116     {
2117       if (serialised->size == 0)
2118         serialised->size =
2119           g_variant_serialiser_needed_size (instance->info, tree_filler,
2120                                             (gpointer *) instance->children,
2121                                             instance->n_children);
2122 
2123       if (serialised->data)
2124         g_variant_serialiser_serialise (*serialised, tree_filler,
2125                                         (gpointer *) instance->children,
2126                                         instance->n_children);
2127     }
2128   else
2129     /* it is a leaf */
2130     {
2131       if (serialised->size == 0)
2132         serialised->size = instance->data_size;
2133 
2134       if (serialised->data)
2135         {
2136           switch (instance->data_size)
2137             {
2138             case 1:
2139               *serialised->data = instance->data.integer;
2140               break;
2141 
2142             case 2:
2143               {
2144                 guint16 value = instance->data.integer;
2145 
2146                 if (i_am_writing_byteswapped)
2147                   value = GUINT16_SWAP_LE_BE (value);
2148 
2149                 *(guint16 *) serialised->data = value;
2150               }
2151               break;
2152 
2153             case 4:
2154               {
2155                 guint32 value = instance->data.integer;
2156 
2157                 if (i_am_writing_byteswapped)
2158                   value = GUINT32_SWAP_LE_BE (value);
2159 
2160                 *(guint32 *) serialised->data = value;
2161               }
2162               break;
2163 
2164             case 8:
2165               {
2166                 guint64 value = instance->data.integer;
2167 
2168                 if (i_am_writing_byteswapped)
2169                   value = GUINT64_SWAP_LE_BE (value);
2170 
2171                 *(guint64 *) serialised->data = value;
2172               }
2173               break;
2174 
2175             default:
2176               memcpy (serialised->data,
2177                       instance->data.string,
2178                       instance->data_size);
2179               break;
2180             }
2181         }
2182     }
2183 }
2184 
2185 static gboolean
check_tree(TreeInstance * instance,GVariantSerialised serialised)2186 check_tree (TreeInstance       *instance,
2187             GVariantSerialised  serialised)
2188 {
2189   if (instance->info != serialised.type_info)
2190     return FALSE;
2191 
2192   if (instance->data_size == 0)
2193     /* is a container */
2194     {
2195       gsize i;
2196 
2197       if (g_variant_serialised_n_children (serialised) !=
2198           instance->n_children)
2199         return FALSE;
2200 
2201       for (i = 0; i < instance->n_children; i++)
2202         {
2203           GVariantSerialised child;
2204           gpointer data = NULL;
2205           gboolean ok;
2206 
2207           child = g_variant_serialised_get_child (serialised, i);
2208           if (child.size && child.data == NULL)
2209             child.data = data = g_malloc0 (child.size);
2210           ok = check_tree (instance->children[i], child);
2211           g_variant_type_info_unref (child.type_info);
2212           g_free (data);
2213 
2214           if (!ok)
2215             return FALSE;
2216         }
2217 
2218       return TRUE;
2219     }
2220   else
2221     /* it is a leaf */
2222     {
2223       switch (instance->data_size)
2224         {
2225         case 1:
2226           g_assert_cmpuint (serialised.size, ==, 1);
2227           return *(guint8 *) serialised.data ==
2228                   (guint8) instance->data.integer;
2229 
2230         case 2:
2231           g_assert_cmpuint (serialised.size, ==, 2);
2232           return *(guint16 *) serialised.data ==
2233                   (guint16) instance->data.integer;
2234 
2235         case 4:
2236           g_assert_cmpuint (serialised.size, ==, 4);
2237           return *(guint32 *) serialised.data ==
2238                   (guint32) instance->data.integer;
2239 
2240         case 8:
2241           g_assert_cmpuint (serialised.size, ==, 8);
2242           return *(guint64 *) serialised.data ==
2243                   (guint64) instance->data.integer;
2244 
2245         default:
2246           if (serialised.size != instance->data_size)
2247             return FALSE;
2248 
2249           return memcmp (serialised.data,
2250                          instance->data.string,
2251                          instance->data_size) == 0;
2252         }
2253     }
2254 }
2255 
2256 static void
serialise_tree(TreeInstance * tree,GVariantSerialised * serialised)2257 serialise_tree (TreeInstance       *tree,
2258                 GVariantSerialised *serialised)
2259 {
2260   GVariantSerialised empty = {0, };
2261 
2262   *serialised = empty;
2263   tree_filler (serialised, tree);
2264   serialised->data = g_malloc (serialised->size);
2265   tree_filler (serialised, tree);
2266 }
2267 
2268 static void
test_byteswap(void)2269 test_byteswap (void)
2270 {
2271   GVariantSerialised one, two;
2272   TreeInstance *tree;
2273 
2274   tree = tree_instance_new (NULL, 3);
2275   serialise_tree (tree, &one);
2276 
2277   i_am_writing_byteswapped = TRUE;
2278   serialise_tree (tree, &two);
2279   i_am_writing_byteswapped = FALSE;
2280 
2281   g_variant_serialised_byteswap (two);
2282 
2283   g_assert_cmpmem (one.data, one.size, two.data, two.size);
2284   g_assert_cmpuint (one.depth, ==, two.depth);
2285 
2286   tree_instance_free (tree);
2287   g_free (one.data);
2288   g_free (two.data);
2289 }
2290 
2291 static void
test_byteswaps(void)2292 test_byteswaps (void)
2293 {
2294   int i;
2295 
2296   for (i = 0; i < 200; i++)
2297     test_byteswap ();
2298 
2299   g_variant_type_info_assert_no_infos ();
2300 }
2301 
2302 static void
test_serialiser_children(void)2303 test_serialiser_children (void)
2304 {
2305   GBytes *data1, *data2;
2306   GVariant *child1, *child2;
2307   GVariantType *mv_type = g_variant_type_new_maybe (G_VARIANT_TYPE_VARIANT);
2308   GVariant *variant, *child;
2309 
2310   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1865");
2311   g_test_summary ("Test that getting a child variant before and after "
2312                   "serialisation of the parent works");
2313 
2314   /* Construct a variable sized array containing a child which serializes to a
2315    * zero-length bytestring. */
2316   child = g_variant_new_maybe (G_VARIANT_TYPE_VARIANT, NULL);
2317   variant = g_variant_new_array (mv_type, &child, 1);
2318 
2319   /* Get the child before serializing. */
2320   child1 = g_variant_get_child_value (variant, 0);
2321   data1 = g_variant_get_data_as_bytes (child1);
2322 
2323   /* Serialize the parent variant. */
2324   g_variant_get_data (variant);
2325 
2326   /* Get the child again after serializing — this uses a different code path. */
2327   child2 = g_variant_get_child_value (variant, 0);
2328   data2 = g_variant_get_data_as_bytes (child2);
2329 
2330   /* Check things are equal. */
2331   g_assert_cmpvariant (child1, child2);
2332   g_assert_true (g_bytes_equal (data1, data2));
2333 
2334   g_variant_unref (child2);
2335   g_variant_unref (child1);
2336   g_variant_unref (variant);
2337   g_bytes_unref (data2);
2338   g_bytes_unref (data1);
2339   g_variant_type_free (mv_type);
2340 }
2341 
2342 static void
test_fuzz(gdouble * fuzziness)2343 test_fuzz (gdouble *fuzziness)
2344 {
2345   GVariantSerialised serialised;
2346   TreeInstance *tree;
2347 
2348   /* make an instance */
2349   tree = tree_instance_new (NULL, 3);
2350 
2351   /* serialize it */
2352   serialise_tree (tree, &serialised);
2353 
2354   g_assert_true (g_variant_serialised_is_normal (serialised));
2355   g_assert_true (check_tree (tree, serialised));
2356 
2357   if (serialised.size)
2358     {
2359       gboolean fuzzed = FALSE;
2360       gboolean a, b;
2361 
2362       while (!fuzzed)
2363         {
2364           gsize i;
2365 
2366           for (i = 0; i < serialised.size; i++)
2367             if (randomly (*fuzziness))
2368               {
2369                 serialised.data[i] += g_test_rand_int_range (1, 256);
2370                 fuzzed = TRUE;
2371               }
2372         }
2373 
2374       /* at least one byte in the serialized data has changed.
2375        *
2376        * this means that at least one of the following is true:
2377        *
2378        *    - the serialized data now represents a different value:
2379        *        check_tree() will return FALSE
2380        *
2381        *    - the serialized data is in non-normal form:
2382        *        g_variant_serialiser_is_normal() will return FALSE
2383        *
2384        * we always do both checks to increase exposure of the serializer
2385        * to corrupt data.
2386        */
2387       a = g_variant_serialised_is_normal (serialised);
2388       b = check_tree (tree, serialised);
2389 
2390       g_assert_true (!a || !b);
2391     }
2392 
2393   tree_instance_free (tree);
2394   g_free (serialised.data);
2395 }
2396 
2397 
2398 static void
test_fuzzes(gpointer data)2399 test_fuzzes (gpointer data)
2400 {
2401   gdouble fuzziness;
2402   int i;
2403 
2404   fuzziness = GPOINTER_TO_INT (data) / 100.;
2405 
2406   for (i = 0; i < 200; i++)
2407     test_fuzz (&fuzziness);
2408 
2409   g_variant_type_info_assert_no_infos ();
2410 }
2411 
2412 static GVariant *
tree_instance_get_gvariant(TreeInstance * tree)2413 tree_instance_get_gvariant (TreeInstance *tree)
2414 {
2415   const GVariantType *type;
2416   GVariant *result;
2417 
2418   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2419 
2420   switch (g_variant_type_info_get_type_char (tree->info))
2421     {
2422     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2423       {
2424         const GVariantType *child_type;
2425         GVariant *child;
2426 
2427         if (tree->n_children)
2428           child = tree_instance_get_gvariant (tree->children[0]);
2429         else
2430           child = NULL;
2431 
2432         child_type = g_variant_type_element (type);
2433 
2434         if (child != NULL && randomly (0.5))
2435           child_type = NULL;
2436 
2437         result = g_variant_new_maybe (child_type, child);
2438       }
2439       break;
2440 
2441     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2442       {
2443         const GVariantType *child_type;
2444         GVariant **children;
2445         gsize i;
2446 
2447         children = g_new (GVariant *, tree->n_children);
2448         for (i = 0; i < tree->n_children; i++)
2449           children[i] = tree_instance_get_gvariant (tree->children[i]);
2450 
2451         child_type = g_variant_type_element (type);
2452 
2453         if (i > 0 && randomly (0.5))
2454           child_type = NULL;
2455 
2456         result = g_variant_new_array (child_type, children, tree->n_children);
2457         g_free (children);
2458       }
2459       break;
2460 
2461     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2462       {
2463         GVariant **children;
2464         gsize i;
2465 
2466         children = g_new (GVariant *, tree->n_children);
2467         for (i = 0; i < tree->n_children; i++)
2468           children[i] = tree_instance_get_gvariant (tree->children[i]);
2469 
2470         result = g_variant_new_tuple (children, tree->n_children);
2471         g_free (children);
2472       }
2473       break;
2474 
2475     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2476       {
2477         GVariant *key, *val;
2478 
2479         g_assert_cmpuint (tree->n_children, ==, 2);
2480 
2481         key = tree_instance_get_gvariant (tree->children[0]);
2482         val = tree_instance_get_gvariant (tree->children[1]);
2483 
2484         result = g_variant_new_dict_entry (key, val);
2485       }
2486       break;
2487 
2488     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2489       {
2490         GVariant *value;
2491 
2492         g_assert_cmpuint (tree->n_children, ==, 1);
2493 
2494         value = tree_instance_get_gvariant (tree->children[0]);
2495         result = g_variant_new_variant (value);
2496       }
2497       break;
2498 
2499     case 'b':
2500       result = g_variant_new_boolean (tree->data.integer > 0);
2501       break;
2502 
2503     case 'y':
2504       result = g_variant_new_byte (tree->data.integer);
2505       break;
2506 
2507     case 'n':
2508       result = g_variant_new_int16 (tree->data.integer);
2509       break;
2510 
2511     case 'q':
2512       result = g_variant_new_uint16 (tree->data.integer);
2513       break;
2514 
2515     case 'i':
2516       result = g_variant_new_int32 (tree->data.integer);
2517       break;
2518 
2519     case 'u':
2520       result = g_variant_new_uint32 (tree->data.integer);
2521       break;
2522 
2523     case 'x':
2524       result = g_variant_new_int64 (tree->data.integer);
2525       break;
2526 
2527     case 't':
2528       result = g_variant_new_uint64 (tree->data.integer);
2529       break;
2530 
2531     case 'h':
2532       result = g_variant_new_handle (tree->data.integer);
2533       break;
2534 
2535     case 'd':
2536       result = g_variant_new_double (tree->data.floating);
2537       break;
2538 
2539     case 's':
2540       result = g_variant_new_string (tree->data.string);
2541       break;
2542 
2543     case 'o':
2544       result = g_variant_new_object_path (tree->data.string);
2545       break;
2546 
2547     case 'g':
2548       result = g_variant_new_signature (tree->data.string);
2549       break;
2550 
2551     default:
2552       g_assert_not_reached ();
2553     }
2554 
2555   return result;
2556 }
2557 
2558 static gboolean
tree_instance_check_gvariant(TreeInstance * tree,GVariant * value)2559 tree_instance_check_gvariant (TreeInstance *tree,
2560                               GVariant     *value)
2561 {
2562   const GVariantType *type;
2563 
2564   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2565   g_assert_true (g_variant_is_of_type (value, type));
2566 
2567   switch (g_variant_type_info_get_type_char (tree->info))
2568     {
2569     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2570       {
2571         GVariant *child;
2572         gboolean equal;
2573 
2574         child = g_variant_get_maybe (value);
2575 
2576         if (child != NULL && tree->n_children == 1)
2577           equal = tree_instance_check_gvariant (tree->children[0], child);
2578         else if (child == NULL && tree->n_children == 0)
2579           equal = TRUE;
2580         else
2581           equal = FALSE;
2582 
2583         if (child != NULL)
2584           g_variant_unref (child);
2585 
2586         return equal;
2587       }
2588       break;
2589 
2590     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2591     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2592     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2593       {
2594         gsize i;
2595 
2596         if (g_variant_n_children (value) != tree->n_children)
2597           return FALSE;
2598 
2599         for (i = 0; i < tree->n_children; i++)
2600           {
2601             GVariant *child;
2602             gboolean equal;
2603 
2604             child = g_variant_get_child_value (value, i);
2605             equal = tree_instance_check_gvariant (tree->children[i], child);
2606             g_variant_unref (child);
2607 
2608             if (!equal)
2609               return FALSE;
2610           }
2611 
2612         return TRUE;
2613       }
2614       break;
2615 
2616     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2617       {
2618         const gchar *str1, *str2;
2619         GVariant *child;
2620         gboolean equal;
2621 
2622         child = g_variant_get_variant (value);
2623         str1 = g_variant_get_type_string (child);
2624         str2 = g_variant_type_info_get_type_string (tree->children[0]->info);
2625         /* GVariant only keeps one copy of type strings around */
2626         equal = str1 == str2 &&
2627                 tree_instance_check_gvariant (tree->children[0], child);
2628 
2629         g_variant_unref (child);
2630 
2631         return equal;
2632       }
2633       break;
2634 
2635     case 'b':
2636       return g_variant_get_boolean (value) == (gboolean) tree->data.integer;
2637 
2638     case 'y':
2639       return g_variant_get_byte (value) == (guchar) tree->data.integer;
2640 
2641     case 'n':
2642       return g_variant_get_int16 (value) == (gint16) tree->data.integer;
2643 
2644     case 'q':
2645       return g_variant_get_uint16 (value) == (guint16) tree->data.integer;
2646 
2647     case 'i':
2648       return g_variant_get_int32 (value) == (gint32) tree->data.integer;
2649 
2650     case 'u':
2651       return g_variant_get_uint32 (value) == (guint32) tree->data.integer;
2652 
2653     case 'x':
2654       return g_variant_get_int64 (value) == (gint64) tree->data.integer;
2655 
2656     case 't':
2657       return g_variant_get_uint64 (value) == (guint64) tree->data.integer;
2658 
2659     case 'h':
2660       return g_variant_get_handle (value) == (gint32) tree->data.integer;
2661 
2662     case 'd':
2663       {
2664         gdouble floating = g_variant_get_double (value);
2665 
2666         return memcmp (&floating, &tree->data.floating, sizeof floating) == 0;
2667       }
2668 
2669     case 's':
2670     case 'o':
2671     case 'g':
2672       return strcmp (g_variant_get_string (value, NULL),
2673                      tree->data.string) == 0;
2674 
2675     default:
2676       g_assert_not_reached ();
2677     }
2678 }
2679 
2680 static void
tree_instance_build_gvariant(TreeInstance * tree,GVariantBuilder * builder,gboolean guess_ok)2681 tree_instance_build_gvariant (TreeInstance    *tree,
2682                               GVariantBuilder *builder,
2683                               gboolean         guess_ok)
2684 {
2685   const GVariantType *type;
2686 
2687   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2688 
2689   if (g_variant_type_is_container (type))
2690     {
2691       gsize i;
2692 
2693       /* force GVariantBuilder to guess the type half the time */
2694       if (guess_ok && randomly (0.5))
2695         {
2696           if (g_variant_type_is_array (type) && tree->n_children)
2697             type = G_VARIANT_TYPE_ARRAY;
2698 
2699           if (g_variant_type_is_maybe (type) && tree->n_children)
2700             type = G_VARIANT_TYPE_MAYBE;
2701 
2702           if (g_variant_type_is_tuple (type))
2703             type = G_VARIANT_TYPE_TUPLE;
2704 
2705           if (g_variant_type_is_dict_entry (type))
2706             type = G_VARIANT_TYPE_DICT_ENTRY;
2707         }
2708       else
2709         guess_ok = FALSE;
2710 
2711       g_variant_builder_open (builder, type);
2712 
2713       for (i = 0; i < tree->n_children; i++)
2714         tree_instance_build_gvariant (tree->children[i], builder, guess_ok);
2715 
2716       g_variant_builder_close (builder);
2717     }
2718   else
2719     g_variant_builder_add_value (builder, tree_instance_get_gvariant (tree));
2720 }
2721 
2722 
2723 static gboolean
tree_instance_check_iter(TreeInstance * tree,GVariantIter * iter)2724 tree_instance_check_iter (TreeInstance *tree,
2725                           GVariantIter *iter)
2726 {
2727   GVariant *value;
2728 
2729   value = g_variant_iter_next_value (iter);
2730 
2731   if (g_variant_is_container (value))
2732     {
2733       gsize i;
2734 
2735       iter = g_variant_iter_new (value);
2736       g_variant_unref (value);
2737 
2738       if (g_variant_iter_n_children (iter) != tree->n_children)
2739         {
2740           g_variant_iter_free (iter);
2741           return FALSE;
2742         }
2743 
2744       for (i = 0; i < tree->n_children; i++)
2745         if (!tree_instance_check_iter (tree->children[i], iter))
2746           {
2747             g_variant_iter_free (iter);
2748             return FALSE;
2749           }
2750 
2751       g_assert_null (g_variant_iter_next_value (iter));
2752       g_variant_iter_free (iter);
2753 
2754       return TRUE;
2755     }
2756 
2757   else
2758     {
2759       gboolean equal;
2760 
2761       equal = tree_instance_check_gvariant (tree, value);
2762       g_variant_unref (value);
2763 
2764       return equal;
2765     }
2766 }
2767 
2768 static void
test_container(void)2769 test_container (void)
2770 {
2771   TreeInstance *tree;
2772   GVariant *value;
2773   gchar *s1, *s2;
2774 
2775   tree = tree_instance_new (NULL, 3);
2776   value = g_variant_ref_sink (tree_instance_get_gvariant (tree));
2777 
2778   s1 = g_variant_print (value, TRUE);
2779   g_assert_true (tree_instance_check_gvariant (tree, value));
2780 
2781   g_variant_get_data (value);
2782 
2783   s2 = g_variant_print (value, TRUE);
2784   g_assert_true (tree_instance_check_gvariant (tree, value));
2785 
2786   g_assert_cmpstr (s1, ==, s2);
2787 
2788   if (g_variant_is_container (value))
2789     {
2790       GVariantBuilder builder;
2791       GVariantIter iter;
2792       GVariant *built;
2793       GVariant *val;
2794       gchar *s3;
2795 
2796       g_variant_builder_init (&builder, G_VARIANT_TYPE_VARIANT);
2797       tree_instance_build_gvariant (tree, &builder, TRUE);
2798       built = g_variant_builder_end (&builder);
2799       g_variant_ref_sink (built);
2800       g_variant_get_data (built);
2801       val = g_variant_get_variant (built);
2802 
2803       s3 = g_variant_print (val, TRUE);
2804       g_assert_cmpstr (s1, ==, s3);
2805 
2806       g_variant_iter_init (&iter, built);
2807       g_assert_true (tree_instance_check_iter (tree, &iter));
2808       g_assert_null (g_variant_iter_next_value (&iter));
2809 
2810       g_variant_unref (built);
2811       g_variant_unref (val);
2812       g_free (s3);
2813     }
2814 
2815   tree_instance_free (tree);
2816   g_variant_unref (value);
2817   g_free (s2);
2818   g_free (s1);
2819 }
2820 
2821 static void
test_string(void)2822 test_string (void)
2823 {
2824   /* Test some different methods of creating strings */
2825   GVariant *v;
2826 
2827   v = g_variant_new_string ("foo");
2828   g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "foo");
2829   g_variant_unref (v);
2830 
2831 
2832   v = g_variant_new_take_string (g_strdup ("foo"));
2833   g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "foo");
2834   g_variant_unref (v);
2835 
2836   v = g_variant_new_printf ("%s %d", "foo", 123);
2837   g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "foo 123");
2838   g_variant_unref (v);
2839 }
2840 
2841 static void
test_utf8(void)2842 test_utf8 (void)
2843 {
2844   const gchar invalid[] = "hello\xffworld";
2845   GVariant *value;
2846 
2847   /* ensure that the test data is not valid utf8... */
2848   g_assert_false (g_utf8_validate (invalid, -1, NULL));
2849 
2850   /* load the data untrusted */
2851   value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2852                                    invalid, sizeof invalid,
2853                                    FALSE, NULL, NULL);
2854 
2855   /* ensure that the problem is caught and we get valid UTF-8 */
2856   g_assert_true (g_utf8_validate (g_variant_get_string (value, NULL), -1, NULL));
2857   g_variant_unref (value);
2858 
2859 
2860   /* now load it trusted */
2861   value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2862                                    invalid, sizeof invalid,
2863                                    TRUE, NULL, NULL);
2864 
2865   /* ensure we get the invalid data (ie: make sure that time wasn't
2866    * wasted on validating data that was marked as trusted)
2867    */
2868   g_assert_true (g_variant_get_string (value, NULL) == invalid);
2869   g_variant_unref (value);
2870 }
2871 
2872 static void
test_containers(void)2873 test_containers (void)
2874 {
2875   gsize i;
2876 
2877   for (i = 0; i < 100; i++)
2878     {
2879       test_container ();
2880     }
2881 
2882   g_variant_type_info_assert_no_infos ();
2883 }
2884 
2885 static void
test_format_strings(void)2886 test_format_strings (void)
2887 {
2888   GVariantType *type;
2889   const gchar *end;
2890 
2891   g_assert_true (g_variant_format_string_scan ("i", NULL, &end) && *end == '\0');
2892   g_assert_true (g_variant_format_string_scan ("@i", NULL, &end) && *end == '\0');
2893   g_assert_true (g_variant_format_string_scan ("@ii", NULL, &end) && *end == 'i');
2894   g_assert_true (g_variant_format_string_scan ("^a&s", NULL, &end) && *end == '\0');
2895   g_assert_true (g_variant_format_string_scan ("(^as)", NULL, &end) &&
2896                  *end == '\0');
2897   g_assert_false (g_variant_format_string_scan ("(^s)", NULL, &end));
2898   g_assert_false (g_variant_format_string_scan ("(^a)", NULL, &end));
2899   g_assert_false (g_variant_format_string_scan ("(z)", NULL, &end));
2900   g_assert_false (g_variant_format_string_scan ("az", NULL, &end));
2901   g_assert_false (g_variant_format_string_scan ("{**}", NULL, &end));
2902   g_assert_false (g_variant_format_string_scan ("{@**}", NULL, &end));
2903   g_assert_true (g_variant_format_string_scan ("{@y*}", NULL, &end) &&
2904                  *end == '\0');
2905   g_assert_true (g_variant_format_string_scan ("{yv}", NULL, &end) &&
2906                  *end == '\0');
2907   g_assert_false (g_variant_format_string_scan ("{&?v}", NULL, &end));
2908   g_assert_true (g_variant_format_string_scan ("{@?v}", NULL, &end) &&
2909                  *end == '\0');
2910   g_assert_false (g_variant_format_string_scan ("{&@sv}", NULL, &end));
2911   g_assert_false (g_variant_format_string_scan ("{@&sv}", NULL, &end));
2912   g_assert_true (g_variant_format_string_scan ("{&sv}", NULL, &end) &&
2913                  *end == '\0');
2914   g_assert_false (g_variant_format_string_scan ("{vv}", NULL, &end));
2915   g_assert_false (g_variant_format_string_scan ("{y}", NULL, &end));
2916   g_assert_false (g_variant_format_string_scan ("{yyy}", NULL, &end));
2917   g_assert_false (g_variant_format_string_scan ("{ya}", NULL, &end));
2918   g_assert_true (g_variant_format_string_scan ("&s", NULL, &end) && *end == '\0');
2919   g_assert_false (g_variant_format_string_scan ("&as", NULL, &end));
2920   g_assert_false (g_variant_format_string_scan ("@z", NULL, &end));
2921   g_assert_false (g_variant_format_string_scan ("az", NULL, &end));
2922   g_assert_false (g_variant_format_string_scan ("a&s", NULL, &end));
2923 
2924   type = g_variant_format_string_scan_type ("mm(@xy^a&s*?@?)", NULL, &end);
2925   g_assert_true (type && *end == '\0');
2926   g_assert_true (g_variant_type_equal (type, G_VARIANT_TYPE ("mm(xyas*?\?)")));
2927   g_variant_type_free (type);
2928 
2929   type = g_variant_format_string_scan_type ("mm(@xy^a&*?@?)", NULL, NULL);
2930   g_assert_null (type);
2931 }
2932 
2933 static void
do_failed_test(const char * test,const gchar * pattern)2934 do_failed_test (const char *test,
2935                 const gchar *pattern)
2936 {
2937   g_test_trap_subprocess (test, 1000000, 0);
2938   g_test_trap_assert_failed ();
2939   g_test_trap_assert_stderr (pattern);
2940 }
2941 
2942 static void
test_invalid_varargs(void)2943 test_invalid_varargs (void)
2944 {
2945   GVariant *value;
2946   const gchar *end;
2947 
2948   if (!g_test_undefined ())
2949     return;
2950 
2951   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2952                          "*GVariant format string*");
2953   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2954                          "*valid_format_string*");
2955   value = g_variant_new ("z");
2956   g_test_assert_expected_messages ();
2957   g_assert_null (value);
2958 
2959   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2960                          "*valid GVariant format string as a prefix*");
2961   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2962                          "*valid_format_string*");
2963   value = g_variant_new_va ("z", &end, NULL);
2964   g_test_assert_expected_messages ();
2965   g_assert_null (value);
2966 
2967   value = g_variant_new ("y", 'a');
2968   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2969                          "*type of 'q' but * has a type of 'y'*");
2970   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2971                          "*valid_format_string*");
2972   g_variant_get (value, "q");
2973   g_test_assert_expected_messages ();
2974   g_variant_unref (value);
2975 }
2976 
2977 static void
check_and_free(GVariant * value,const gchar * str)2978 check_and_free (GVariant    *value,
2979                 const gchar *str)
2980 {
2981   gchar *valstr = g_variant_print (value, FALSE);
2982   g_assert_cmpstr (str, ==, valstr);
2983   g_variant_unref (value);
2984   g_free (valstr);
2985 }
2986 
2987 static void
test_varargs_empty_array(void)2988 test_varargs_empty_array (void)
2989 {
2990   g_variant_new ("(a{s*})", NULL);
2991 
2992   g_assert_not_reached ();
2993 }
2994 
2995 static void
test_varargs(void)2996 test_varargs (void)
2997 {
2998   {
2999     GVariantBuilder array;
3000 
3001     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
3002     g_variant_builder_add_parsed (&array, "{'size', <(%i, %i)> }", 800, 600);
3003     g_variant_builder_add (&array, "{sv}", "title",
3004                            g_variant_new_string ("Test case"));
3005     g_variant_builder_add_value (&array,
3006       g_variant_new_dict_entry (g_variant_new_string ("temperature"),
3007                                 g_variant_new_variant (
3008                                   g_variant_new_double (37.5))));
3009     check_and_free (g_variant_new ("(ma{sv}m(a{sv})ma{sv}ii)",
3010                                    NULL, FALSE, NULL, &array, 7777, 8888),
3011                     "(nothing, nothing, {'size': <(800, 600)>, "
3012                                         "'title': <'Test case'>, "
3013                                         "'temperature': <37.5>}, "
3014                      "7777, 8888)");
3015 
3016     check_and_free (g_variant_new ("(imimimmimmimmi)",
3017                                    123,
3018                                    FALSE, 321,
3019                                    TRUE, 123,
3020                                    FALSE, TRUE, 321,
3021                                    TRUE, FALSE, 321,
3022                                    TRUE, TRUE, 123),
3023                     "(123, nothing, 123, nothing, just nothing, 123)");
3024 
3025     check_and_free (g_variant_new ("(ybnixd)",
3026                                    'a', 1, 22, 33, (guint64) 44, 5.5),
3027                     "(0x61, true, 22, 33, 44, 5.5)");
3028 
3029     check_and_free (g_variant_new ("(@y?*rv)",
3030                                    g_variant_new ("y", 'a'),
3031                                    g_variant_new ("y", 'b'),
3032                                    g_variant_new ("y", 'c'),
3033                                    g_variant_new ("(y)", 'd'),
3034                                    g_variant_new ("y", 'e')),
3035                     "(0x61, 0x62, 0x63, (0x64,), <byte 0x65>)");
3036   }
3037 
3038   {
3039     GVariantBuilder array;
3040     GVariantIter iter;
3041     GVariant *value;
3042     gchar *number;
3043     gboolean just;
3044     guint i;
3045     gint val;
3046 
3047     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
3048     for (i = 0; i < 100; i++)
3049       {
3050         number = g_strdup_printf ("%u", i);
3051         g_variant_builder_add (&array, "s", number);
3052         g_free (number);
3053       }
3054 
3055     value = g_variant_builder_end (&array);
3056     g_variant_iter_init (&iter, value);
3057 
3058     i = 0;
3059     while (g_variant_iter_loop (&iter, "s", &number))
3060       {
3061         gchar *check = g_strdup_printf ("%u", i++);
3062         g_assert_cmpstr (number, ==, check);
3063         g_free (check);
3064       }
3065     g_assert_null (number);
3066     g_assert_cmpuint (i, ==, 100);
3067 
3068     g_variant_unref (value);
3069 
3070     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
3071     for (i = 0; i < 100; i++)
3072       g_variant_builder_add (&array, "mi", i % 2 == 0, i);
3073     value = g_variant_builder_end (&array);
3074 
3075     i = 0;
3076     g_variant_iter_init (&iter, value);
3077     while (g_variant_iter_loop (&iter, "mi", NULL, &val))
3078       g_assert_true (val == (gint) i++ || val == 0);
3079     g_assert_cmpuint (i, ==, 100);
3080 
3081     i = 0;
3082     g_variant_iter_init (&iter, value);
3083     while (g_variant_iter_loop (&iter, "mi", &just, &val))
3084       {
3085         gint this = i++;
3086 
3087         if (this % 2 == 0)
3088           {
3089             g_assert_true (just);
3090             g_assert_cmpint (val, ==, this);
3091           }
3092         else
3093           {
3094             g_assert_false (just);
3095             g_assert_cmpint (val, ==, 0);
3096           }
3097       }
3098     g_assert_cmpuint (i, ==, 100);
3099 
3100     g_variant_unref (value);
3101   }
3102 
3103   {
3104     const gchar *strvector[] = {"/hello", "/world", NULL};
3105     const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
3106     GVariantBuilder builder;
3107     GVariantIter *array;
3108     GVariantIter tuple;
3109     const gchar **strv;
3110     gchar **my_strv;
3111     GVariant *value;
3112     gchar *str;
3113     gsize i;
3114 
3115     g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
3116     g_variant_builder_add (&builder, "s", test_strs[0]);
3117     g_variant_builder_add (&builder, "s", test_strs[1]);
3118     g_variant_builder_add (&builder, "s", test_strs[2]);
3119     value = g_variant_new ("(as^as^a&s)", &builder, strvector, strvector);
3120     g_variant_iter_init (&tuple, value);
3121     g_variant_iter_next (&tuple, "as", &array);
3122 
3123     i = 0;
3124     while (g_variant_iter_loop (array, "s", &str))
3125       g_assert_cmpstr (str, ==, test_strs[i++]);
3126     g_assert_cmpuint (i, ==, 3);
3127 
3128     g_variant_iter_free (array);
3129 
3130     /* start over */
3131     g_variant_iter_init (&tuple, value);
3132     g_variant_iter_next (&tuple, "as", &array);
3133 
3134     i = 0;
3135     while (g_variant_iter_loop (array, "&s", &str))
3136       g_assert_cmpstr (str, ==, test_strs[i++]);
3137     g_assert_cmpuint (i, ==, 3);
3138 
3139     g_variant_iter_free (array);
3140 
3141     g_variant_iter_next (&tuple, "^a&s", &strv);
3142     g_variant_iter_next (&tuple, "^as", &my_strv);
3143 
3144     g_assert_cmpstrv (strv, strvector);
3145     g_assert_cmpstrv (my_strv, strvector);
3146 
3147     g_variant_unref (value);
3148     g_strfreev (my_strv);
3149     g_free (strv);
3150   }
3151 
3152   {
3153     const gchar *strvector[] = {"/hello", "/world", NULL};
3154     const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
3155     GVariantBuilder builder;
3156     GVariantIter *array;
3157     GVariantIter tuple;
3158     const gchar **strv;
3159     gchar **my_strv;
3160     GVariant *value;
3161     gchar *str;
3162     gsize i;
3163 
3164     g_variant_builder_init (&builder, G_VARIANT_TYPE ("aaay"));
3165     g_variant_builder_add (&builder, "^aay", strvector);
3166     g_variant_builder_add (&builder, "^aay", strvector);
3167     g_variant_builder_add (&builder, "^aay", strvector);
3168     value = g_variant_new ("aaay", &builder);
3169     array = g_variant_iter_new (value);
3170     i = 0;
3171     while (g_variant_iter_loop (array, "^aay", &my_strv))
3172       i++;
3173     g_assert_cmpuint (i, ==, 3);
3174 
3175     /* start over */
3176     g_variant_iter_init (array, value);
3177     i = 0;
3178     while (g_variant_iter_loop (array, "^a&ay", &strv))
3179       i++;
3180     g_assert_cmpuint (i, ==, 3);
3181     g_variant_unref (value);
3182     g_variant_iter_free (array);
3183 
3184     /* next test */
3185     g_variant_builder_init (&builder, G_VARIANT_TYPE ("aay"));
3186     g_variant_builder_add (&builder, "^ay", test_strs[0]);
3187     g_variant_builder_add (&builder, "^ay", test_strs[1]);
3188     g_variant_builder_add (&builder, "^ay", test_strs[2]);
3189     value = g_variant_new ("(aay^aay^a&ay)", &builder, strvector, strvector);
3190     g_variant_iter_init (&tuple, value);
3191     g_variant_iter_next (&tuple, "aay", &array);
3192 
3193     i = 0;
3194     while (g_variant_iter_loop (array, "^ay", &str))
3195       g_assert_cmpstr (str, ==, test_strs[i++]);
3196     g_assert_cmpuint (i, ==, 3);
3197 
3198     g_variant_iter_free (array);
3199 
3200     /* start over */
3201     g_variant_iter_init (&tuple, value);
3202     g_variant_iter_next (&tuple, "aay", &array);
3203 
3204     i = 0;
3205     while (g_variant_iter_loop (array, "^&ay", &str))
3206       g_assert_cmpstr (str, ==, test_strs[i++]);
3207     g_assert_cmpuint (i, ==, 3);
3208 
3209     g_variant_iter_free (array);
3210 
3211     g_variant_iter_next (&tuple, "^a&ay", &strv);
3212     g_variant_iter_next (&tuple, "^aay", &my_strv);
3213 
3214     g_assert_cmpstrv (strv, strvector);
3215     g_assert_cmpstrv (my_strv, strvector);
3216 
3217     g_variant_unref (value);
3218     g_strfreev (my_strv);
3219     g_free (strv);
3220   }
3221 
3222   {
3223     const gchar *strvector[] = {"/hello", "/world", NULL};
3224     const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
3225     GVariantBuilder builder;
3226     GVariantIter *array;
3227     GVariantIter tuple;
3228     const gchar **strv;
3229     gchar **my_strv;
3230     GVariant *value;
3231     gchar *str;
3232     gsize i;
3233 
3234     g_variant_builder_init (&builder, G_VARIANT_TYPE_OBJECT_PATH_ARRAY);
3235     g_variant_builder_add (&builder, "o", test_strs[0]);
3236     g_variant_builder_add (&builder, "o", test_strs[1]);
3237     g_variant_builder_add (&builder, "o", test_strs[2]);
3238     value = g_variant_new ("(ao^ao^a&o)", &builder, strvector, strvector);
3239     g_variant_iter_init (&tuple, value);
3240     g_variant_iter_next (&tuple, "ao", &array);
3241 
3242     i = 0;
3243     while (g_variant_iter_loop (array, "o", &str))
3244       g_assert_cmpstr (str, ==, test_strs[i++]);
3245     g_assert_cmpuint (i, ==, 3);
3246 
3247     g_variant_iter_free (array);
3248 
3249     /* start over */
3250     g_variant_iter_init (&tuple, value);
3251     g_variant_iter_next (&tuple, "ao", &array);
3252 
3253     i = 0;
3254     while (g_variant_iter_loop (array, "&o", &str))
3255       g_assert_cmpstr (str, ==, test_strs[i++]);
3256     g_assert_cmpuint (i, ==, 3);
3257 
3258     g_variant_iter_free (array);
3259 
3260     g_variant_iter_next (&tuple, "^a&o", &strv);
3261     g_variant_iter_next (&tuple, "^ao", &my_strv);
3262 
3263     g_assert_cmpstrv (strv, strvector);
3264     g_assert_cmpstrv (my_strv, strvector);
3265 
3266     g_variant_unref (value);
3267     g_strfreev (my_strv);
3268     g_free (strv);
3269   }
3270 
3271   {
3272     const gchar *strvector[] = { "i", "ii", "iii", "iv", "v", "vi", NULL };
3273     GVariantBuilder builder;
3274     GVariantIter iter;
3275     GVariantIter *i2;
3276     GVariantIter *i3;
3277     GVariant *value;
3278     GVariant *sub;
3279     gchar **strv;
3280     gsize i;
3281 
3282     g_variant_builder_init (&builder, G_VARIANT_TYPE ("aas"));
3283     g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
3284     for (i = 0; i < 6; i++)
3285       if (i & 1)
3286         g_variant_builder_add (&builder, "s", strvector[i]);
3287       else
3288         g_variant_builder_add (&builder, "&s", strvector[i]);
3289     g_variant_builder_close (&builder);
3290     g_variant_builder_add (&builder, "^as", strvector);
3291     g_variant_builder_add (&builder, "^as", strvector);
3292     value = g_variant_new ("aas", &builder);
3293 
3294     g_variant_iter_init (&iter, value);
3295     while (g_variant_iter_loop (&iter, "^as", &strv))
3296       for (i = 0; i < 6; i++)
3297         g_assert_cmpstr (strv[i], ==, strvector[i]);
3298 
3299     g_variant_iter_init (&iter, value);
3300     while (g_variant_iter_loop (&iter, "^a&s", &strv))
3301       for (i = 0; i < 6; i++)
3302         g_assert_cmpstr (strv[i], ==, strvector[i]);
3303 
3304     g_variant_iter_init (&iter, value);
3305     while (g_variant_iter_loop (&iter, "as", &i2))
3306       {
3307         gchar *str;
3308 
3309         i = 0;
3310         while (g_variant_iter_loop (i2, "s", &str))
3311           g_assert_cmpstr (str, ==, strvector[i++]);
3312         g_assert_cmpuint (i, ==, 6);
3313       }
3314 
3315     g_variant_iter_init (&iter, value);
3316     i3 = g_variant_iter_copy (&iter);
3317     while (g_variant_iter_loop (&iter, "@as", &sub))
3318       {
3319         gchar *str = g_variant_print (sub, TRUE);
3320         g_assert_cmpstr (str, ==,
3321                          "['i', 'ii', 'iii', 'iv', 'v', 'vi']");
3322         g_free (str);
3323       }
3324 
3325     g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
3326                            "*NULL has already been returned*");
3327     g_variant_iter_next_value (&iter);
3328     g_test_assert_expected_messages ();
3329 
3330     while (g_variant_iter_loop (i3, "*", &sub))
3331       {
3332         gchar *str = g_variant_print (sub, TRUE);
3333         g_assert_cmpstr (str, ==,
3334                          "['i', 'ii', 'iii', 'iv', 'v', 'vi']");
3335         g_free (str);
3336       }
3337 
3338     g_variant_iter_free (i3);
3339 
3340     for (i = 0; i < g_variant_n_children (value); i++)
3341       {
3342         gsize j;
3343 
3344         g_variant_get_child (value, i, "*", &sub);
3345 
3346         for (j = 0; j < g_variant_n_children (sub); j++)
3347           {
3348             const gchar *str = NULL;
3349             GVariant *cval;
3350 
3351             g_variant_get_child (sub, j, "&s", &str);
3352             g_assert_cmpstr (str, ==, strvector[j]);
3353 
3354             cval = g_variant_get_child_value (sub, j);
3355             g_variant_get (cval, "&s", &str);
3356             g_assert_cmpstr (str, ==, strvector[j]);
3357             g_variant_unref (cval);
3358           }
3359 
3360         g_variant_unref (sub);
3361       }
3362 
3363     g_variant_unref (value);
3364   }
3365 
3366   {
3367     gboolean justs[10];
3368     GVariant *value;
3369 
3370     GVariant *vval;
3371     guchar byteval;
3372     gboolean bval;
3373     gint16 i16val;
3374     guint16 u16val;
3375     gint32 i32val;
3376     guint32 u32val;
3377     gint64 i64val;
3378     guint64 u64val;
3379     gdouble dval;
3380     gint32 hval;
3381 
3382     /* test all 'nothing' */
3383     value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3384                            FALSE, 'a',
3385                            FALSE, TRUE,
3386                            FALSE, (gint16) 123,
3387                            FALSE, (guint16) 123,
3388                            FALSE, (gint32) 123,
3389                            FALSE, (guint32) 123,
3390                            FALSE, (gint64) 123,
3391                            FALSE, (guint64) 123,
3392                            FALSE, (gint32) -1,
3393                            FALSE, (gdouble) 37.5,
3394                            NULL);
3395 
3396     /* both NULL */
3397     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3398                    NULL, NULL,
3399                    NULL, NULL,
3400                    NULL, NULL,
3401                    NULL, NULL,
3402                    NULL, NULL,
3403                    NULL, NULL,
3404                    NULL, NULL,
3405                    NULL, NULL,
3406                    NULL, NULL,
3407                    NULL, NULL,
3408                    NULL);
3409 
3410     /* NULL values */
3411     memset (justs, 1, sizeof justs);
3412     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3413                    &justs[0], NULL,
3414                    &justs[1], NULL,
3415                    &justs[2], NULL,
3416                    &justs[3], NULL,
3417                    &justs[4], NULL,
3418                    &justs[5], NULL,
3419                    &justs[6], NULL,
3420                    &justs[7], NULL,
3421                    &justs[8], NULL,
3422                    &justs[9], NULL,
3423                    NULL);
3424     g_assert_true (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3425                      justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3426 
3427     /* both non-NULL */
3428     memset (justs, 1, sizeof justs);
3429     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3430     vval = (void *) 1;
3431     bval = TRUE;
3432     dval = 88.88;
3433     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3434                    &justs[0], &byteval,
3435                    &justs[1], &bval,
3436                    &justs[2], &i16val,
3437                    &justs[3], &u16val,
3438                    &justs[4], &i32val,
3439                    &justs[5], &u32val,
3440                    &justs[6], &i64val,
3441                    &justs[7], &u64val,
3442                    &justs[8], &hval,
3443                    &justs[9], &dval,
3444                    &vval);
3445     g_assert_true (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3446                      justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3447     g_assert_true (byteval == '\0' && bval == FALSE);
3448     g_assert_true (i16val == 0 && u16val == 0 && i32val == 0 &&
3449                    u32val == 0 && i64val == 0 && u64val == 0 &&
3450                    hval == 0 && dval == 0.0);
3451     g_assert_null (vval);
3452 
3453     /* NULL justs */
3454     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3455     vval = (void *) 1;
3456     bval = TRUE;
3457     dval = 88.88;
3458     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3459                    NULL, &byteval,
3460                    NULL, &bval,
3461                    NULL, &i16val,
3462                    NULL, &u16val,
3463                    NULL, &i32val,
3464                    NULL, &u32val,
3465                    NULL, &i64val,
3466                    NULL, &u64val,
3467                    NULL, &hval,
3468                    NULL, &dval,
3469                    &vval);
3470     g_assert_true (byteval == '\0' && bval == FALSE);
3471     g_assert_true (i16val == 0 && u16val == 0 && i32val == 0 &&
3472                    u32val == 0 && i64val == 0 && u64val == 0 &&
3473                    hval == 0 && dval == 0.0);
3474     g_assert_null (vval);
3475 
3476     g_variant_unref (value);
3477 
3478 
3479     /* test all 'just' */
3480     value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3481                            TRUE, 'a',
3482                            TRUE, TRUE,
3483                            TRUE, (gint16) 123,
3484                            TRUE, (guint16) 123,
3485                            TRUE, (gint32) 123,
3486                            TRUE, (guint32) 123,
3487                            TRUE, (gint64) 123,
3488                            TRUE, (guint64) 123,
3489                            TRUE, (gint32) -1,
3490                            TRUE, (gdouble) 37.5,
3491                            g_variant_new ("()"));
3492 
3493     /* both NULL */
3494     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3495                    NULL, NULL,
3496                    NULL, NULL,
3497                    NULL, NULL,
3498                    NULL, NULL,
3499                    NULL, NULL,
3500                    NULL, NULL,
3501                    NULL, NULL,
3502                    NULL, NULL,
3503                    NULL, NULL,
3504                    NULL, NULL,
3505                    NULL);
3506 
3507     /* NULL values */
3508     memset (justs, 0, sizeof justs);
3509     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3510                    &justs[0], NULL,
3511                    &justs[1], NULL,
3512                    &justs[2], NULL,
3513                    &justs[3], NULL,
3514                    &justs[4], NULL,
3515                    &justs[5], NULL,
3516                    &justs[6], NULL,
3517                    &justs[7], NULL,
3518                    &justs[8], NULL,
3519                    &justs[9], NULL,
3520                    NULL);
3521     g_assert_true (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3522                    justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3523 
3524     /* both non-NULL */
3525     memset (justs, 0, sizeof justs);
3526     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3527     vval = (void *) 1;
3528     bval = FALSE;
3529     dval = 88.88;
3530     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3531                    &justs[0], &byteval,
3532                    &justs[1], &bval,
3533                    &justs[2], &i16val,
3534                    &justs[3], &u16val,
3535                    &justs[4], &i32val,
3536                    &justs[5], &u32val,
3537                    &justs[6], &i64val,
3538                    &justs[7], &u64val,
3539                    &justs[8], &hval,
3540                    &justs[9], &dval,
3541                    &vval);
3542     g_assert_true (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3543                    justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3544     g_assert_true (byteval == 'a' && bval == TRUE);
3545     g_assert_true (i16val == 123 && u16val == 123 && i32val == 123 &&
3546                    u32val == 123 && i64val == 123 && u64val == 123 &&
3547                    hval == -1 && dval == 37.5);
3548     g_assert_true (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3549     g_variant_unref (vval);
3550 
3551     /* NULL justs */
3552     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3553     vval = (void *) 1;
3554     bval = TRUE;
3555     dval = 88.88;
3556     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3557                    NULL, &byteval,
3558                    NULL, &bval,
3559                    NULL, &i16val,
3560                    NULL, &u16val,
3561                    NULL, &i32val,
3562                    NULL, &u32val,
3563                    NULL, &i64val,
3564                    NULL, &u64val,
3565                    NULL, &hval,
3566                    NULL, &dval,
3567                    &vval);
3568     g_assert_true (byteval == 'a' && bval == TRUE);
3569     g_assert_true (i16val == 123 && u16val == 123 && i32val == 123 &&
3570                    u32val == 123 && i64val == 123 && u64val == 123 &&
3571                    hval == -1 && dval == 37.5);
3572     g_assert_true (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3573     g_variant_unref (vval);
3574 
3575     g_variant_unref (value);
3576   }
3577 
3578   {
3579     GVariant *value;
3580     gchar *str;
3581 
3582     value = g_variant_new ("(masas)", NULL, NULL);
3583     g_variant_ref_sink (value);
3584 
3585     str = g_variant_print (value, TRUE);
3586     g_assert_cmpstr (str, ==, "(@mas nothing, @as [])");
3587     g_variant_unref (value);
3588     g_free (str);
3589 
3590     do_failed_test ("/gvariant/varargs/subprocess/empty-array",
3591                     "*which type of empty array*");
3592   }
3593 
3594   g_variant_type_info_assert_no_infos ();
3595 }
3596 
3597 static void
hash_get(GVariant * value,const gchar * format,...)3598 hash_get (GVariant    *value,
3599           const gchar *format,
3600           ...)
3601 {
3602   const gchar *endptr = NULL;
3603   gboolean hash;
3604   va_list ap;
3605 
3606   hash = g_str_has_suffix (format, "#");
3607 
3608   va_start (ap, format);
3609   g_variant_get_va (value, format, hash ? &endptr : NULL, &ap);
3610   va_end (ap);
3611 
3612   if (hash)
3613     g_assert_cmpint (*endptr, ==, '#');
3614 }
3615 
3616 static GVariant *
hash_new(const gchar * format,...)3617 hash_new (const gchar *format,
3618           ...)
3619 {
3620   const gchar *endptr = NULL;
3621   GVariant *value;
3622   gboolean hash;
3623   va_list ap;
3624 
3625   hash = g_str_has_suffix (format, "#");
3626 
3627   va_start (ap, format);
3628   value = g_variant_new_va (format, hash ? &endptr : NULL, &ap);
3629   va_end (ap);
3630 
3631   if (hash)
3632     g_assert_cmpint (*endptr, ==, '#');
3633 
3634   return value;
3635 }
3636 
3637 static void
test_valist(void)3638 test_valist (void)
3639 {
3640   GVariant *value;
3641   gint32 x;
3642 
3643   x = 0;
3644   value = hash_new ("i", 234);
3645   hash_get (value, "i", &x);
3646   g_assert_cmpint (x, ==, 234);
3647   g_variant_unref (value);
3648 
3649   x = 0;
3650   value = hash_new ("i#", 234);
3651   hash_get (value, "i#", &x);
3652   g_assert_cmpint (x, ==, 234);
3653   g_variant_unref (value);
3654 
3655   g_variant_type_info_assert_no_infos ();
3656 }
3657 
3658 static void
test_builder_memory(void)3659 test_builder_memory (void)
3660 {
3661   GVariantBuilder *hb;
3662   GVariantBuilder sb;
3663 
3664   hb = g_variant_builder_new  (G_VARIANT_TYPE_ARRAY);
3665   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3666   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3667   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3668   g_variant_builder_add (hb, "s", "some value");
3669   g_variant_builder_ref (hb);
3670   g_variant_builder_unref (hb);
3671   g_variant_builder_unref (hb);
3672 
3673   hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3674   g_variant_builder_unref (hb);
3675 
3676   hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3677   g_variant_builder_clear (hb);
3678   g_variant_builder_unref (hb);
3679 
3680   g_variant_builder_init (&sb, G_VARIANT_TYPE_ARRAY);
3681   g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3682   g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3683   g_variant_builder_add (&sb, "s", "some value");
3684   g_variant_builder_clear (&sb);
3685 
3686   g_variant_type_info_assert_no_infos ();
3687 }
3688 
3689 static void
test_hashing(void)3690 test_hashing (void)
3691 {
3692   GVariant *items[4096];
3693   GHashTable *table;
3694   gsize i;
3695 
3696   table = g_hash_table_new_full (g_variant_hash, g_variant_equal,
3697                                  (GDestroyNotify ) g_variant_unref,
3698                                  NULL);
3699 
3700   for (i = 0; i < G_N_ELEMENTS (items); i++)
3701     {
3702       TreeInstance *tree;
3703       gsize j;
3704 
3705  again:
3706       tree = tree_instance_new (NULL, 0);
3707       items[i] = tree_instance_get_gvariant (tree);
3708       tree_instance_free (tree);
3709 
3710       for (j = 0; j < i; j++)
3711         if (g_variant_equal (items[i], items[j]))
3712           {
3713             g_variant_unref (items[i]);
3714             goto again;
3715           }
3716 
3717       g_hash_table_insert (table,
3718                            g_variant_ref_sink (items[i]),
3719                            GINT_TO_POINTER (i));
3720     }
3721 
3722   for (i = 0; i < G_N_ELEMENTS (items); i++)
3723     {
3724       gpointer result;
3725 
3726       result = g_hash_table_lookup (table, items[i]);
3727       g_assert_cmpint (GPOINTER_TO_INT (result), ==, i);
3728     }
3729 
3730   g_hash_table_unref (table);
3731 
3732   g_variant_type_info_assert_no_infos ();
3733 }
3734 
3735 static void
test_gv_byteswap(void)3736 test_gv_byteswap (void)
3737 {
3738 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
3739 # define native16(x)  x, 0
3740 # define swapped16(x) 0, x
3741 #else
3742 # define native16(x)  0, x
3743 # define swapped16(x) x, 0
3744 #endif
3745   /* all kinds of of crazy randomised testing already performed on the
3746    * byteswapper in the /gvariant/serializer/byteswap test and all kinds
3747    * of crazy randomised testing performed against the serializer
3748    * normalisation functions in the /gvariant/serializer/fuzz/ tests.
3749    *
3750    * just test a few simple cases here to make sure they each work
3751    */
3752   guchar validbytes[] = { 'a', '\0', swapped16(66), 2,
3753                           0,
3754                           'b', '\0', swapped16(77), 2,
3755                           5, 11 };
3756   guchar corruptbytes[] = { 'a', '\0', swapped16(66), 2,
3757                             0,
3758                             'b', '\0', swapped16(77), 2,
3759                             6, 11 };
3760   guint valid_data[4], corrupt_data[4];
3761   GVariant *value, *swapped;
3762   gchar *string, *string2;
3763 
3764   memcpy (valid_data, validbytes, sizeof validbytes);
3765   memcpy (corrupt_data, corruptbytes, sizeof corruptbytes);
3766 
3767   /* trusted */
3768   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3769                                    valid_data, sizeof validbytes, TRUE,
3770                                    NULL, NULL);
3771   swapped = g_variant_byteswap (value);
3772   g_variant_unref (value);
3773   g_assert_cmpuint (g_variant_get_size (swapped), ==, 13);
3774   string = g_variant_print (swapped, FALSE);
3775   g_variant_unref (swapped);
3776   g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3777   g_free (string);
3778 
3779   /* untrusted but valid */
3780   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3781                                    valid_data, sizeof validbytes, FALSE,
3782                                    NULL, NULL);
3783   swapped = g_variant_byteswap (value);
3784   g_variant_unref (value);
3785   g_assert_cmpuint (g_variant_get_size (swapped), ==, 13);
3786   string = g_variant_print (swapped, FALSE);
3787   g_variant_unref (swapped);
3788   g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3789   g_free (string);
3790 
3791   /* untrusted, invalid */
3792   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3793                                    corrupt_data, sizeof corruptbytes, FALSE,
3794                                    NULL, NULL);
3795   string = g_variant_print (value, FALSE);
3796   swapped = g_variant_byteswap (value);
3797   g_variant_unref (value);
3798   g_assert_cmpuint (g_variant_get_size (swapped), ==, 13);
3799   value = g_variant_byteswap (swapped);
3800   g_variant_unref (swapped);
3801   string2 = g_variant_print (value, FALSE);
3802   g_assert_cmpuint (g_variant_get_size (value), ==, 13);
3803   g_variant_unref (value);
3804   g_assert_cmpstr (string, ==, string2);
3805   g_free (string2);
3806   g_free (string);
3807 }
3808 
3809 static void
test_parser(void)3810 test_parser (void)
3811 {
3812   TreeInstance *tree;
3813   GVariant *parsed;
3814   GVariant *value;
3815   gchar *pt, *p;
3816   gchar *res;
3817 
3818   tree = tree_instance_new (NULL, 3);
3819   value = tree_instance_get_gvariant (tree);
3820   tree_instance_free (tree);
3821 
3822   pt = g_variant_print (value, TRUE);
3823   p = g_variant_print (value, FALSE);
3824 
3825   parsed = g_variant_parse (NULL, pt, NULL, NULL, NULL);
3826   res = g_variant_print (parsed, FALSE);
3827   g_assert_cmpstr (p, ==, res);
3828   g_variant_unref (parsed);
3829   g_free (res);
3830 
3831   parsed = g_variant_parse (g_variant_get_type (value), p,
3832                             NULL, NULL, NULL);
3833   res = g_variant_print (parsed, TRUE);
3834   g_assert_cmpstr (pt, ==, res);
3835   g_variant_unref (parsed);
3836   g_free (res);
3837 
3838   g_variant_unref (value);
3839   g_free (pt);
3840   g_free (p);
3841 }
3842 
3843 static void
test_parses(void)3844 test_parses (void)
3845 {
3846   gsize i;
3847 
3848   for (i = 0; i < 100; i++)
3849     {
3850       test_parser ();
3851     }
3852 
3853   /* mini test */
3854   {
3855     GError *error = NULL;
3856     gchar str[128];
3857     GVariant *val;
3858     gchar *p, *p2;
3859 
3860     for (i = 0; i < 127; i++)
3861       str[i] = i + 1;
3862     str[i] = 0;
3863 
3864     val = g_variant_new_string (str);
3865     p = g_variant_print (val, FALSE);
3866     g_variant_unref (val);
3867 
3868     val = g_variant_parse (NULL, p, NULL, NULL, &error);
3869     p2 = g_variant_print (val, FALSE);
3870 
3871     g_assert_cmpstr (str, ==, g_variant_get_string (val, NULL));
3872     g_assert_cmpstr (p, ==, p2);
3873 
3874     g_variant_unref (val);
3875     g_free (p2);
3876     g_free (p);
3877   }
3878 
3879   /* another mini test */
3880   {
3881     const gchar *end;
3882     GVariant *value;
3883 
3884     value = g_variant_parse (G_VARIANT_TYPE_INT32, "1 2 3", NULL, &end, NULL);
3885     g_assert_cmpint (g_variant_get_int32 (value), ==, 1);
3886     /* make sure endptr returning works */
3887     g_assert_cmpstr (end, ==, " 2 3");
3888     g_variant_unref (value);
3889   }
3890 
3891   /* unicode mini test */
3892   {
3893     /* ał�� */
3894     const gchar orig[] = "a\xc5\x82\xf0\x9d\x84\x9e \t\n";
3895     GVariant *value;
3896     gchar *printed;
3897 
3898     value = g_variant_new_string (orig);
3899     printed = g_variant_print (value, FALSE);
3900     g_variant_unref (value);
3901 
3902     g_assert_cmpstr (printed, ==, "'a\xc5\x82\xf0\x9d\x84\x9e \\t\\n'");
3903     value = g_variant_parse (NULL, printed, NULL, NULL, NULL);
3904     g_assert_cmpstr (g_variant_get_string (value, NULL), ==, orig);
3905     g_variant_unref (value);
3906     g_free (printed);
3907   }
3908 
3909   /* escapes */
3910   {
3911     const gchar orig[] = " \342\200\254 \360\220\210\240 \a \b \f \n \r \t \v ";
3912     GVariant *value;
3913     gchar *printed;
3914 
3915     value = g_variant_new_string (orig);
3916     printed = g_variant_print (value, FALSE);
3917     g_variant_unref (value);
3918 
3919     g_assert_cmpstr (printed, ==, "' \\u202c \\U00010220 \\a \\b \\f \\n \\r \\t \\v '");
3920     value = g_variant_parse (NULL, printed, NULL, NULL, NULL);
3921     g_assert_cmpstr (g_variant_get_string (value, NULL), ==, orig);
3922     g_variant_unref (value);
3923     g_free (printed);
3924   }
3925 
3926   /* pattern coalese of `MN` and `*` is `MN` */
3927   {
3928     GVariant *value = NULL;
3929     GError *error = NULL;
3930 
3931     value = g_variant_parse (NULL, "[[0], [], [nothing]]", NULL, NULL, &error);
3932     g_assert_no_error (error);
3933     g_assert_cmpstr (g_variant_get_type_string (value), ==, "aami");
3934     g_variant_unref (value);
3935   }
3936 
3937 #ifndef _MSC_VER
3938   /* inf/nan strings are C99 features which Visual C++ does not support */
3939   /* inf/nan mini test */
3940   {
3941     const gchar *tests[] = { "inf", "-inf", "nan" };
3942     GVariant *value;
3943     gchar *printed;
3944     gchar *printed_down;
3945     gsize i;
3946 
3947     for (i = 0; i < G_N_ELEMENTS (tests); i++)
3948       {
3949         GError *error = NULL;
3950         value = g_variant_parse (NULL, tests[i], NULL, NULL, &error);
3951         printed = g_variant_print (value, FALSE);
3952         /* Canonicalize to lowercase; https://bugzilla.gnome.org/show_bug.cgi?id=704585 */
3953         printed_down = g_ascii_strdown (printed, -1);
3954         g_assert_true (g_str_has_prefix (printed_down, tests[i]));
3955         g_free (printed);
3956         g_free (printed_down);
3957         g_variant_unref (value);
3958       }
3959   }
3960 #endif
3961 
3962   g_variant_type_info_assert_no_infos ();
3963 }
3964 
3965 static void
test_parse_failures(void)3966 test_parse_failures (void)
3967 {
3968   const gchar *test[] = {
3969     "[1, 2,",                   "6:",              "expected value",
3970     "",                         "0:",              "expected value",
3971     "(1, 2,",                   "6:",              "expected value",
3972     "<1",                       "2:",              "expected '>'",
3973     "[]",                       "0-2:",            "unable to infer",
3974     "(,",                       "1:",              "expected value",
3975     "[4,'']",                   "1-2,3-5:",        "common type",
3976     "[4, '', 5]",               "1-2,4-6:",        "common type",
3977     "['', 4, 5]",               "1-3,5-6:",        "common type",
3978     "[4, 5, '']",               "1-2,7-9:",        "common type",
3979     "[[4], [], ['']]",          "1-4,10-14:",      "common type",
3980     "[[], [4], ['']]",          "5-8,10-14:",      "common type",
3981     "just",                     "4:",              "expected value",
3982     "nothing",                  "0-7:",            "unable to infer",
3983     "just [4, '']",             "6-7,9-11:",       "common type",
3984     "[[4,'']]",                 "2-3,4-6:",        "common type",
3985     "([4,''],)",                "2-3,4-6:",        "common type",
3986     "(4)",                      "2:",              "','",
3987     "{}",                       "0-2:",            "unable to infer",
3988     "{[1,2],[3,4]}",            "0-13:",           "basic types",
3989     "{[1,2]:[3,4]}",            "0-13:",           "basic types",
3990     "justt",                    "0-5:",            "unknown keyword",
3991     "nothng",                   "0-6:",            "unknown keyword",
3992     "uint33",                   "0-6:",            "unknown keyword",
3993     "@mi just ''",              "9-11:",           "can not parse as",
3994     "@ai ['']",                 "5-7:",            "can not parse as",
3995     "@(i) ('',)",               "6-8:",            "can not parse as",
3996     "[[], 5]",                  "1-3,5-6:",        "common type",
3997     "[[5], 5]",                 "1-4,6-7:",        "common type",
3998     "5 5",                      "2:",              "expected end of input",
3999     "[5, [5, '']]",             "5-6,8-10:",       "common type",
4000     "@i just 5",                "3-9:",            "can not parse as",
4001     "@i nothing",               "3-10:",           "can not parse as",
4002     "@i []",                    "3-5:",            "can not parse as",
4003     "@i ()",                    "3-5:",            "can not parse as",
4004     "@ai (4,)",                 "4-8:",            "can not parse as",
4005     "@(i) []",                  "5-7:",            "can not parse as",
4006     "(5 5)",                    "3:",              "expected ','",
4007     "[5 5]",                    "3:",              "expected ',' or ']'",
4008     "(5, 5 5)",                 "6:",              "expected ',' or ')'",
4009     "[5, 5 5]",                 "6:",              "expected ',' or ']'",
4010     "<@i []>",                  "4-6:",            "can not parse as",
4011     "<[5 5]>",                  "4:",              "expected ',' or ']'",
4012     "{[4,''],5}",               "2-3,4-6:",        "common type",
4013     "{5,[4,'']}",               "4-5,6-8:",        "common type",
4014     "@i {1,2}",                 "3-8:",            "can not parse as",
4015     "{@i '', 5}",               "4-6:",            "can not parse as",
4016     "{5, @i ''}",               "7-9:",            "can not parse as",
4017     "@ai {}",                   "4-6:",            "can not parse as",
4018     "{@i '': 5}",               "4-6:",            "can not parse as",
4019     "{5: @i ''}",               "7-9:",            "can not parse as",
4020     "{<4,5}",                   "3:",              "expected '>'",
4021     "{4,<5}",                   "5:",              "expected '>'",
4022     "{4,5,6}",                  "4:",              "expected '}'",
4023     "{5 5}",                    "3:",              "expected ':' or ','",
4024     "{4: 5: 6}",                "5:",              "expected ',' or '}'",
4025     "{4:5,<6:7}",               "7:",              "expected '>'",
4026     "{4:5,6:<7}",               "9:",              "expected '>'",
4027     "{4:5,6 7}",                "7:",              "expected ':'",
4028     "@o 'foo'",                 "3-8:",            "object path",
4029     "@g 'zzz'",                 "3-8:",            "signature",
4030     "@i true",                  "3-7:",            "can not parse as",
4031     "@z 4",                     "0-2:",            "invalid type",
4032     "@a* []",                   "0-3:",            "definite",
4033     "@ai [3 3]",                "7:",              "expected ',' or ']'",
4034     "18446744073709551616",     "0-20:",           "too big for any type",
4035     "-18446744073709551616",    "0-21:",           "too big for any type",
4036     "byte 256",                 "5-8:",            "out of range for type",
4037     "byte -1",                  "5-7:",            "out of range for type",
4038     "int16 32768",              "6-11:",           "out of range for type",
4039     "int16 -32769",             "6-12:",           "out of range for type",
4040     "uint16 -1",                "7-9:",            "out of range for type",
4041     "uint16 65536",             "7-12:",           "out of range for type",
4042     "2147483648",               "0-10:",           "out of range for type",
4043     "-2147483649",              "0-11:",           "out of range for type",
4044     "uint32 -1",                "7-9:",            "out of range for type",
4045     "uint32 4294967296",        "7-17:",           "out of range for type",
4046     "@x 9223372036854775808",   "3-22:",           "out of range for type",
4047     "@x -9223372036854775809",  "3-23:",           "out of range for type",
4048     "@t -1",                    "3-5:",            "out of range for type",
4049     "@t 18446744073709551616",  "3-23:",           "too big for any type",
4050     "handle 2147483648",        "7-17:",           "out of range for type",
4051     "handle -2147483649",       "7-18:",           "out of range for type",
4052     "1.798e308",                "0-9:",            "too big for any type",
4053     "37.5a488",                 "4-5:",            "invalid character",
4054     "0x7ffgf",                  "5-6:",            "invalid character",
4055     "07758",                    "4-5:",            "invalid character",
4056     "123a5",                    "3-4:",            "invalid character",
4057     "@ai 123",                  "4-7:",            "can not parse as",
4058     "'\"\\'",                   "0-4:",            "unterminated string",
4059     "'\"\\'\\",                 "0-5:",            "unterminated string",
4060     "boolean 4",                "8-9:",            "can not parse as",
4061     "int32 true",               "6-10:",           "can not parse as",
4062     "[double 5, int32 5]",      "1-9,11-18:",      "common type",
4063     "string 4",                 "7-8:",            "can not parse as",
4064     "\x0a",                     "1:",              "expected value",
4065     "((",                       "2:",              "expected value",
4066     "(b",                       "1:",              "expected value",
4067     "b'",                       "0-2:",            "unterminated string constant",
4068     "b\"",                      "0-2:",            "unterminated string constant",
4069     "b'a",                      "0-3:",            "unterminated string constant",
4070     "b\"a",                     "0-3:",            "unterminated string constant",
4071     "b'\\",                     "0-3:",            "unterminated string constant",
4072     "b\"\\",                    "0-3:",            "unterminated string constant",
4073     "b'\\'",                    "0-4:",            "unterminated string constant",
4074     "b\"\\\"",                  "0-4:",            "unterminated string constant",
4075     "b'\\'a",                   "0-5:",            "unterminated string constant",
4076     "b\"\\\"a",                 "0-5:",            "unterminated string constant",
4077     "'\\u-ff4'",                "3:",              "invalid 4-character unicode escape",
4078     "'\\u+ff4'",                "3:",              "invalid 4-character unicode escape",
4079     "'\\u'",                    "3:",              "invalid 4-character unicode escape",
4080     "'\\u0'",                   "3-4:",            "invalid 4-character unicode escape",
4081     "'\\uHELLO'",               "3:",              "invalid 4-character unicode escape",
4082     "'\\u ff4'",                "3:",              "invalid 4-character unicode escape",
4083     "'\\u012'",                 "3-6:",            "invalid 4-character unicode escape",
4084     "'\\u0xff4'",               "3-4:",            "invalid 4-character unicode escape",
4085     "'\\U-ff4'",                "3:",              "invalid 8-character unicode escape",
4086     "'\\U+ff4'",                "3:",              "invalid 8-character unicode escape",
4087     "'\\U'",                    "3:",              "invalid 8-character unicode escape",
4088     "'\\U0'",                   "3-4:",            "invalid 8-character unicode escape",
4089     "'\\UHELLO'",               "3:",              "invalid 8-character unicode escape",
4090     "'\\U ff4'",                "3:",              "invalid 8-character unicode escape",
4091     "'\\U0123456'",             "3-10:",           "invalid 8-character unicode escape",
4092     "'\\U0xff4'",               "3-4:",            "invalid 8-character unicode escape",
4093   };
4094   guint i;
4095 
4096   for (i = 0; i < G_N_ELEMENTS (test); i += 3)
4097     {
4098       GError *error1 = NULL, *error2 = NULL;
4099       GVariant *value;
4100 
4101       /* Copy the test string and drop its nul terminator, then use the @limit
4102        * parameter of g_variant_parse() to set the length. This allows valgrind
4103        * to catch 1-byte heap buffer overflows. */
4104       gsize test_len = MAX (strlen (test[i]), 1);
4105       gchar *test_blob = g_malloc0 (test_len);  /* no nul terminator */
4106 
4107       memcpy (test_blob, test[i], test_len);
4108       value = g_variant_parse (NULL, test_blob, test_blob + test_len, NULL, &error1);
4109       g_assert_null (value);
4110 
4111       g_free (test_blob);
4112 
4113       if (!strstr (error1->message, test[i+2]))
4114         g_error ("test %u: Can't find '%s' in '%s'", i / 3,
4115                  test[i+2], error1->message);
4116 
4117       if (!g_str_has_prefix (error1->message, test[i+1]))
4118         g_error ("test %u: Expected location '%s' in '%s'", i / 3,
4119                  test[i+1], error1->message);
4120 
4121       /* Test again with the nul terminator this time. The behaviour should be
4122        * the same. */
4123       value = g_variant_parse (NULL, test[i], NULL, NULL, &error2);
4124       g_assert_null (value);
4125 
4126       g_assert_cmpint (error1->domain, ==, error2->domain);
4127       g_assert_cmpint (error1->code, ==, error2->code);
4128       g_assert_cmpstr (error1->message, ==, error2->message);
4129 
4130       g_clear_error (&error1);
4131       g_clear_error (&error2);
4132     }
4133 }
4134 
4135 /* Test that parsing GVariant text format integers works at the boundaries of
4136  * those integer types. We’re especially interested in the handling of the most
4137  * negative numbers, since those can’t be represented in sign + absolute value
4138  * form. */
4139 static void
test_parser_integer_bounds(void)4140 test_parser_integer_bounds (void)
4141 {
4142   GVariant *value = NULL;
4143   GError *local_error = NULL;
4144 
4145 #define test_bound(TYPE, type, text, expected_value) \
4146   value = g_variant_parse (G_VARIANT_TYPE_##TYPE, text, NULL, NULL, &local_error); \
4147   g_assert_no_error (local_error); \
4148   g_assert_nonnull (value); \
4149   g_assert_true (g_variant_is_of_type (value, G_VARIANT_TYPE_##TYPE)); \
4150   g_assert_cmpint (g_variant_get_##type (value), ==, expected_value); \
4151   g_variant_unref (value)
4152 
4153   test_bound (BYTE, byte, "0", 0);
4154   test_bound (BYTE, byte, "255", G_MAXUINT8);
4155   test_bound (INT16, int16, "-32768", G_MININT16);
4156   test_bound (INT16, int16, "32767", G_MAXINT16);
4157   test_bound (INT32, int32, "-2147483648", G_MININT32);
4158   test_bound (INT32, int32, "2147483647", G_MAXINT32);
4159   test_bound (INT64, int64, "-9223372036854775808", G_MININT64);
4160   test_bound (INT64, int64, "9223372036854775807", G_MAXINT64);
4161   test_bound (HANDLE, handle, "-2147483648", G_MININT32);
4162   test_bound (HANDLE, handle, "2147483647", G_MAXINT32);
4163 
4164 #undef test_bound
4165 }
4166 
4167 /* Test that #GVariants which recurse too deeply are rejected. */
4168 static void
test_parser_recursion(void)4169 test_parser_recursion (void)
4170 {
4171   GVariant *value = NULL;
4172   GError *local_error = NULL;
4173   const guint recursion_depth = G_VARIANT_MAX_RECURSION_DEPTH + 1;
4174   gchar *silly_dict = g_malloc0 (recursion_depth * 2 + 1);
4175   gsize i;
4176 
4177   for (i = 0; i < recursion_depth; i++)
4178     {
4179       silly_dict[i] = '{';
4180       silly_dict[recursion_depth * 2 - i - 1] = '}';
4181     }
4182 
4183   value = g_variant_parse (NULL, silly_dict, NULL, NULL, &local_error);
4184   g_assert_error (local_error, G_VARIANT_PARSE_ERROR, G_VARIANT_PARSE_ERROR_RECURSION);
4185   g_assert_null (value);
4186   g_error_free (local_error);
4187   g_free (silly_dict);
4188 }
4189 
4190 static void
test_parse_bad_format_char(void)4191 test_parse_bad_format_char (void)
4192 {
4193   g_variant_new_parsed ("%z");
4194 
4195   g_assert_not_reached ();
4196 }
4197 
4198 static void
test_parse_bad_format_string(void)4199 test_parse_bad_format_string (void)
4200 {
4201   g_variant_new_parsed ("uint32 %i", 2);
4202 
4203   g_assert_not_reached ();
4204 }
4205 
4206 static void
test_parse_bad_args(void)4207 test_parse_bad_args (void)
4208 {
4209   g_variant_new_parsed ("%@i", g_variant_new_uint32 (2));
4210 
4211   g_assert_not_reached ();
4212 }
4213 
4214 static void
test_parse_positional(void)4215 test_parse_positional (void)
4216 {
4217   GVariant *value;
4218   check_and_free (g_variant_new_parsed ("[('one', 1), (%s, 2),"
4219                                         " ('three', %i)]", "two", 3),
4220                   "[('one', 1), ('two', 2), ('three', 3)]");
4221   value = g_variant_new_parsed ("[('one', 1), (%s, 2),"
4222                                 " ('three', %u)]", "two", 3);
4223   g_assert_true (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(su)")));
4224   check_and_free (value, "[('one', 1), ('two', 2), ('three', 3)]");
4225   check_and_free (g_variant_new_parsed ("{%s:%i}", "one", 1), "{'one': 1}");
4226 
4227   if (g_test_undefined ())
4228     {
4229       do_failed_test ("/gvariant/parse/subprocess/bad-format-char",
4230                       "*GVariant format string*");
4231 
4232       do_failed_test ("/gvariant/parse/subprocess/bad-format-string",
4233                       "*can not parse as*");
4234 
4235       do_failed_test ("/gvariant/parse/subprocess/bad-args",
4236                       "*expected GVariant of type 'i'*");
4237     }
4238 }
4239 
4240 static void
test_floating(void)4241 test_floating (void)
4242 {
4243   GVariant *value;
4244 
4245   value = g_variant_new_int32 (42);
4246   g_assert_true (g_variant_is_floating (value));
4247   g_variant_ref_sink (value);
4248   g_assert_true (!g_variant_is_floating (value));
4249   g_variant_unref (value);
4250 }
4251 
4252 static void
test_bytestring(void)4253 test_bytestring (void)
4254 {
4255   const gchar *test_string = "foo,bar,baz,quux,\xffoooo";
4256   GVariant *value;
4257   gchar **strv;
4258   gchar *str;
4259   const gchar *const_str;
4260   GVariant *untrusted_empty;
4261 
4262   strv = g_strsplit (test_string, ",", 0);
4263 
4264   value = g_variant_new_bytestring_array ((const gchar **) strv, -1);
4265   g_assert_true (g_variant_is_floating (value));
4266   g_strfreev (strv);
4267 
4268   str = g_variant_print (value, FALSE);
4269   g_variant_unref (value);
4270 
4271   value = g_variant_parse (NULL, str, NULL, NULL, NULL);
4272   g_free (str);
4273 
4274   strv = g_variant_dup_bytestring_array (value, NULL);
4275   g_variant_unref (value);
4276 
4277   str = g_strjoinv (",", strv);
4278   g_strfreev (strv);
4279 
4280   g_assert_cmpstr (str, ==, test_string);
4281   g_free (str);
4282 
4283   strv = g_strsplit (test_string, ",", 0);
4284   value = g_variant_new ("(^aay^a&ay^ay^&ay)",
4285                          strv, strv, strv[0], strv[0]);
4286   g_strfreev (strv);
4287 
4288   g_variant_get_child (value, 0, "^a&ay", &strv);
4289   str = g_strjoinv (",", strv);
4290   g_free (strv);
4291   g_assert_cmpstr (str, ==, test_string);
4292   g_free (str);
4293 
4294   g_variant_get_child (value, 0, "^aay", &strv);
4295   str = g_strjoinv (",", strv);
4296   g_strfreev (strv);
4297   g_assert_cmpstr (str, ==, test_string);
4298   g_free (str);
4299 
4300   g_variant_get_child (value, 1, "^a&ay", &strv);
4301   str = g_strjoinv (",", strv);
4302   g_free (strv);
4303   g_assert_cmpstr (str, ==, test_string);
4304   g_free (str);
4305 
4306   g_variant_get_child (value, 1, "^aay", &strv);
4307   str = g_strjoinv (",", strv);
4308   g_strfreev (strv);
4309   g_assert_cmpstr (str, ==, test_string);
4310   g_free (str);
4311 
4312   g_variant_get_child (value, 2, "^ay", &str);
4313   g_assert_cmpstr (str, ==, "foo");
4314   g_free (str);
4315 
4316   g_variant_get_child (value, 2, "^&ay", &str);
4317   g_assert_cmpstr (str, ==, "foo");
4318 
4319   g_variant_get_child (value, 3, "^ay", &str);
4320   g_assert_cmpstr (str, ==, "foo");
4321   g_free (str);
4322 
4323   g_variant_get_child (value, 3, "^&ay", &str);
4324   g_assert_cmpstr (str, ==, "foo");
4325   g_variant_unref (value);
4326 
4327   untrusted_empty = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), NULL, 0, FALSE, NULL, NULL);
4328   value = g_variant_get_normal_form (untrusted_empty);
4329   const_str = g_variant_get_bytestring (value);
4330   (void) const_str;
4331   g_variant_unref (value);
4332   g_variant_unref (untrusted_empty);
4333 }
4334 
4335 static void
test_lookup_value(void)4336 test_lookup_value (void)
4337 {
4338   struct {
4339     const gchar *dict, *key, *value;
4340   } cases[] = {
4341     { "@a{ss} {'x':  'y'}",   "x",  "'y'" },
4342     { "@a{ss} {'x':  'y'}",   "y",  NULL  },
4343     { "@a{os} {'/x': 'y'}",   "/x", "'y'" },
4344     { "@a{os} {'/x': 'y'}",   "/y", NULL  },
4345     { "@a{sv} {'x':  <'y'>}", "x",  "'y'" },
4346     { "@a{sv} {'x':  <5>}",   "x",  "5"   },
4347     { "@a{sv} {'x':  <'y'>}", "y",  NULL  }
4348   };
4349   gsize i;
4350 
4351   for (i = 0; i < G_N_ELEMENTS (cases); i++)
4352     {
4353       GVariant *dictionary;
4354       GVariant *value;
4355       gchar *p;
4356 
4357       dictionary = g_variant_parse (NULL, cases[i].dict, NULL, NULL, NULL);
4358       value = g_variant_lookup_value (dictionary, cases[i].key, NULL);
4359       g_variant_unref (dictionary);
4360 
4361       if (value == NULL && cases[i].value == NULL)
4362         continue;
4363 
4364       g_assert_true (value && cases[i].value);
4365       p = g_variant_print (value, FALSE);
4366       g_assert_cmpstr (cases[i].value, ==, p);
4367       g_variant_unref (value);
4368       g_free (p);
4369     }
4370 }
4371 
4372 static void
test_lookup(void)4373 test_lookup (void)
4374 {
4375   const gchar *str;
4376   GVariant *dict;
4377   gboolean ok;
4378   gint num;
4379 
4380   dict = g_variant_parse (NULL,
4381                           "{'a': <5>, 'b': <'c'>}",
4382                           NULL, NULL, NULL);
4383 
4384   ok = g_variant_lookup (dict, "a", "i", &num);
4385   g_assert_true (ok);
4386   g_assert_cmpint (num, ==, 5);
4387 
4388   ok = g_variant_lookup (dict, "a", "&s", &str);
4389   g_assert_false (ok);
4390 
4391   ok = g_variant_lookup (dict, "q", "&s", &str);
4392   g_assert_false (ok);
4393 
4394   ok = g_variant_lookup (dict, "b", "i", &num);
4395   g_assert_false (ok);
4396 
4397   ok = g_variant_lookup (dict, "b", "&s", &str);
4398   g_assert_true (ok);
4399   g_assert_cmpstr (str, ==, "c");
4400 
4401   ok = g_variant_lookup (dict, "q", "&s", &str);
4402   g_assert_false (ok);
4403 
4404   g_variant_unref (dict);
4405 }
4406 
4407 static GVariant *
untrusted(GVariant * a)4408 untrusted (GVariant *a)
4409 {
4410   GVariant *b;
4411   const GVariantType *type;
4412   GBytes *bytes;
4413 
4414   type = g_variant_get_type (a);
4415   bytes = g_variant_get_data_as_bytes (a);
4416   b = g_variant_new_from_bytes (type, bytes, FALSE);
4417   g_bytes_unref (bytes);
4418   g_variant_unref (a);
4419 
4420   return b;
4421 }
4422 
4423 static void
test_compare(void)4424 test_compare (void)
4425 {
4426   GVariant *a;
4427   GVariant *b;
4428 
4429   a = untrusted (g_variant_new_byte (5));
4430   b = g_variant_new_byte (6);
4431   g_assert_cmpint (g_variant_compare (a, b), <, 0);
4432   g_variant_unref (a);
4433   g_variant_unref (b);
4434   a = untrusted (g_variant_new_int16 (G_MININT16));
4435   b = g_variant_new_int16 (G_MAXINT16);
4436   g_assert_cmpint (g_variant_compare (a, b), <, 0);
4437   g_variant_unref (a);
4438   g_variant_unref (b);
4439   a = untrusted (g_variant_new_uint16 (0));
4440   b = g_variant_new_uint16 (G_MAXUINT16);
4441   g_assert_cmpint (g_variant_compare (a, b), <, 0);
4442   g_variant_unref (a);
4443   g_variant_unref (b);
4444   a = untrusted (g_variant_new_int32 (G_MININT32));
4445   b = g_variant_new_int32 (G_MAXINT32);
4446   g_assert_cmpint (g_variant_compare (a, b), <, 0);
4447   g_variant_unref (a);
4448   g_variant_unref (b);
4449   a = untrusted (g_variant_new_uint32 (0));
4450   b = g_variant_new_uint32 (G_MAXUINT32);
4451   g_assert_cmpint (g_variant_compare (a, b), <, 0);
4452   g_variant_unref (a);
4453   g_variant_unref (b);
4454   a = untrusted (g_variant_new_int64 (G_MININT64));
4455   b = g_variant_new_int64 (G_MAXINT64);
4456   g_assert_cmpint (g_variant_compare (a, b), <, 0);
4457   g_variant_unref (a);
4458   g_variant_unref (b);
4459   a = untrusted (g_variant_new_uint64 (0));
4460   b = g_variant_new_uint64 (G_MAXUINT64);
4461   g_assert_cmpint (g_variant_compare (a, b), <, 0);
4462   g_variant_unref (a);
4463   g_variant_unref (b);
4464   a = untrusted (g_variant_new_double (G_MINDOUBLE));
4465   b = g_variant_new_double (G_MAXDOUBLE);
4466   g_assert_cmpint (g_variant_compare (a, b), <, 0);
4467   g_variant_unref (a);
4468   g_variant_unref (b);
4469   a = untrusted (g_variant_new_string ("abc"));
4470   b = g_variant_new_string ("abd");
4471   g_assert_cmpint (g_variant_compare (a, b), <, 0);
4472   g_variant_unref (a);
4473   g_variant_unref (b);
4474   a = untrusted (g_variant_new_object_path ("/abc"));
4475   b = g_variant_new_object_path ("/abd");
4476   g_assert_cmpint (g_variant_compare (a, b), <, 0);
4477   g_variant_unref (a);
4478   g_variant_unref (b);
4479   a = untrusted (g_variant_new_signature ("g"));
4480   b = g_variant_new_signature ("o");
4481   g_assert_cmpint (g_variant_compare (a, b), <, 0);
4482   g_variant_unref (a);
4483   g_variant_unref (b);
4484   a = untrusted (g_variant_new_boolean (FALSE));
4485   b = g_variant_new_boolean (TRUE);
4486   g_assert_cmpint (g_variant_compare (a, b), <, 0);
4487   g_variant_unref (a);
4488   g_variant_unref (b);
4489 }
4490 
4491 static void
test_equal(void)4492 test_equal (void)
4493 {
4494   GVariant *a;
4495   GVariant *b;
4496 
4497   a = untrusted (g_variant_new_byte (5));
4498   b = g_variant_get_normal_form (a);
4499   g_assert_cmpvariant (a, b);
4500   g_variant_unref (a);
4501   g_variant_unref (b);
4502   a = untrusted (g_variant_new_int16 (G_MININT16));
4503   b = g_variant_get_normal_form (a);
4504   g_assert_cmpvariant (a, b);
4505   g_variant_unref (a);
4506   g_variant_unref (b);
4507   a = untrusted (g_variant_new_uint16 (0));
4508   b = g_variant_get_normal_form (a);
4509   g_assert_cmpvariant (a, b);
4510   g_variant_unref (a);
4511   g_variant_unref (b);
4512   a = untrusted (g_variant_new_int32 (G_MININT32));
4513   b = g_variant_get_normal_form (a);
4514   g_assert_cmpvariant (a, b);
4515   g_variant_unref (a);
4516   g_variant_unref (b);
4517   a = untrusted (g_variant_new_uint32 (0));
4518   b = g_variant_get_normal_form (a);
4519   g_assert_cmpvariant (a, b);
4520   g_variant_unref (a);
4521   g_variant_unref (b);
4522   a = untrusted (g_variant_new_int64 (G_MININT64));
4523   b = g_variant_get_normal_form (a);
4524   g_assert_cmpvariant (a, b);
4525   g_variant_unref (a);
4526   g_variant_unref (b);
4527   a = untrusted (g_variant_new_uint64 (0));
4528   b = g_variant_get_normal_form (a);
4529   g_assert_cmpvariant (a, b);
4530   g_variant_unref (a);
4531   g_variant_unref (b);
4532   a = untrusted (g_variant_new_double (G_MINDOUBLE));
4533   b = g_variant_get_normal_form (a);
4534   g_assert_cmpvariant (a, b);
4535   g_variant_unref (a);
4536   g_variant_unref (b);
4537   a = untrusted (g_variant_new_string ("abc"));
4538   g_assert_cmpvariant (a, a);
4539   b = g_variant_get_normal_form (a);
4540   g_assert_cmpvariant (a, b);
4541   g_variant_unref (a);
4542   g_variant_unref (b);
4543   a = untrusted (g_variant_new_object_path ("/abc"));
4544   g_assert_cmpvariant (a, a);
4545   b = g_variant_get_normal_form (a);
4546   a = untrusted (a);
4547   g_assert_cmpvariant (a, b);
4548   g_variant_unref (a);
4549   g_variant_unref (b);
4550   a = untrusted (g_variant_new_signature ("g"));
4551   g_assert_cmpvariant (a, a);
4552   b = g_variant_get_normal_form (a);
4553   a = untrusted (a);
4554   g_assert_cmpvariant (a, b);
4555   g_variant_unref (a);
4556   g_variant_unref (b);
4557   a = untrusted (g_variant_new_boolean (FALSE));
4558   b = g_variant_get_normal_form (a);
4559   g_assert_cmpvariant (a, b);
4560   g_variant_unref (a);
4561   g_variant_unref (b);
4562 }
4563 
4564 static void
test_fixed_array(void)4565 test_fixed_array (void)
4566 {
4567   GVariant *a;
4568   gint32 values[5];
4569   const gint32 *elts;
4570   gsize n_elts;
4571   gsize i;
4572 
4573   n_elts = 0;
4574   a = g_variant_new_parsed ("[1,2,3,4,5]");
4575   elts = g_variant_get_fixed_array (a, &n_elts, sizeof (gint32));
4576   g_assert_cmpuint (n_elts, ==, 5);
4577   for (i = 0; i < 5; i++)
4578     g_assert_cmpint (elts[i], ==, i + 1);
4579   g_variant_unref (a);
4580 
4581   n_elts = 0;
4582   for (i = 0; i < 5; i++)
4583     values[i] = i + 1;
4584   a = g_variant_new_fixed_array (G_VARIANT_TYPE_INT32, values,
4585                                  G_N_ELEMENTS (values), sizeof (values[0]));
4586   g_assert_cmpstr (g_variant_get_type_string (a), ==, "ai");
4587   elts = g_variant_get_fixed_array (a, &n_elts, sizeof (gint32));
4588   g_assert_cmpuint (n_elts, ==, 5);
4589   for (i = 0; i < 5; i++)
4590     g_assert_cmpint (elts[i], ==, i + 1);
4591   g_variant_unref (a);
4592 }
4593 
4594 static void
test_check_format_string(void)4595 test_check_format_string (void)
4596 {
4597   GVariant *value;
4598 
4599   value = g_variant_new ("(sas)", "foo", NULL);
4600   g_variant_ref_sink (value);
4601 
4602   g_assert_true (g_variant_check_format_string (value, "(s*)", TRUE));
4603   g_assert_true (g_variant_check_format_string (value, "(s*)", FALSE));
4604   g_assert_false (g_variant_check_format_string (value, "(u*)", TRUE));
4605   g_assert_false (g_variant_check_format_string (value, "(u*)", FALSE));
4606 
4607   g_assert_true (g_variant_check_format_string (value, "(&s*)", FALSE));
4608   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
4609   g_assert_false (g_variant_check_format_string (value, "(&s*)", TRUE));
4610   g_test_assert_expected_messages ();
4611 
4612   g_assert_true (g_variant_check_format_string (value, "(s^as)", TRUE));
4613   g_assert_true (g_variant_check_format_string (value, "(s^as)", FALSE));
4614 
4615   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
4616   g_assert_false (g_variant_check_format_string (value, "(s^a&s)", TRUE));
4617   g_test_assert_expected_messages ();
4618   g_assert_true (g_variant_check_format_string (value, "(s^a&s)", FALSE));
4619 
4620   g_variant_unref (value);
4621 
4622   /* Do it again with a type that will let us put a '&' after a '^' */
4623   value = g_variant_new ("(say)", "foo", NULL);
4624   g_variant_ref_sink (value);
4625 
4626   g_assert_true (g_variant_check_format_string (value, "(s*)", TRUE));
4627   g_assert_true (g_variant_check_format_string (value, "(s*)", FALSE));
4628   g_assert_false (g_variant_check_format_string (value, "(u*)", TRUE));
4629   g_assert_false (g_variant_check_format_string (value, "(u*)", FALSE));
4630 
4631   g_assert_true (g_variant_check_format_string (value, "(&s*)", FALSE));
4632   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
4633   g_assert_false (g_variant_check_format_string (value, "(&s*)", TRUE));
4634   g_test_assert_expected_messages ();
4635 
4636   g_assert_true (g_variant_check_format_string (value, "(s^ay)", TRUE));
4637   g_assert_true (g_variant_check_format_string (value, "(s^ay)", FALSE));
4638 
4639   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
4640   g_assert_false (g_variant_check_format_string (value, "(s^&ay)", TRUE));
4641   g_test_assert_expected_messages ();
4642   g_assert_true (g_variant_check_format_string (value, "(s^&ay)", FALSE));
4643 
4644   g_assert_true (g_variant_check_format_string (value, "r", FALSE));
4645   g_assert_true (g_variant_check_format_string (value, "(?a?)", FALSE));
4646 
4647   g_variant_unref (value);
4648 }
4649 
4650 static void
verify_gvariant_checksum(const gchar * sha256,GVariant * v)4651 verify_gvariant_checksum (const gchar  *sha256,
4652 			  GVariant     *v)
4653 
4654 {
4655   gchar *checksum;
4656   checksum = g_compute_checksum_for_data (G_CHECKSUM_SHA256,
4657 					  g_variant_get_data (v),
4658 					  g_variant_get_size (v));
4659   g_assert_cmpstr (sha256, ==, checksum);
4660   g_free (checksum);
4661 }
4662 
4663 static void
verify_gvariant_checksum_va(const gchar * sha256,const gchar * fmt,...)4664 verify_gvariant_checksum_va (const gchar *sha256,
4665 			     const gchar *fmt,
4666 			     ...)
4667 {
4668   va_list args;
4669   GVariant *v;
4670 
4671   va_start (args, fmt);
4672 
4673   v = g_variant_new_va (fmt, NULL, &args);
4674   g_variant_ref_sink (v);
4675 #if G_BYTE_ORDER == G_BIG_ENDIAN
4676   {
4677     GVariant *byteswapped = g_variant_byteswap (v);
4678     g_variant_unref (v);
4679     v = byteswapped;
4680   }
4681 #endif
4682 
4683   va_end (args);
4684 
4685   verify_gvariant_checksum (sha256, v);
4686 
4687   g_variant_unref (v);
4688 }
4689 
4690 static void
test_checksum_basic(void)4691 test_checksum_basic (void)
4692 {
4693   verify_gvariant_checksum_va ("e8a4b2ee7ede79a3afb332b5b6cc3d952a65fd8cffb897f5d18016577c33d7cc",
4694 			       "u", 42);
4695   verify_gvariant_checksum_va ("c53e363c33b00cfce298229ee83856b8a98c2e6126cab13f65899f62473b0df5",
4696 			       "s", "moocow");
4697   verify_gvariant_checksum_va ("2b4c342f5433ebe591a1da77e013d1b72475562d48578dca8b84bac6651c3cb9",
4698 			       "y", 9);
4699   verify_gvariant_checksum_va ("12a3ae445661ce5dee78d0650d33362dec29c4f82af05e7e57fb595bbbacf0ca",
4700 			       "t", G_MAXUINT64);
4701   verify_gvariant_checksum_va ("e25a59b24440eb6c833aa79c93b9840e6eab6966add0dacf31df7e9e7000f5b3",
4702 			       "d", 3.14159);
4703   verify_gvariant_checksum_va ("4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a",
4704 			       "b", TRUE);
4705   verify_gvariant_checksum_va ("ca2fd00fa001190744c15c317643ab092e7048ce086a243e2be9437c898de1bb",
4706 			       "q", G_MAXUINT16);
4707 }
4708 
4709 static void
test_checksum_nested(void)4710 test_checksum_nested (void)
4711 {
4712   static const char* const strv[] = {"foo", "bar", "baz", NULL};
4713 
4714   verify_gvariant_checksum_va ("31fbc92f08fddaca716188fe4b5d44ae122fc6306fd3c6925af53cfa47ea596d",
4715 			       "(uu)", 41, 43);
4716   verify_gvariant_checksum_va ("01759d683cead856d1d386d59af0578841698a424a265345ad5413122f220de8",
4717 			       "(su)", "moocow", 79);
4718   verify_gvariant_checksum_va ("52b3ae95f19b3e642ea1d01185aea14a09004c1d1712672644427403a8a0afe6",
4719 			       "(qyst)", G_MAXUINT16, 9, "moocow", G_MAXUINT64);
4720   verify_gvariant_checksum_va ("6fc6f4524161c3ae0d316812d7088e3fcd372023edaea2d7821093be40ae1060",
4721 			       "(@ay)", g_variant_new_bytestring ("\xFF\xFF\xFF"));
4722   verify_gvariant_checksum_va ("572aca386e1a983dd23bb6eb6e3dfa72eef9ca7c7744581aa800e18d7d9d0b0b",
4723 			       "(^as)", strv);
4724   verify_gvariant_checksum_va ("4bddf6174c791bb44fc6a4106573031690064df34b741033a0122ed8dc05bcf3",
4725 			       "(yvu)", 254, g_variant_new ("(^as)", strv), 42);
4726 }
4727 
4728 static void
test_gbytes(void)4729 test_gbytes (void)
4730 {
4731   GVariant *a;
4732   GVariant *tuple;
4733   GBytes *bytes;
4734   GBytes *bytes2;
4735   const guint8 values[5] = { 1, 2, 3, 4, 5 };
4736   const guint8 *elts;
4737   gsize n_elts;
4738   gsize i;
4739 
4740   bytes = g_bytes_new (&values, 5);
4741   a = g_variant_new_from_bytes (G_VARIANT_TYPE_BYTESTRING, bytes, TRUE);
4742   g_bytes_unref (bytes);
4743   n_elts = 0;
4744   elts = g_variant_get_fixed_array (a, &n_elts, sizeof (guint8));
4745   g_assert_cmpuint (n_elts, ==, 5);
4746   for (i = 0; i < 5; i++)
4747     g_assert_cmpuint (elts[i], ==, i + 1);
4748 
4749   bytes2 = g_variant_get_data_as_bytes (a);
4750   g_variant_unref (a);
4751 
4752   bytes = g_bytes_new (&values, 5);
4753   g_assert_true (g_bytes_equal (bytes, bytes2));
4754   g_bytes_unref (bytes);
4755   g_bytes_unref (bytes2);
4756 
4757   tuple = g_variant_new_parsed ("['foo', 'bar']");
4758   bytes = g_variant_get_data_as_bytes (tuple); /* force serialization */
4759   a = g_variant_get_child_value (tuple, 1);
4760   bytes2 = g_variant_get_data_as_bytes (a);
4761   g_assert_false (g_bytes_equal (bytes, bytes2));
4762 
4763   g_bytes_unref (bytes);
4764   g_bytes_unref (bytes2);
4765   g_variant_unref (a);
4766   g_variant_unref (tuple);
4767 }
4768 
4769 typedef struct {
4770   const GVariantType *type;
4771   const gchar *in;
4772   const gchar *out;
4773 } ContextTest;
4774 
4775 static void
test_print_context(void)4776 test_print_context (void)
4777 {
4778   ContextTest tests[] = {
4779     { NULL, "(1, 2, 3, 'abc", "          ^^^^" },
4780     { NULL, "[1, 2, 3, 'str']", " ^        ^^^^^" },
4781     { G_VARIANT_TYPE_UINT16, "{ 'abc':'def' }", "  ^^^^^^^^^^^^^^^" },
4782     { NULL, "<5", "    ^" },
4783     { NULL, "'ab\\ux'", "       ^ " },
4784     { NULL, "'ab\\U00efx'", "       ^^^^  " }
4785   };
4786   GVariant *v;
4787   gchar *s;
4788   gsize i;
4789   GError *error = NULL;
4790 
4791   for (i = 0; i < G_N_ELEMENTS (tests); i++)
4792     {
4793       v = g_variant_parse (tests[i].type, tests[i].in, NULL, NULL, &error);
4794       g_assert_null (v);
4795       s = g_variant_parse_error_print_context (error, tests[i].in);
4796       g_assert_nonnull (strstr (s, tests[i].out));
4797       g_free (s);
4798       g_clear_error (&error);
4799     }
4800 }
4801 
4802 static void
test_error_quark(void)4803 test_error_quark (void)
4804 {
4805 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
4806   g_assert_cmpuint (g_variant_parser_get_error_quark (), ==, g_variant_parse_error_quark ());
4807 G_GNUC_END_IGNORE_DEPRECATIONS
4808 }
4809 
4810 static void
test_stack_builder_init(void)4811 test_stack_builder_init (void)
4812 {
4813   GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_BYTESTRING);
4814   GVariant *variant;
4815 
4816   g_variant_builder_add_value (&builder, g_variant_new_byte ('g'));
4817   g_variant_builder_add_value (&builder, g_variant_new_byte ('l'));
4818   g_variant_builder_add_value (&builder, g_variant_new_byte ('i'));
4819   g_variant_builder_add_value (&builder, g_variant_new_byte ('b'));
4820   g_variant_builder_add_value (&builder, g_variant_new_byte ('\0'));
4821 
4822   variant = g_variant_ref_sink (g_variant_builder_end (&builder));
4823   g_assert_nonnull (variant);
4824   g_assert_true (g_variant_type_equal (g_variant_get_type (variant),
4825                                        G_VARIANT_TYPE_BYTESTRING));
4826   g_assert_cmpuint (g_variant_n_children (variant), ==, 5);
4827   g_assert_cmpstr (g_variant_get_bytestring (variant), ==, "glib");
4828   g_variant_unref (variant);
4829 }
4830 
4831 static GVariant *
get_asv(void)4832 get_asv (void)
4833 {
4834   GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_VARDICT);
4835 
4836   g_variant_builder_add (&builder, "{s@v}", "foo", g_variant_new_variant (g_variant_new_string ("FOO")));
4837   g_variant_builder_add (&builder, "{s@v}", "bar", g_variant_new_variant (g_variant_new_string ("BAR")));
4838 
4839   return g_variant_ref_sink (g_variant_builder_end (&builder));
4840 }
4841 
4842 static void
test_stack_dict_init(void)4843 test_stack_dict_init (void)
4844 {
4845   GVariant *asv = get_asv ();
4846   GVariantDict dict = G_VARIANT_DICT_INIT (asv);
4847   GVariant *variant;
4848   GVariantIter iter;
4849   gchar *key;
4850   GVariant *value;
4851 
4852   g_variant_dict_insert_value (&dict, "baz", g_variant_new_string ("BAZ"));
4853   g_variant_dict_insert_value (&dict, "quux", g_variant_new_string ("QUUX"));
4854 
4855   variant = g_variant_ref_sink (g_variant_dict_end (&dict));
4856   g_assert_nonnull (variant);
4857   g_assert_true (g_variant_type_equal (g_variant_get_type (variant),
4858                                        G_VARIANT_TYPE_VARDICT));
4859   g_assert_cmpuint (g_variant_n_children (variant), ==, 4);
4860 
4861   g_variant_iter_init (&iter, variant);
4862   while (g_variant_iter_next (&iter, "{sv}", &key, &value))
4863     {
4864       gchar *strup = g_ascii_strup (key, -1);
4865 
4866       g_assert_cmpstr (strup, ==, g_variant_get_string (value, NULL));
4867       g_free (key);
4868       g_free (strup);
4869       g_variant_unref (value);
4870     }
4871 
4872   g_variant_unref (asv);
4873   g_variant_unref (variant);
4874 }
4875 
4876 /* Test checking arbitrary binary data for normal form. This time, it’s a tuple
4877  * with invalid element ends. */
4878 static void
test_normal_checking_tuples(void)4879 test_normal_checking_tuples (void)
4880 {
4881   const guint8 data[] = {
4882     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
4883     'a', '(', 'a', 'o', 'a', 'o', 'a', 'a', 'o', 'a', 'a', 'o', ')'
4884   };
4885   gsize size = sizeof (data);
4886   GVariant *variant = NULL;
4887   GVariant *normal_variant = NULL;
4888 
4889   variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size,
4890                                      FALSE, NULL, NULL);
4891   g_assert_nonnull (variant);
4892 
4893   normal_variant = g_variant_get_normal_form (variant);
4894   g_assert_nonnull (normal_variant);
4895 
4896   g_variant_unref (normal_variant);
4897   g_variant_unref (variant);
4898 }
4899 
4900 /* Check that deeply nested variants are not considered in normal form when
4901  * deserialized from untrusted data.*/
4902 static void
test_recursion_limits_variant_in_variant(void)4903 test_recursion_limits_variant_in_variant (void)
4904 {
4905   GVariant *wrapper_variant = NULL;
4906   gsize i;
4907   GBytes *bytes = NULL;
4908   GVariant *deserialised_variant = NULL;
4909 
4910   /* Construct a hierarchy of variants, containing a single string. This is just
4911    * below the maximum recursion level, as a series of nested variant types. */
4912   wrapper_variant = g_variant_new_string ("hello");
4913 
4914   for (i = 0; i < G_VARIANT_MAX_RECURSION_DEPTH - 1; i++)
4915     wrapper_variant = g_variant_new_variant (g_steal_pointer (&wrapper_variant));
4916 
4917   /* Serialize and deserialize it as untrusted data, to force normalisation. */
4918   bytes = g_variant_get_data_as_bytes (wrapper_variant);
4919   deserialised_variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT,
4920                                                    bytes, FALSE);
4921   g_assert_nonnull (deserialised_variant);
4922   g_assert_true (g_variant_is_normal_form (deserialised_variant));
4923 
4924   g_bytes_unref (bytes);
4925   g_variant_unref (deserialised_variant);
4926 
4927   /* Wrap it once more. Normalisation should now fail. */
4928   wrapper_variant = g_variant_new_variant (g_steal_pointer (&wrapper_variant));
4929 
4930   bytes = g_variant_get_data_as_bytes (wrapper_variant);
4931   deserialised_variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT,
4932                                                    bytes, FALSE);
4933   g_assert_nonnull (deserialised_variant);
4934   g_assert_false (g_variant_is_normal_form (deserialised_variant));
4935 
4936   g_variant_unref (deserialised_variant);
4937 
4938   /* Deserialize it again, but trusted this time. This should succeed. */
4939   deserialised_variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT,
4940                                                    bytes, TRUE);
4941   g_assert_nonnull (deserialised_variant);
4942   g_assert_true (g_variant_is_normal_form (deserialised_variant));
4943 
4944   g_bytes_unref (bytes);
4945   g_variant_unref (deserialised_variant);
4946   g_variant_unref (wrapper_variant);
4947 }
4948 
4949 /* Check that deeply nested arrays are not considered in normal form when
4950  * deserialized from untrusted data after being wrapped in a variant. This is
4951  * worth testing, because neither the deeply nested array, nor the variant,
4952  * have a static #GVariantType which is too deep — only when nested together do
4953  * they become too deep. */
4954 static void
test_recursion_limits_array_in_variant(void)4955 test_recursion_limits_array_in_variant (void)
4956 {
4957   GVariant *child_variant = NULL;
4958   GVariant *wrapper_variant = NULL;
4959   gsize i;
4960   GBytes *bytes = NULL;
4961   GVariant *deserialised_variant = NULL;
4962 
4963   /* Construct a hierarchy of arrays, containing a single string. This is just
4964    * below the maximum recursion level, all in a single definite type. */
4965   child_variant = g_variant_new_string ("hello");
4966 
4967   for (i = 0; i < G_VARIANT_MAX_RECURSION_DEPTH - 1; i++)
4968     child_variant = g_variant_new_array (NULL, &child_variant, 1);
4969 
4970   /* Serialize and deserialize it as untrusted data, to force normalisation. */
4971   bytes = g_variant_get_data_as_bytes (child_variant);
4972   deserialised_variant = g_variant_new_from_bytes (g_variant_get_type (child_variant),
4973                                                    bytes, FALSE);
4974   g_assert_nonnull (deserialised_variant);
4975   g_assert_true (g_variant_is_normal_form (deserialised_variant));
4976 
4977   g_bytes_unref (bytes);
4978   g_variant_unref (deserialised_variant);
4979 
4980   /* Wrap it in a variant. Normalisation should now fail. */
4981   wrapper_variant = g_variant_new_variant (g_steal_pointer (&child_variant));
4982 
4983   bytes = g_variant_get_data_as_bytes (wrapper_variant);
4984   deserialised_variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT,
4985                                                    bytes, FALSE);
4986   g_assert_nonnull (deserialised_variant);
4987   g_assert_false (g_variant_is_normal_form (deserialised_variant));
4988 
4989   g_variant_unref (deserialised_variant);
4990 
4991   /* Deserialize it again, but trusted this time. This should succeed. */
4992   deserialised_variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT,
4993                                                    bytes, TRUE);
4994   g_assert_nonnull (deserialised_variant);
4995   g_assert_true (g_variant_is_normal_form (deserialised_variant));
4996 
4997   g_bytes_unref (bytes);
4998   g_variant_unref (deserialised_variant);
4999   g_variant_unref (wrapper_variant);
5000 }
5001 
5002 /* Test that an array with invalidly large values in its offset table is
5003  * normalised successfully without looping infinitely. */
5004 static void
test_normal_checking_array_offsets(void)5005 test_normal_checking_array_offsets (void)
5006 {
5007   const guint8 data[] = {
5008     0x07, 0xe5, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00,
5009     'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'g',
5010   };
5011   gsize size = sizeof (data);
5012   GVariant *variant = NULL;
5013   GVariant *normal_variant = NULL;
5014 
5015   variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size,
5016                                      FALSE, NULL, NULL);
5017   g_assert_nonnull (variant);
5018 
5019   normal_variant = g_variant_get_normal_form (variant);
5020   g_assert_nonnull (normal_variant);
5021 
5022   g_variant_unref (normal_variant);
5023   g_variant_unref (variant);
5024 }
5025 
5026 /* Test that a tuple with invalidly large values in its offset table is
5027  * normalised successfully without looping infinitely. */
5028 static void
test_normal_checking_tuple_offsets(void)5029 test_normal_checking_tuple_offsets (void)
5030 {
5031   const guint8 data[] = {
5032     0x07, 0xe5, 0x00, 0x07, 0x00, 0x07,
5033     '(', 'a', 's', 'a', 's', 'a', 's', 'a', 's', 'a', 's', 'a', 's', ')',
5034   };
5035   gsize size = sizeof (data);
5036   GVariant *variant = NULL;
5037   GVariant *normal_variant = NULL;
5038 
5039   variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size,
5040                                      FALSE, NULL, NULL);
5041   g_assert_nonnull (variant);
5042 
5043   normal_variant = g_variant_get_normal_form (variant);
5044   g_assert_nonnull (normal_variant);
5045 
5046   g_variant_unref (normal_variant);
5047   g_variant_unref (variant);
5048 }
5049 
5050 /* Test that an empty object path is normalised successfully to the base object
5051  * path, ‘/’. */
5052 static void
test_normal_checking_empty_object_path(void)5053 test_normal_checking_empty_object_path (void)
5054 {
5055   const guint8 data[] = {
5056     0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
5057     '(', 'h', '(', 'a', 'i', 'a', 'b', 'i', 'o', ')', ')',
5058   };
5059   gsize size = sizeof (data);
5060   GVariant *variant = NULL;
5061   GVariant *normal_variant = NULL;
5062 
5063   variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size,
5064                                      FALSE, NULL, NULL);
5065   g_assert_nonnull (variant);
5066 
5067   normal_variant = g_variant_get_normal_form (variant);
5068   g_assert_nonnull (normal_variant);
5069 
5070   g_variant_unref (normal_variant);
5071   g_variant_unref (variant);
5072 }
5073 
5074 /* Test that constructing a #GVariant from data which is not correctly aligned
5075  * for the variant type is OK, by loading a variant from data at various offsets
5076  * which are aligned and unaligned. When unaligned, a slow construction path
5077  * should be taken. */
5078 static void
test_unaligned_construction(void)5079 test_unaligned_construction (void)
5080 {
5081   const guint8 data[] = {
5082     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
5083     0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
5084   };
5085   GVariant *variant = NULL;
5086   GVariant *normal_variant = NULL;
5087   gsize i, offset;
5088   const struct {
5089     const GVariantType *type;
5090     gsize size;
5091     gsize max_offset;
5092   } vectors[] = {
5093     { G_VARIANT_TYPE_UINT64, sizeof (guint64), sizeof (guint64) },
5094     { G_VARIANT_TYPE_UINT32, sizeof (guint32), sizeof (guint32) },
5095     { G_VARIANT_TYPE_UINT16, sizeof (guint16), sizeof (guint16) },
5096     { G_VARIANT_TYPE_BYTE, sizeof (guint8), 3 },
5097   };
5098 
5099   G_STATIC_ASSERT (sizeof (guint64) * 2 <= sizeof (data));
5100 
5101   for (i = 0; i < G_N_ELEMENTS (vectors); i++)
5102     {
5103       for (offset = 0; offset < vectors[i].max_offset; offset++)
5104         {
5105           variant = g_variant_new_from_data (vectors[i].type, data + offset,
5106                                              vectors[i].size,
5107                                              FALSE, NULL, NULL);
5108           g_assert_nonnull (variant);
5109 
5110           normal_variant = g_variant_get_normal_form (variant);
5111           g_assert_nonnull (normal_variant);
5112 
5113           g_variant_unref (normal_variant);
5114           g_variant_unref (variant);
5115         }
5116     }
5117 }
5118 
5119 int
main(int argc,char ** argv)5120 main (int argc, char **argv)
5121 {
5122   guint i;
5123 
5124   g_test_init (&argc, &argv, NULL);
5125 
5126   g_test_add_func ("/gvariant/type", test_gvarianttype);
5127   g_test_add_func ("/gvariant/type/string-scan/recursion/tuple",
5128                    test_gvarianttype_string_scan_recursion_tuple);
5129   g_test_add_func ("/gvariant/type/string-scan/recursion/array",
5130                    test_gvarianttype_string_scan_recursion_array);
5131   g_test_add_func ("/gvariant/typeinfo", test_gvarianttypeinfo);
5132   g_test_add_func ("/gvariant/serialiser/maybe", test_maybes);
5133   g_test_add_func ("/gvariant/serialiser/array", test_arrays);
5134   g_test_add_func ("/gvariant/serialiser/tuple", test_tuples);
5135   g_test_add_func ("/gvariant/serialiser/variant", test_variants);
5136   g_test_add_func ("/gvariant/serialiser/strings", test_strings);
5137   g_test_add_func ("/gvariant/serialiser/byteswap", test_byteswaps);
5138   g_test_add_func ("/gvariant/serialiser/children", test_serialiser_children);
5139 
5140   for (i = 1; i <= 20; i += 4)
5141     {
5142       char *testname;
5143 
5144       testname = g_strdup_printf ("/gvariant/serialiser/fuzz/%u%%", i);
5145       g_test_add_data_func (testname, GINT_TO_POINTER (i),
5146                             (gpointer) test_fuzzes);
5147       g_free (testname);
5148     }
5149 
5150   g_test_add_func ("/gvariant/string", test_string);
5151   g_test_add_func ("/gvariant/utf8", test_utf8);
5152   g_test_add_func ("/gvariant/containers", test_containers);
5153   g_test_add_func ("/gvariant/format-strings", test_format_strings);
5154   g_test_add_func ("/gvariant/invalid-varargs", test_invalid_varargs);
5155   g_test_add_func ("/gvariant/varargs", test_varargs);
5156   g_test_add_func ("/gvariant/varargs/subprocess/empty-array", test_varargs_empty_array);
5157   g_test_add_func ("/gvariant/valist", test_valist);
5158   g_test_add_func ("/gvariant/builder-memory", test_builder_memory);
5159   g_test_add_func ("/gvariant/hashing", test_hashing);
5160   g_test_add_func ("/gvariant/byteswap", test_gv_byteswap);
5161   g_test_add_func ("/gvariant/parser", test_parses);
5162   g_test_add_func ("/gvariant/parser/integer-bounds", test_parser_integer_bounds);
5163   g_test_add_func ("/gvariant/parser/recursion", test_parser_recursion);
5164   g_test_add_func ("/gvariant/parse-failures", test_parse_failures);
5165   g_test_add_func ("/gvariant/parse-positional", test_parse_positional);
5166   g_test_add_func ("/gvariant/parse/subprocess/bad-format-char", test_parse_bad_format_char);
5167   g_test_add_func ("/gvariant/parse/subprocess/bad-format-string", test_parse_bad_format_string);
5168   g_test_add_func ("/gvariant/parse/subprocess/bad-args", test_parse_bad_args);
5169   g_test_add_func ("/gvariant/floating", test_floating);
5170   g_test_add_func ("/gvariant/bytestring", test_bytestring);
5171   g_test_add_func ("/gvariant/lookup-value", test_lookup_value);
5172   g_test_add_func ("/gvariant/lookup", test_lookup);
5173   g_test_add_func ("/gvariant/compare", test_compare);
5174   g_test_add_func ("/gvariant/equal", test_equal);
5175   g_test_add_func ("/gvariant/fixed-array", test_fixed_array);
5176   g_test_add_func ("/gvariant/check-format-string", test_check_format_string);
5177 
5178   g_test_add_func ("/gvariant/checksum-basic", test_checksum_basic);
5179   g_test_add_func ("/gvariant/checksum-nested", test_checksum_nested);
5180 
5181   g_test_add_func ("/gvariant/gbytes", test_gbytes);
5182   g_test_add_func ("/gvariant/print-context", test_print_context);
5183   g_test_add_func ("/gvariant/error-quark", test_error_quark);
5184 
5185   g_test_add_func ("/gvariant/stack-builder-init", test_stack_builder_init);
5186   g_test_add_func ("/gvariant/stack-dict-init", test_stack_dict_init);
5187 
5188   g_test_add_func ("/gvariant/normal-checking/tuples",
5189                    test_normal_checking_tuples);
5190   g_test_add_func ("/gvariant/normal-checking/array-offsets",
5191                    test_normal_checking_array_offsets);
5192   g_test_add_func ("/gvariant/normal-checking/tuple-offsets",
5193                    test_normal_checking_tuple_offsets);
5194   g_test_add_func ("/gvariant/normal-checking/empty-object-path",
5195                    test_normal_checking_empty_object_path);
5196 
5197   g_test_add_func ("/gvariant/recursion-limits/variant-in-variant",
5198                    test_recursion_limits_variant_in_variant);
5199   g_test_add_func ("/gvariant/recursion-limits/array-in-variant",
5200                    test_recursion_limits_array_in_variant);
5201 
5202   g_test_add_func ("/gvariant/unaligned-construction",
5203                    test_unaligned_construction);
5204 
5205   return g_test_run ();
5206 }
5207