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