Coverage Report

Created: 2026-07-12 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gstreamer/subprojects/glib-2.86.3/glib/gvariant-parser.c
Line
Count
Source
1
/*
2
 * Copyright © 2009, 2010 Codethink Limited
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 *
19
 * Author: Ryan Lortie <desrt@desrt.ca>
20
 */
21
22
#include "config.h"
23
24
#include <stdlib.h>
25
#include <string.h>
26
#include <errno.h>
27
28
#include "gerror.h"
29
#include "gquark.h"
30
#include "gstring.h"
31
#include "gstrfuncs.h"
32
#include "gtestutils.h"
33
#include "gvariant.h"
34
#include "glib/gvariant-core.h"
35
#include "gvariant-internal.h"
36
#include "gvarianttype.h"
37
#include "gslice.h"
38
#include "gthread.h"
39
40
/*
41
 * two-pass algorithm
42
 * designed by ryan lortie and william hua
43
 * designed in itb-229 and at ghazi's, 2009.
44
 */
45
46
/**
47
 * G_VARIANT_PARSE_ERROR:
48
 *
49
 * Error domain for GVariant text format parsing.  Specific error codes
50
 * are not currently defined for this domain.  See #GError for
51
 * information on error domains.
52
 **/
53
/**
54
 * GVariantParseError:
55
 * @G_VARIANT_PARSE_ERROR_FAILED: generic error (unused)
56
 * @G_VARIANT_PARSE_ERROR_BASIC_TYPE_EXPECTED: a non-basic #GVariantType was given where a basic type was expected
57
 * @G_VARIANT_PARSE_ERROR_CANNOT_INFER_TYPE: cannot infer the #GVariantType
58
 * @G_VARIANT_PARSE_ERROR_DEFINITE_TYPE_EXPECTED: an indefinite #GVariantType was given where a definite type was expected
59
 * @G_VARIANT_PARSE_ERROR_INPUT_NOT_AT_END: extra data after parsing finished
60
 * @G_VARIANT_PARSE_ERROR_INVALID_CHARACTER: invalid character in number or unicode escape
61
 * @G_VARIANT_PARSE_ERROR_INVALID_FORMAT_STRING: not a valid #GVariant format string
62
 * @G_VARIANT_PARSE_ERROR_INVALID_OBJECT_PATH: not a valid object path
63
 * @G_VARIANT_PARSE_ERROR_INVALID_SIGNATURE: not a valid type signature
64
 * @G_VARIANT_PARSE_ERROR_INVALID_TYPE_STRING: not a valid #GVariant type string
65
 * @G_VARIANT_PARSE_ERROR_NO_COMMON_TYPE: could not find a common type for array entries
66
 * @G_VARIANT_PARSE_ERROR_NUMBER_OUT_OF_RANGE: the numerical value is out of range of the given type
67
 * @G_VARIANT_PARSE_ERROR_NUMBER_TOO_BIG: the numerical value is out of range for any type
68
 * @G_VARIANT_PARSE_ERROR_TYPE_ERROR: cannot parse as variant of the specified type
69
 * @G_VARIANT_PARSE_ERROR_UNEXPECTED_TOKEN: an unexpected token was encountered
70
 * @G_VARIANT_PARSE_ERROR_UNKNOWN_KEYWORD: an unknown keyword was encountered
71
 * @G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT: unterminated string constant
72
 * @G_VARIANT_PARSE_ERROR_VALUE_EXPECTED: no value given
73
 * @G_VARIANT_PARSE_ERROR_RECURSION: variant was too deeply nested; #GVariant is only guaranteed to handle nesting up to 64 levels (Since: 2.64)
74
 *
75
 * Error codes returned by parsing text-format GVariants.
76
 **/
77
G_DEFINE_QUARK (g-variant-parse-error-quark, g_variant_parse_error)
78
79
/**
80
 * g_variant_parser_get_error_quark:
81
 *
82
 * Same as g_variant_error_quark().
83
 *
84
 * Deprecated: Use g_variant_parse_error_quark() instead.
85
 */
86
GQuark
87
g_variant_parser_get_error_quark (void)
88
0
{
89
0
  return g_variant_parse_error_quark ();
90
0
}
91
92
typedef struct
93
{
94
  /* Offsets from the start of the input, in bytes. Can be equal when referring
95
   * to a point rather than a range. The invariant `end >= start` always holds. */
96
  size_t start, end;
97
} SourceRef;
98
99
G_GNUC_PRINTF(5, 0)
100
static void
101
parser_set_error_va (GError      **error,
102
                     SourceRef    *location,
103
                     SourceRef    *other,
104
                     gint          code,
105
                     const gchar  *format,
106
                     va_list       ap)
107
0
{
108
0
  GString *msg = g_string_new (NULL);
109
110
0
  if (location->start == location->end)
111
0
    g_string_append_printf (msg, "%" G_GSIZE_FORMAT, location->start);
112
0
  else
113
0
    g_string_append_printf (msg, "%" G_GSIZE_FORMAT "-%" G_GSIZE_FORMAT,
114
0
                            location->start, location->end);
115
116
0
  if (other != NULL)
117
0
    {
118
0
      g_assert (other->start != other->end);
119
0
      g_string_append_printf (msg, ",%" G_GSIZE_FORMAT "-%" G_GSIZE_FORMAT,
120
0
                              other->start, other->end);
121
0
    }
122
0
  g_string_append_c (msg, ':');
123
124
0
  g_string_append_vprintf (msg, format, ap);
125
0
  g_set_error_literal (error, G_VARIANT_PARSE_ERROR, code, msg->str);
126
0
  g_string_free (msg, TRUE);
127
0
}
128
129
G_GNUC_PRINTF(5, 6)
130
static void
131
parser_set_error (GError      **error,
132
                  SourceRef    *location,
133
                  SourceRef    *other,
134
                  gint          code,
135
                  const gchar  *format,
136
                  ...)
137
0
{
138
0
  va_list ap;
139
140
0
  va_start (ap, format);
141
0
  parser_set_error_va (error, location, other, code, format, ap);
142
0
  va_end (ap);
143
0
}
144
145
typedef struct
146
{
147
  /* We should always have the following ordering constraint:
148
   *   start <= this <= stream <= end
149
   * Additionally, unless in an error or EOF state, `this < stream`.
150
   */
151
  const gchar *start;
152
  const gchar *stream;
153
  const gchar *end;
154
155
  const gchar *this;  /* (nullable) */
156
} TokenStream;
157
158
159
G_GNUC_PRINTF(5, 6)
160
static void
161
token_stream_set_error (TokenStream  *stream,
162
                        GError      **error,
163
                        gboolean      this_token,
164
                        gint          code,
165
                        const gchar  *format,
166
                        ...)
167
0
{
168
0
  SourceRef ref;
169
0
  va_list ap;
170
171
0
  ref.start = stream->this - stream->start;
172
173
0
  if (this_token)
174
0
    ref.end = stream->stream - stream->start;
175
0
  else
176
0
    ref.end = ref.start;
177
178
0
  va_start (ap, format);
179
0
  parser_set_error_va (error, &ref, NULL, code, format, ap);
180
0
  va_end (ap);
181
0
}
182
183
static gboolean
184
token_stream_prepare (TokenStream *stream)
185
0
{
186
0
  gssize brackets = 0;
187
0
  const gchar *end;
188
189
0
  if (stream->this != NULL)
190
0
    return TRUE;
191
192
0
  while (stream->stream != stream->end && g_ascii_isspace (*stream->stream))
193
0
    stream->stream++;
194
195
0
  if (stream->stream == stream->end || *stream->stream == '\0')
196
0
    {
197
0
      stream->this = stream->stream;
198
0
      return FALSE;
199
0
    }
200
201
0
  switch (stream->stream[0])
202
0
    {
203
0
    case '-': case '+': case '.': case '0': case '1': case '2':
204
0
    case '3': case '4': case '5': case '6': case '7': case '8':
205
0
    case '9':
206
0
      for (end = stream->stream; end != stream->end; end++)
207
0
        if (!g_ascii_isalnum (*end) &&
208
0
            *end != '-' && *end != '+' && *end != '.')
209
0
          break;
210
0
      break;
211
212
0
    case 'b':
213
0
      if (stream->stream + 1 != stream->end &&
214
0
          (stream->stream[1] == '\'' || stream->stream[1] == '"'))
215
0
        {
216
0
          for (end = stream->stream + 2; end != stream->end; end++)
217
0
            if (*end == stream->stream[1] || *end == '\0' ||
218
0
                (*end == '\\' && (++end == stream->end || *end == '\0')))
219
0
              break;
220
221
0
          if (end != stream->end && *end)
222
0
            end++;
223
0
          break;
224
0
        }
225
226
0
      G_GNUC_FALLTHROUGH;
227
228
0
    case 'a': /* 'b' */ case 'c': case 'd': case 'e': case 'f':
229
0
    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
230
0
    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
231
0
    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
232
0
    case 'y': case 'z':
233
0
      for (end = stream->stream; end != stream->end; end++)
234
0
        if (!g_ascii_isalnum (*end))
235
0
          break;
236
0
      break;
237
238
0
    case '\'': case '"':
239
0
      for (end = stream->stream + 1; end != stream->end; end++)
240
0
        if (*end == stream->stream[0] || *end == '\0' ||
241
0
            (*end == '\\' && (++end == stream->end || *end == '\0')))
242
0
          break;
243
244
0
      if (end != stream->end && *end)
245
0
        end++;
246
0
      break;
247
248
0
    case '@': case '%':
249
      /* stop at the first space, comma, colon or unmatched bracket.
250
       * deals nicely with cases like (%i, %i) or {%i: %i}.
251
       * Also: ] and > are never in format strings.
252
       */
253
0
      for (end = stream->stream + 1;
254
0
           end != stream->end && *end != '\0' && *end != ',' &&
255
0
           *end != ':' && *end != '>' && *end != ']' && !g_ascii_isspace (*end);
256
0
           end++)
257
258
0
        if (*end == '(' || *end == '{')
259
0
          brackets++;
260
261
0
        else if ((*end == ')' || *end == '}') && !brackets--)
262
0
          break;
263
264
0
      break;
265
266
0
    default:
267
0
      end = stream->stream + 1;
268
0
      break;
269
0
    }
270
271
0
  stream->this = stream->stream;
272
0
  stream->stream = end;
273
274
  /* We must have at least one byte in a token. */
275
0
  g_assert (stream->stream - stream->this >= 1);
276
277
0
  return TRUE;
278
0
}
279
280
static void
281
token_stream_next (TokenStream *stream)
282
0
{
283
0
  stream->this = NULL;
284
0
}
285
286
static gboolean
287
token_stream_peek (TokenStream *stream,
288
                   gchar        first_char)
289
0
{
290
0
  if (!token_stream_prepare (stream))
291
0
    return FALSE;
292
293
0
  return stream->stream - stream->this >= 1 &&
294
0
         stream->this[0] == first_char;
295
0
}
296
297
static gboolean
298
token_stream_peek2 (TokenStream *stream,
299
                    gchar        first_char,
300
                    gchar        second_char)
301
0
{
302
0
  if (!token_stream_prepare (stream))
303
0
    return FALSE;
304
305
0
  return stream->stream - stream->this >= 2 &&
306
0
         stream->this[0] == first_char &&
307
0
         stream->this[1] == second_char;
308
0
}
309
310
static gboolean
311
token_stream_is_keyword (TokenStream *stream)
312
0
{
313
0
  if (!token_stream_prepare (stream))
314
0
    return FALSE;
315
316
0
  return stream->stream - stream->this >= 2 &&
317
0
         g_ascii_isalpha (stream->this[0]) &&
318
0
         g_ascii_isalpha (stream->this[1]);
319
0
}
320
321
static gboolean
322
token_stream_is_numeric (TokenStream *stream)
323
0
{
324
0
  if (!token_stream_prepare (stream))
325
0
    return FALSE;
326
327
0
  return (stream->stream - stream->this >= 1 &&
328
0
          (g_ascii_isdigit (stream->this[0]) ||
329
0
           stream->this[0] == '-' ||
330
0
           stream->this[0] == '+' ||
331
0
           stream->this[0] == '.'));
332
0
}
333
334
static gboolean
335
token_stream_peek_string (TokenStream *stream,
336
                          const gchar *token)
337
0
{
338
0
  size_t length = strlen (token);
339
340
0
  return token_stream_prepare (stream) &&
341
0
         (size_t) (stream->stream - stream->this) == length &&
342
0
         memcmp (stream->this, token, length) == 0;
343
0
}
344
345
static gboolean
346
token_stream_consume (TokenStream *stream,
347
                      const gchar *token)
348
0
{
349
0
  if (!token_stream_peek_string (stream, token))
350
0
    return FALSE;
351
352
0
  token_stream_next (stream);
353
0
  return TRUE;
354
0
}
355
356
static gboolean
357
token_stream_require (TokenStream  *stream,
358
                      const gchar  *token,
359
                      const gchar  *purpose,
360
                      GError      **error)
361
0
{
362
363
0
  if (!token_stream_consume (stream, token))
364
0
    {
365
0
      token_stream_set_error (stream, error, FALSE,
366
0
                              G_VARIANT_PARSE_ERROR_UNEXPECTED_TOKEN,
367
0
                              "expected '%s'%s", token, purpose);
368
0
      return FALSE;
369
0
    }
370
371
0
  return TRUE;
372
0
}
373
374
static void
375
token_stream_assert (TokenStream *stream,
376
                     const gchar *token)
377
0
{
378
0
  gboolean correct_token G_GNUC_UNUSED  /* when compiling with G_DISABLE_ASSERT */;
379
380
0
  correct_token = token_stream_consume (stream, token);
381
0
  g_assert (correct_token);
382
0
}
383
384
static gchar *
385
token_stream_get (TokenStream *stream)
386
0
{
387
0
  gchar *result;
388
389
0
  if (!token_stream_prepare (stream))
390
0
    return NULL;
391
392
0
  result = g_strndup (stream->this, stream->stream - stream->this);
393
394
0
  return result;
395
0
}
396
397
static void
398
token_stream_start_ref (TokenStream *stream,
399
                        SourceRef   *ref)
400
0
{
401
0
  token_stream_prepare (stream);
402
0
  ref->start = stream->this - stream->start;
403
0
}
404
405
static void
406
token_stream_end_ref (TokenStream *stream,
407
                      SourceRef   *ref)
408
0
{
409
0
  ref->end = stream->stream - stream->start;
410
0
}
411
412
/* This is guaranteed to write exactly as many bytes to `out` as it consumes
413
 * from `in`. i.e. The `out` buffer doesn’t need to be any longer than `in`. */
414
static void
415
pattern_copy (gchar       **out,
416
              const gchar **in)
417
0
{
418
0
  gssize brackets = 0;
419
420
0
  while (**in == 'a' || **in == 'm' || **in == 'M')
421
0
    *(*out)++ = *(*in)++;
422
423
0
  do
424
0
    {
425
0
      if (**in == '(' || **in == '{')
426
0
        brackets++;
427
428
0
      else if (**in == ')' || **in == '}')
429
0
        brackets--;
430
431
0
      *(*out)++ = *(*in)++;
432
0
    }
433
0
  while (brackets);
434
0
}
435
436
/* Returns the most general pattern that is subpattern of left and subpattern
437
 * of right, or NULL if there is no such pattern. */
438
static gchar *
439
pattern_coalesce (const gchar *left,
440
                  const gchar *right)
441
0
{
442
0
  gchar *result;
443
0
  gchar *out;
444
0
  size_t buflen;
445
0
  size_t left_len = strlen (left), right_len = strlen (right);
446
447
  /* the length of the output is loosely bound by the sum of the input
448
   * lengths, not simply the greater of the two lengths.
449
   *
450
   *   (*(iii)) + ((iii)*) = ((iii)(iii))
451
   *
452
   *      8     +    8     = 12
453
   *
454
   * This can be proven by the fact that `out` is never incremented by more
455
   * bytes than are consumed from `left` or `right` in each iteration.
456
   */
457
0
  g_assert (left_len < G_MAXSIZE - right_len);
458
0
  buflen = left_len + right_len + 1;
459
0
  out = result = g_malloc (buflen);
460
461
0
  while (*left && *right)
462
0
    {
463
0
      if (*left == *right)
464
0
        {
465
0
          *out++ = *left++;
466
0
          right++;
467
0
        }
468
469
0
      else
470
0
        {
471
0
          const gchar **one = &left, **the_other = &right;
472
473
0
         again:
474
0
          if (**one == '*' && **the_other != ')')
475
0
            {
476
0
              pattern_copy (&out, the_other);
477
0
              (*one)++;
478
0
            }
479
480
0
          else if (**one == 'M' && **the_other == 'm')
481
0
            {
482
0
              *out++ = *(*the_other)++;
483
0
            }
484
485
0
          else if (**one == 'M' && **the_other != 'm' && **the_other != '*')
486
0
            {
487
0
              (*one)++;
488
0
            }
489
490
0
          else if (**one == 'N' && strchr ("ynqiuxthd", **the_other))
491
0
            {
492
0
              *out++ = *(*the_other)++;
493
0
              (*one)++;
494
0
            }
495
496
0
          else if (**one == 'S' && strchr ("sog", **the_other))
497
0
            {
498
0
              *out++ = *(*the_other)++;
499
0
              (*one)++;
500
0
            }
501
502
0
          else if (one == &left)
503
0
            {
504
0
              one = &right, the_other = &left;
505
0
              goto again;
506
0
            }
507
508
0
          else
509
0
            break;
510
0
        }
511
0
    }
512
513
  /* Need at least one byte remaining for trailing nul. */
514
0
  g_assert (out < result + buflen);
515
516
0
  if (*left || *right)
517
0
    {
518
0
      g_free (result);
519
0
      result = NULL;
520
0
    }
521
0
  else
522
0
    *out++ = '\0';
523
524
0
  return result;
525
0
}
526
527
typedef struct _AST AST;
528
typedef gchar *    (*get_pattern_func)    (AST                 *ast,
529
                                           GError             **error);
530
typedef GVariant * (*get_value_func)      (AST                 *ast,
531
                                           const GVariantType  *type,
532
                                           GError             **error);
533
typedef GVariant * (*get_base_value_func) (AST                 *ast,
534
                                           const GVariantType  *type,
535
                                           GError             **error);
536
typedef void       (*free_func)           (AST                 *ast);
537
538
typedef struct
539
{
540
  gchar *    (* get_pattern)    (AST                 *ast,
541
                                 GError             **error);
542
  GVariant * (* get_value)      (AST                 *ast,
543
                                 const GVariantType  *type,
544
                                 GError             **error);
545
  GVariant * (* get_base_value) (AST                 *ast,
546
                                 const GVariantType  *type,
547
                                 GError             **error);
548
  void       (* free)           (AST                 *ast);
549
} ASTClass;
550
551
struct _AST
552
{
553
  const ASTClass *class;
554
  SourceRef source_ref;
555
};
556
557
static gchar *
558
ast_get_pattern (AST     *ast,
559
                 GError **error)
560
0
{
561
0
  return ast->class->get_pattern (ast, error);
562
0
}
563
564
static GVariant *
565
ast_get_value (AST                 *ast,
566
               const GVariantType  *type,
567
               GError             **error)
568
0
{
569
0
  return ast->class->get_value (ast, type, error);
570
0
}
571
572
static void
573
ast_free (AST *ast)
574
0
{
575
0
  ast->class->free (ast);
576
0
}
577
578
G_GNUC_PRINTF(5, 6)
579
static void
580
ast_set_error (AST          *ast,
581
               GError      **error,
582
               AST          *other_ast,
583
               gint          code,
584
               const gchar  *format,
585
               ...)
586
0
{
587
0
  va_list ap;
588
589
0
  va_start (ap, format);
590
0
  parser_set_error_va (error, &ast->source_ref,
591
0
                       other_ast ? & other_ast->source_ref : NULL,
592
0
                       code,
593
0
                       format, ap);
594
0
  va_end (ap);
595
0
}
596
597
static GVariant *
598
ast_type_error (AST                 *ast,
599
                const GVariantType  *type,
600
                GError             **error)
601
0
{
602
0
  gchar *typestr;
603
604
0
  typestr = g_variant_type_dup_string (type);
605
0
  ast_set_error (ast, error, NULL,
606
0
                 G_VARIANT_PARSE_ERROR_TYPE_ERROR,
607
0
                 "can not parse as value of type '%s'",
608
0
                 typestr);
609
0
  g_free (typestr);
610
611
0
  return NULL;
612
0
}
613
614
static GVariant *
615
ast_resolve (AST     *ast,
616
             GError **error)
617
0
{
618
0
  GVariant *value;
619
0
  gchar *pattern;
620
0
  size_t i, j = 0;
621
622
0
  pattern = ast_get_pattern (ast, error);
623
624
0
  if (pattern == NULL)
625
0
    return NULL;
626
627
  /* choose reasonable defaults
628
   *
629
   *   1) favour non-maybe values where possible
630
   *   2) default type for strings is 's'
631
   *   3) default type for integers is 'i'
632
   */
633
0
  for (i = 0; pattern[i]; i++)
634
0
    switch (pattern[i])
635
0
      {
636
0
      case '*':
637
0
        ast_set_error (ast, error, NULL,
638
0
                       G_VARIANT_PARSE_ERROR_CANNOT_INFER_TYPE,
639
0
                       "unable to infer type");
640
0
        g_free (pattern);
641
0
        return NULL;
642
643
0
      case 'M':
644
0
        break;
645
646
0
      case 'S':
647
0
        pattern[j++] = 's';
648
0
        break;
649
650
0
      case 'N':
651
0
        pattern[j++] = 'i';
652
0
        break;
653
654
0
      default:
655
0
        pattern[j++] = pattern[i];
656
0
        break;
657
0
      }
658
0
  pattern[j++] = '\0';
659
660
0
  value = ast_get_value (ast, G_VARIANT_TYPE (pattern), error);
661
0
  g_free (pattern);
662
663
0
  return value;
664
0
}
665
666
667
static AST *parse (TokenStream  *stream,
668
                   guint         max_depth,
669
                   va_list      *app,
670
                   GError      **error);
671
672
static void
673
ast_array_append (AST    ***array,
674
                  size_t   *n_items,
675
                  AST      *ast)
676
0
{
677
0
  if ((*n_items & (*n_items - 1)) == 0)
678
0
    *array = g_renew (AST *, *array, *n_items ? 2 ** n_items : 1);
679
680
0
  (*array)[(*n_items)++] = ast;
681
0
}
682
683
static void
684
ast_array_free (AST    **array,
685
                size_t   n_items)
686
0
{
687
0
  size_t i;
688
689
0
  for (i = 0; i < n_items; i++)
690
0
    ast_free (array[i]);
691
0
  g_free (array);
692
0
}
693
694
static gchar *
695
ast_array_get_pattern (AST    **array,
696
                       size_t   n_items,
697
                       GError **error)
698
0
{
699
0
  gchar *pattern;
700
0
  size_t i;
701
702
  /* Find the pattern which applies to all children in the array, by l-folding a
703
   * coalesce operation.
704
   */
705
0
  pattern = ast_get_pattern (array[0], error);
706
707
0
  if (pattern == NULL)
708
0
    return NULL;
709
710
0
  for (i = 1; i < n_items; i++)
711
0
    {
712
0
      gchar *tmp, *merged;
713
714
0
      tmp = ast_get_pattern (array[i], error);
715
716
0
      if (tmp == NULL)
717
0
        {
718
0
          g_free (pattern);
719
0
          return NULL;
720
0
        }
721
722
0
      merged = pattern_coalesce (pattern, tmp);
723
0
      g_free (pattern);
724
0
      pattern = merged;
725
726
0
      if (merged == NULL)
727
        /* set coalescence implies pairwise coalescence (i think).
728
         * we should therefore be able to trace the failure to a single
729
         * pair of values.
730
         */
731
0
        {
732
0
          size_t j = 0;
733
734
0
          while (TRUE)
735
0
            {
736
0
              gchar *tmp2;
737
0
              gchar *m;
738
739
              /* if 'j' reaches 'i' then we didn't find the pair that failed
740
               * to coalesce. This shouldn't happen (see above), but just in
741
               * case report an error:
742
               */
743
0
              if (j >= i)
744
0
                {
745
0
                  ast_set_error (array[i], error, NULL,
746
0
                                 G_VARIANT_PARSE_ERROR_NO_COMMON_TYPE,
747
0
                                 "unable to find a common type");
748
0
                  g_free (tmp);
749
0
                  return NULL;
750
0
                }
751
752
0
              tmp2 = ast_get_pattern (array[j], NULL);
753
0
              g_assert (tmp2 != NULL);
754
755
0
              m = pattern_coalesce (tmp, tmp2);
756
0
              g_free (tmp2);
757
0
              g_free (m);
758
759
0
              if (m == NULL)
760
0
                {
761
                  /* we found a conflict between 'i' and 'j'.
762
                   *
763
                   * report the error.  note: 'j' is first.
764
                   */
765
0
                  ast_set_error (array[j], error, array[i],
766
0
                                 G_VARIANT_PARSE_ERROR_NO_COMMON_TYPE,
767
0
                                 "unable to find a common type");
768
0
                  g_free (tmp);
769
0
                  return NULL;
770
0
                }
771
772
0
              j++;
773
0
            }
774
775
0
        }
776
777
0
      g_free (tmp);
778
0
    }
779
780
0
  return pattern;
781
0
}
782
783
typedef struct
784
{
785
  AST ast;
786
787
  AST *child;
788
} Maybe;
789
790
static gchar *
791
maybe_get_pattern (AST     *ast,
792
                   GError **error)
793
0
{
794
0
  Maybe *maybe = (Maybe *) ast;
795
796
0
  if (maybe->child != NULL)
797
0
    {
798
0
      gchar *child_pattern;
799
0
      gchar *pattern;
800
801
0
      child_pattern = ast_get_pattern (maybe->child, error);
802
803
0
      if (child_pattern == NULL)
804
0
        return NULL;
805
806
0
      pattern = g_strdup_printf ("m%s", child_pattern);
807
0
      g_free (child_pattern);
808
809
0
      return pattern;
810
0
    }
811
812
0
  return g_strdup ("m*");
813
0
}
814
815
static GVariant *
816
maybe_get_value (AST                 *ast,
817
                 const GVariantType  *type,
818
                 GError             **error)
819
0
{
820
0
  Maybe *maybe = (Maybe *) ast;
821
0
  GVariant *value;
822
823
0
  if (!g_variant_type_is_maybe (type))
824
0
    return ast_type_error (ast, type, error);
825
826
0
  type = g_variant_type_element (type);
827
828
0
  if (maybe->child)
829
0
    {
830
0
      value = ast_get_value (maybe->child, type, error);
831
832
0
      if (value == NULL)
833
0
        return NULL;
834
0
    }
835
0
  else
836
0
    value = NULL;
837
838
0
  return g_variant_new_maybe (type, value);
839
0
}
840
841
static void
842
maybe_free (AST *ast)
843
0
{
844
0
  Maybe *maybe = (Maybe *) ast;
845
846
0
  if (maybe->child != NULL)
847
0
    ast_free (maybe->child);
848
849
0
  g_slice_free (Maybe, maybe);
850
0
}
851
852
static AST *
853
maybe_parse (TokenStream  *stream,
854
             guint         max_depth,
855
             va_list      *app,
856
             GError      **error)
857
0
{
858
0
  static const ASTClass maybe_class = {
859
0
    maybe_get_pattern,
860
0
    maybe_get_value, NULL,
861
0
    maybe_free
862
0
  };
863
0
  AST *child = NULL;
864
0
  Maybe *maybe;
865
866
0
  if (token_stream_consume (stream, "just"))
867
0
    {
868
0
      child = parse (stream, max_depth - 1, app, error);
869
0
      if (child == NULL)
870
0
        return NULL;
871
0
    }
872
873
0
  else if (!token_stream_consume (stream, "nothing"))
874
0
    {
875
0
      token_stream_set_error (stream, error, TRUE,
876
0
                              G_VARIANT_PARSE_ERROR_UNKNOWN_KEYWORD,
877
0
                              "unknown keyword");
878
0
      return NULL;
879
0
    }
880
881
0
  maybe = g_slice_new (Maybe);
882
0
  maybe->ast.class = &maybe_class;
883
0
  maybe->child = child;
884
885
0
  return (AST *) maybe;
886
0
}
887
888
static GVariant *
889
maybe_wrapper (AST                 *ast,
890
               const GVariantType  *type,
891
               GError             **error)
892
0
{
893
0
  const GVariantType *base_type;
894
0
  GVariant *base_value;
895
0
  GVariant *value = NULL;
896
0
  unsigned int depth;
897
0
  gboolean trusted;
898
0
  GVariantTypeInfo *base_type_info = NULL;
899
0
  gsize base_serialised_fixed_size, base_serialised_size, serialised_size, n_suffix_zeros;
900
0
  guint8 *serialised = NULL;
901
0
  GBytes *bytes = NULL;
902
0
  gsize i;
903
904
0
  for (depth = 0, base_type = type;
905
0
       g_variant_type_is_maybe (base_type);
906
0
       depth++, base_type = g_variant_type_element (base_type));
907
908
0
  base_value = ast->class->get_base_value (ast, base_type, error);
909
910
0
  if (base_value == NULL || depth == 0)
911
0
    return g_steal_pointer (&base_value);
912
913
  /* This is the equivalent of calling g_variant_new_maybe() in a loop enough
914
   * times to match the number of nested maybe types in @type. It does the same
915
   * in a single `GVariant` allocation, though.
916
   *
917
   * This avoids maybe_wrapper() becoming an attack vector where a malicious
918
   * text-form variant can create a long array, and insert a typedecl for a
919
   * deeply nested maybe type on one of its elements. This is achievable with a
920
   * relatively short text form, but results in O(array length × typedecl depth)
921
   * allocations. This is a denial of service attack.
922
   *
923
   * Instead of constructing a tree of `GVariant`s in tree-form to match the
924
   * @ast, construct a single `GVariant` containing the serialised form of the
925
   * maybe-wrappers and the base value that they contain. This is relatively
926
   * straightforward: serialise the base value, and then append the correct
927
   * number of zero bytes for the maybe-wrappers.
928
   *
929
   * This is a bit of a layering violation, unfortunately.
930
   *
931
   * By doing this, the typedecl depth variable is reduced to O(1).
932
   */
933
0
  trusted = g_variant_is_trusted (base_value);
934
935
  /* See https://developer.gnome.org/documentation/specifications/gvariant-specification-1.0.html#maybes
936
   *
937
   * The serialised form of a `Just x` is the serialised form of `x` if `x` is
938
   * fixed-size, and the serialised form of `x` plus a trailing zero byte if `x`
939
   * is variable-size. A `Maybe` variant is always variable-size, even if its
940
   * child element is fixed-size, because it might be `Nothing`. This means that
941
   * all the maybe-wrappers which are not the innermost are always serialised
942
   * with one trailing zero byte each.
943
   *
944
   * The serialised form of a `Nothing` is an empty byte sequence, but that’s
945
   * already handled above in the `base_value == NULL` case.
946
   */
947
0
  base_type_info = g_variant_type_info_get (base_type);
948
0
  g_variant_type_info_query (base_type_info, NULL, &base_serialised_fixed_size);
949
0
  g_variant_type_info_unref (base_type_info);
950
951
0
  base_serialised_size = g_variant_get_size (base_value);
952
0
  n_suffix_zeros = (base_serialised_fixed_size > 0) ? depth - 1 : depth;
953
0
  g_assert (base_serialised_size <= G_MAXSIZE - n_suffix_zeros);
954
0
  serialised_size = base_serialised_size + n_suffix_zeros;
955
956
0
  g_assert (serialised_size >= base_serialised_size);
957
958
  /* Serialise the base value. */
959
0
  serialised = g_malloc (serialised_size);
960
0
  g_variant_store (base_value, serialised);
961
962
  /* Zero-out the suffix zeros to complete the serialisation of the maybe wrappers. */
963
0
  for (i = base_serialised_size; i < serialised_size; i++)
964
0
    serialised[i] = 0;
965
966
0
  bytes = g_bytes_new_take (g_steal_pointer (&serialised), serialised_size);
967
0
  value = g_variant_new_from_bytes (type, bytes, trusted);
968
0
  g_bytes_unref (bytes);
969
970
0
  g_variant_unref (base_value);
971
972
0
  return g_steal_pointer (&value);
973
0
}
974
975
typedef struct
976
{
977
  AST ast;
978
979
  AST **children;
980
  size_t n_children;
981
} Array;
982
983
static gchar *
984
array_get_pattern (AST     *ast,
985
                   GError **error)
986
0
{
987
0
  Array *array = (Array *) ast;
988
0
  gchar *pattern;
989
0
  gchar *result;
990
991
0
  if (array->n_children == 0)
992
0
    return g_strdup ("Ma*");
993
994
0
  pattern = ast_array_get_pattern (array->children, array->n_children, error);
995
996
0
  if (pattern == NULL)
997
0
    return NULL;
998
999
0
  result = g_strdup_printf ("Ma%s", pattern);
1000
0
  g_free (pattern);
1001
1002
0
  return result;
1003
0
}
1004
1005
static GVariant *
1006
array_get_value (AST                 *ast,
1007
                 const GVariantType  *type,
1008
                 GError             **error)
1009
0
{
1010
0
  Array *array = (Array *) ast;
1011
0
  const GVariantType *childtype;
1012
0
  GVariantBuilder builder;
1013
0
  size_t i;
1014
1015
0
  if (!g_variant_type_is_array (type))
1016
0
    return ast_type_error (ast, type, error);
1017
1018
0
  g_variant_builder_init_static (&builder, type);
1019
0
  childtype = g_variant_type_element (type);
1020
1021
0
  for (i = 0; i < array->n_children; i++)
1022
0
    {
1023
0
      GVariant *child;
1024
1025
0
      if (!(child = ast_get_value (array->children[i], childtype, error)))
1026
0
        {
1027
0
          g_variant_builder_clear (&builder);
1028
0
          return NULL;
1029
0
        }
1030
1031
0
      g_variant_builder_add_value (&builder, child);
1032
0
    }
1033
1034
0
  return g_variant_builder_end (&builder);
1035
0
}
1036
1037
static void
1038
array_free (AST *ast)
1039
0
{
1040
0
  Array *array = (Array *) ast;
1041
1042
0
  ast_array_free (array->children, array->n_children);
1043
0
  g_slice_free (Array, array);
1044
0
}
1045
1046
static AST *
1047
array_parse (TokenStream  *stream,
1048
             guint         max_depth,
1049
             va_list      *app,
1050
             GError      **error)
1051
0
{
1052
0
  static const ASTClass array_class = {
1053
0
    array_get_pattern,
1054
0
    maybe_wrapper, array_get_value,
1055
0
    array_free
1056
0
  };
1057
0
  gboolean need_comma = FALSE;
1058
0
  Array *array;
1059
1060
0
  array = g_slice_new (Array);
1061
0
  array->ast.class = &array_class;
1062
0
  array->children = NULL;
1063
0
  array->n_children = 0;
1064
1065
0
  token_stream_assert (stream, "[");
1066
0
  while (!token_stream_consume (stream, "]"))
1067
0
    {
1068
0
      AST *child;
1069
1070
0
      if (need_comma &&
1071
0
          !token_stream_require (stream, ",",
1072
0
                                 " or ']' to follow array element",
1073
0
                                 error))
1074
0
        goto error;
1075
1076
0
      child = parse (stream, max_depth - 1, app, error);
1077
1078
0
      if (!child)
1079
0
        goto error;
1080
1081
0
      ast_array_append (&array->children, &array->n_children, child);
1082
0
      need_comma = TRUE;
1083
0
    }
1084
1085
0
  return (AST *) array;
1086
1087
0
 error:
1088
0
  ast_array_free (array->children, array->n_children);
1089
0
  g_slice_free (Array, array);
1090
1091
0
  return NULL;
1092
0
}
1093
1094
typedef struct
1095
{
1096
  AST ast;
1097
1098
  AST **children;
1099
  size_t n_children;
1100
} Tuple;
1101
1102
static gchar *
1103
tuple_get_pattern (AST     *ast,
1104
                   GError **error)
1105
0
{
1106
0
  Tuple *tuple = (Tuple *) ast;
1107
0
  gchar *result = NULL;
1108
0
  gchar **parts;
1109
0
  size_t i;
1110
1111
0
  parts = g_new (gchar *, tuple->n_children + 4);
1112
0
  parts[tuple->n_children + 1] = (gchar *) ")";
1113
0
  parts[tuple->n_children + 2] = NULL;
1114
0
  parts[0] = (gchar *) "M(";
1115
1116
0
  for (i = 0; i < tuple->n_children; i++)
1117
0
    if (!(parts[i + 1] = ast_get_pattern (tuple->children[i], error)))
1118
0
      break;
1119
1120
0
  if (i == tuple->n_children)
1121
0
    result = g_strjoinv ("", parts);
1122
1123
  /* parts[0] should not be freed */
1124
0
  while (i)
1125
0
    g_free (parts[i--]);
1126
0
  g_free (parts);
1127
1128
0
  return result;
1129
0
}
1130
1131
static GVariant *
1132
tuple_get_value (AST                 *ast,
1133
                 const GVariantType  *type,
1134
                 GError             **error)
1135
0
{
1136
0
  Tuple *tuple = (Tuple *) ast;
1137
0
  const GVariantType *childtype;
1138
0
  GVariantBuilder builder;
1139
0
  size_t i;
1140
1141
0
  if (!g_variant_type_is_tuple (type))
1142
0
    return ast_type_error (ast, type, error);
1143
1144
0
  g_variant_builder_init_static (&builder, type);
1145
0
  childtype = g_variant_type_first (type);
1146
1147
0
  for (i = 0; i < tuple->n_children; i++)
1148
0
    {
1149
0
      GVariant *child;
1150
1151
0
      if (childtype == NULL)
1152
0
        {
1153
0
          g_variant_builder_clear (&builder);
1154
0
          return ast_type_error (ast, type, error);
1155
0
        }
1156
1157
0
      if (!(child = ast_get_value (tuple->children[i], childtype, error)))
1158
0
        {
1159
0
          g_variant_builder_clear (&builder);
1160
0
          return FALSE;
1161
0
        }
1162
1163
0
      g_variant_builder_add_value (&builder, child);
1164
0
      childtype = g_variant_type_next (childtype);
1165
0
    }
1166
1167
0
  if (childtype != NULL)
1168
0
    {
1169
0
      g_variant_builder_clear (&builder);
1170
0
      return ast_type_error (ast, type, error);
1171
0
    }
1172
1173
0
  return g_variant_builder_end (&builder);
1174
0
}
1175
1176
static void
1177
tuple_free (AST *ast)
1178
0
{
1179
0
  Tuple *tuple = (Tuple *) ast;
1180
1181
0
  ast_array_free (tuple->children, tuple->n_children);
1182
0
  g_slice_free (Tuple, tuple);
1183
0
}
1184
1185
static AST *
1186
tuple_parse (TokenStream  *stream,
1187
             guint         max_depth,
1188
             va_list      *app,
1189
             GError      **error)
1190
0
{
1191
0
  static const ASTClass tuple_class = {
1192
0
    tuple_get_pattern,
1193
0
    maybe_wrapper, tuple_get_value,
1194
0
    tuple_free
1195
0
  };
1196
0
  gboolean need_comma = FALSE;
1197
0
  gboolean first = TRUE;
1198
0
  Tuple *tuple;
1199
1200
0
  tuple = g_slice_new (Tuple);
1201
0
  tuple->ast.class = &tuple_class;
1202
0
  tuple->children = NULL;
1203
0
  tuple->n_children = 0;
1204
1205
0
  token_stream_assert (stream, "(");
1206
0
  while (!token_stream_consume (stream, ")"))
1207
0
    {
1208
0
      AST *child;
1209
1210
0
      if (need_comma &&
1211
0
          !token_stream_require (stream, ",",
1212
0
                                 " or ')' to follow tuple element",
1213
0
                                 error))
1214
0
        goto error;
1215
1216
0
      child = parse (stream, max_depth - 1, app, error);
1217
1218
0
      if (!child)
1219
0
        goto error;
1220
1221
0
      ast_array_append (&tuple->children, &tuple->n_children, child);
1222
1223
      /* the first time, we absolutely require a comma, so grab it here
1224
       * and leave need_comma = FALSE so that the code above doesn't
1225
       * require a second comma.
1226
       *
1227
       * the second and remaining times, we set need_comma = TRUE.
1228
       */
1229
0
      if (first)
1230
0
        {
1231
0
          if (!token_stream_require (stream, ",",
1232
0
                                     " after first tuple element", error))
1233
0
            goto error;
1234
1235
0
          first = FALSE;
1236
0
        }
1237
0
      else
1238
0
        need_comma = TRUE;
1239
0
    }
1240
1241
0
  return (AST *) tuple;
1242
1243
0
 error:
1244
0
  ast_array_free (tuple->children, tuple->n_children);
1245
0
  g_slice_free (Tuple, tuple);
1246
1247
0
  return NULL;
1248
0
}
1249
1250
typedef struct
1251
{
1252
  AST ast;
1253
1254
  AST *value;
1255
} Variant;
1256
1257
static gchar *
1258
variant_get_pattern (AST     *ast,
1259
                     GError **error)
1260
0
{
1261
0
  return g_strdup ("Mv");
1262
0
}
1263
1264
static GVariant *
1265
variant_get_value (AST                 *ast,
1266
                   const GVariantType  *type,
1267
                   GError             **error)
1268
0
{
1269
0
  Variant *variant = (Variant *) ast;
1270
0
  GVariant *child;
1271
1272
0
  if (!g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
1273
0
    return ast_type_error (ast, type, error);
1274
1275
0
  child = ast_resolve (variant->value, error);
1276
1277
0
  if (child == NULL)
1278
0
    return NULL;
1279
1280
0
  return g_variant_new_variant (child);
1281
0
}
1282
1283
static void
1284
variant_free (AST *ast)
1285
0
{
1286
0
  Variant *variant = (Variant *) ast;
1287
1288
0
  ast_free (variant->value);
1289
0
  g_slice_free (Variant, variant);
1290
0
}
1291
1292
static AST *
1293
variant_parse (TokenStream  *stream,
1294
               guint         max_depth,
1295
               va_list      *app,
1296
               GError      **error)
1297
0
{
1298
0
  static const ASTClass variant_class = {
1299
0
    variant_get_pattern,
1300
0
    maybe_wrapper, variant_get_value,
1301
0
    variant_free
1302
0
  };
1303
0
  Variant *variant;
1304
0
  AST *value;
1305
1306
0
  token_stream_assert (stream, "<");
1307
0
  value = parse (stream, max_depth - 1, app, error);
1308
1309
0
  if (!value)
1310
0
    return NULL;
1311
1312
0
  if (!token_stream_require (stream, ">", " to follow variant value", error))
1313
0
    {
1314
0
      ast_free (value);
1315
0
      return NULL;
1316
0
    }
1317
1318
0
  variant = g_slice_new (Variant);
1319
0
  variant->ast.class = &variant_class;
1320
0
  variant->value = value;
1321
1322
0
  return (AST *) variant;
1323
0
}
1324
1325
typedef struct
1326
{
1327
  AST ast;
1328
1329
  AST **keys;
1330
  AST **values;
1331
1332
  /* Iff this is DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY then this struct
1333
   * represents a single freestanding dict entry (`{1, "one"}`) rather than a
1334
   * full dict. In the freestanding case, @keys and @values have exactly one
1335
   * member each. */
1336
  size_t n_children;
1337
} Dictionary;
1338
1339
0
#define DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY ((size_t) -1)
1340
1341
static gchar *
1342
dictionary_get_pattern (AST     *ast,
1343
                        GError **error)
1344
0
{
1345
0
  Dictionary *dict = (Dictionary *) ast;
1346
0
  gchar *value_pattern;
1347
0
  gchar *key_pattern;
1348
0
  gchar key_char;
1349
0
  gchar *result;
1350
1351
0
  if (dict->n_children == 0)
1352
0
    return g_strdup ("Ma{**}");
1353
1354
0
  key_pattern = ast_array_get_pattern (dict->keys,
1355
0
                                       (dict->n_children == DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY) ? 1 : dict->n_children,
1356
0
                                       error);
1357
1358
0
  if (key_pattern == NULL)
1359
0
    return NULL;
1360
1361
  /* we can not have maybe keys */
1362
0
  if (key_pattern[0] == 'M')
1363
0
    key_char = key_pattern[1];
1364
0
  else
1365
0
    key_char = key_pattern[0];
1366
1367
0
  g_free (key_pattern);
1368
1369
  /* the basic types,
1370
   * plus undetermined number type and undetermined string type.
1371
   */
1372
0
  if (!strchr ("bynqiuxthdsogNS", key_char))
1373
0
    {
1374
0
      ast_set_error (ast, error, NULL,
1375
0
                     G_VARIANT_PARSE_ERROR_BASIC_TYPE_EXPECTED,
1376
0
                     "dictionary keys must have basic types");
1377
0
      return NULL;
1378
0
    }
1379
1380
0
  value_pattern = ast_get_pattern (dict->values[0], error);
1381
1382
0
  if (value_pattern == NULL)
1383
0
    return NULL;
1384
1385
0
  result = g_strdup_printf ("M%s{%c%s}",
1386
0
                            (dict->n_children > 0 && dict->n_children != DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY) ? "a" : "",
1387
0
                            key_char, value_pattern);
1388
0
  g_free (value_pattern);
1389
1390
0
  return result;
1391
0
}
1392
1393
static GVariant *
1394
dictionary_get_value (AST                 *ast,
1395
                      const GVariantType  *type,
1396
                      GError             **error)
1397
0
{
1398
0
  Dictionary *dict = (Dictionary *) ast;
1399
1400
0
  if (dict->n_children == DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY)
1401
0
    {
1402
0
      const GVariantType *subtype;
1403
0
      GVariantBuilder builder;
1404
0
      GVariant *subvalue;
1405
1406
0
      if (!g_variant_type_is_dict_entry (type))
1407
0
        return ast_type_error (ast, type, error);
1408
1409
0
      g_variant_builder_init_static (&builder, type);
1410
1411
0
      subtype = g_variant_type_key (type);
1412
0
      if (!(subvalue = ast_get_value (dict->keys[0], subtype, error)))
1413
0
        {
1414
0
          g_variant_builder_clear (&builder);
1415
0
          return NULL;
1416
0
        }
1417
0
      g_variant_builder_add_value (&builder, subvalue);
1418
1419
0
      subtype = g_variant_type_value (type);
1420
0
      if (!(subvalue = ast_get_value (dict->values[0], subtype, error)))
1421
0
        {
1422
0
          g_variant_builder_clear (&builder);
1423
0
          return NULL;
1424
0
        }
1425
0
      g_variant_builder_add_value (&builder, subvalue);
1426
1427
0
      return g_variant_builder_end (&builder);
1428
0
    }
1429
0
  else
1430
0
    {
1431
0
      const GVariantType *entry, *key, *val;
1432
0
      GVariantBuilder builder;
1433
0
      size_t i;
1434
1435
0
      if (!g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_DICTIONARY))
1436
0
        return ast_type_error (ast, type, error);
1437
1438
0
      entry = g_variant_type_element (type);
1439
0
      key = g_variant_type_key (entry);
1440
0
      val = g_variant_type_value (entry);
1441
1442
0
      g_variant_builder_init_static (&builder, type);
1443
1444
0
      for (i = 0; i < dict->n_children; i++)
1445
0
        {
1446
0
          GVariant *subvalue;
1447
1448
0
          g_variant_builder_open (&builder, entry);
1449
1450
0
          if (!(subvalue = ast_get_value (dict->keys[i], key, error)))
1451
0
            {
1452
0
              g_variant_builder_clear (&builder);
1453
0
              return NULL;
1454
0
            }
1455
0
          g_variant_builder_add_value (&builder, subvalue);
1456
1457
0
          if (!(subvalue = ast_get_value (dict->values[i], val, error)))
1458
0
            {
1459
0
              g_variant_builder_clear (&builder);
1460
0
              return NULL;
1461
0
            }
1462
0
          g_variant_builder_add_value (&builder, subvalue);
1463
0
          g_variant_builder_close (&builder);
1464
0
        }
1465
1466
0
      return g_variant_builder_end (&builder);
1467
0
    }
1468
0
}
1469
1470
static void
1471
dictionary_free (AST *ast)
1472
0
{
1473
0
  Dictionary *dict = (Dictionary *) ast;
1474
0
  size_t n_children;
1475
1476
0
  if (dict->n_children == DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY)
1477
0
    n_children = 1;
1478
0
  else
1479
0
    n_children = dict->n_children;
1480
1481
0
  ast_array_free (dict->keys, n_children);
1482
0
  ast_array_free (dict->values, n_children);
1483
0
  g_slice_free (Dictionary, dict);
1484
0
}
1485
1486
static AST *
1487
dictionary_parse (TokenStream  *stream,
1488
                  guint         max_depth,
1489
                  va_list      *app,
1490
                  GError      **error)
1491
0
{
1492
0
  static const ASTClass dictionary_class = {
1493
0
    dictionary_get_pattern,
1494
0
    maybe_wrapper, dictionary_get_value,
1495
0
    dictionary_free
1496
0
  };
1497
0
  size_t n_keys, n_values;
1498
0
  gboolean only_one;
1499
0
  Dictionary *dict;
1500
0
  AST *first;
1501
1502
0
  dict = g_slice_new (Dictionary);
1503
0
  dict->ast.class = &dictionary_class;
1504
0
  dict->keys = NULL;
1505
0
  dict->values = NULL;
1506
0
  n_keys = n_values = 0;
1507
1508
0
  token_stream_assert (stream, "{");
1509
1510
0
  if (token_stream_consume (stream, "}"))
1511
0
    {
1512
0
      dict->n_children = 0;
1513
0
      return (AST *) dict;
1514
0
    }
1515
1516
0
  if ((first = parse (stream, max_depth - 1, app, error)) == NULL)
1517
0
    goto error;
1518
1519
0
  ast_array_append (&dict->keys, &n_keys, first);
1520
1521
0
  only_one = token_stream_consume (stream, ",");
1522
0
  if (!only_one &&
1523
0
      !token_stream_require (stream, ":",
1524
0
                             " or ',' to follow dictionary entry key",
1525
0
                             error))
1526
0
    goto error;
1527
1528
0
  if ((first = parse (stream, max_depth - 1, app, error)) == NULL)
1529
0
    goto error;
1530
1531
0
  ast_array_append (&dict->values, &n_values, first);
1532
1533
0
  if (only_one)
1534
0
    {
1535
0
      if (!token_stream_require (stream, "}", " at end of dictionary entry",
1536
0
                                 error))
1537
0
        goto error;
1538
1539
0
      g_assert (n_keys == 1 && n_values == 1);
1540
0
      dict->n_children = DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY;
1541
1542
0
      return (AST *) dict;
1543
0
    }
1544
1545
0
  while (!token_stream_consume (stream, "}"))
1546
0
    {
1547
0
      AST *child;
1548
1549
0
      if (!token_stream_require (stream, ",",
1550
0
                                 " or '}' to follow dictionary entry", error))
1551
0
        goto error;
1552
1553
0
      child = parse (stream, max_depth - 1, app, error);
1554
1555
0
      if (!child)
1556
0
        goto error;
1557
1558
0
      ast_array_append (&dict->keys, &n_keys, child);
1559
1560
0
      if (!token_stream_require (stream, ":",
1561
0
                                 " to follow dictionary entry key", error))
1562
0
        goto error;
1563
1564
0
      child = parse (stream, max_depth - 1, app, error);
1565
1566
0
      if (!child)
1567
0
        goto error;
1568
1569
0
      ast_array_append (&dict->values, &n_values, child);
1570
0
    }
1571
1572
0
  g_assert (n_keys == n_values);
1573
0
  g_assert (n_keys != DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY);
1574
0
  dict->n_children = n_keys;
1575
1576
0
  return (AST *) dict;
1577
1578
0
 error:
1579
0
  ast_array_free (dict->keys, n_keys);
1580
0
  ast_array_free (dict->values, n_values);
1581
0
  g_slice_free (Dictionary, dict);
1582
1583
0
  return NULL;
1584
0
}
1585
1586
typedef struct
1587
{
1588
  AST ast;
1589
  gchar *string;
1590
} String;
1591
1592
static gchar *
1593
string_get_pattern (AST     *ast,
1594
                    GError **error)
1595
0
{
1596
0
  return g_strdup ("MS");
1597
0
}
1598
1599
static GVariant *
1600
string_get_value (AST                 *ast,
1601
                  const GVariantType  *type,
1602
                  GError             **error)
1603
0
{
1604
0
  String *string = (String *) ast;
1605
1606
0
  if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
1607
0
    return g_variant_new_string (string->string);
1608
1609
0
  else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
1610
0
    {
1611
0
      if (!g_variant_is_object_path (string->string))
1612
0
        {
1613
0
          ast_set_error (ast, error, NULL,
1614
0
                         G_VARIANT_PARSE_ERROR_INVALID_OBJECT_PATH,
1615
0
                         "not a valid object path");
1616
0
          return NULL;
1617
0
        }
1618
1619
0
      return g_variant_new_object_path (string->string);
1620
0
    }
1621
1622
0
  else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
1623
0
    {
1624
0
      if (!g_variant_is_signature (string->string))
1625
0
        {
1626
0
          ast_set_error (ast, error, NULL,
1627
0
                         G_VARIANT_PARSE_ERROR_INVALID_SIGNATURE,
1628
0
                         "not a valid signature");
1629
0
          return NULL;
1630
0
        }
1631
1632
0
      return g_variant_new_signature (string->string);
1633
0
    }
1634
1635
0
  else
1636
0
    return ast_type_error (ast, type, error);
1637
0
}
1638
1639
static void
1640
string_free (AST *ast)
1641
0
{
1642
0
  String *string = (String *) ast;
1643
1644
0
  g_free (string->string);
1645
0
  g_slice_free (String, string);
1646
0
}
1647
1648
/* Accepts exactly @length hexadecimal digits. No leading sign or `0x`/`0X` prefix allowed.
1649
 * No leading/trailing space allowed.
1650
 *
1651
 * It's OK to pass a length greater than the actual length of the src buffer,
1652
 * provided src must be null-terminated.
1653
 */
1654
static gboolean
1655
unicode_unescape (const gchar  *src,
1656
                  size_t       *src_ofs,
1657
                  gchar        *dest,
1658
                  size_t       *dest_ofs,
1659
                  gsize         length,
1660
                  SourceRef    *ref,
1661
                  GError      **error)
1662
0
{
1663
0
  gchar buffer[9];
1664
0
  guint64 value = 0;
1665
0
  gchar *end = NULL;
1666
0
  gsize n_valid_chars;
1667
1668
0
  (*src_ofs)++;
1669
1670
0
  g_assert (length < sizeof (buffer));
1671
0
  strncpy (buffer, src + *src_ofs, length);
1672
0
  buffer[length] = '\0';
1673
1674
0
  for (n_valid_chars = 0; n_valid_chars < length; n_valid_chars++)
1675
0
    if (!g_ascii_isxdigit (buffer[n_valid_chars]))
1676
0
      break;
1677
1678
0
  if (n_valid_chars == length)
1679
0
    value = g_ascii_strtoull (buffer, &end, 0x10);
1680
1681
0
  if (value == 0 || end != buffer + length)
1682
0
    {
1683
0
      SourceRef escape_ref;
1684
1685
0
      escape_ref = *ref;
1686
0
      escape_ref.start += *src_ofs;
1687
0
      escape_ref.end = escape_ref.start + n_valid_chars;
1688
1689
0
      parser_set_error (error, &escape_ref, NULL,
1690
0
                        G_VARIANT_PARSE_ERROR_INVALID_CHARACTER,
1691
0
                        "invalid %" G_GSIZE_FORMAT "-character unicode escape", length);
1692
0
      return FALSE;
1693
0
    }
1694
1695
0
  g_assert (value <= G_MAXUINT32);
1696
1697
0
  *dest_ofs += g_unichar_to_utf8 (value, dest + *dest_ofs);
1698
0
  *src_ofs += length;
1699
1700
0
  return TRUE;
1701
0
}
1702
1703
static AST *
1704
string_parse (TokenStream  *stream,
1705
              va_list      *app,
1706
              GError      **error)
1707
0
{
1708
0
  static const ASTClass string_class = {
1709
0
    string_get_pattern,
1710
0
    maybe_wrapper, string_get_value,
1711
0
    string_free
1712
0
  };
1713
0
  String *string;
1714
0
  SourceRef ref;
1715
0
  gchar *token;
1716
0
  gsize length;
1717
0
  gchar quote;
1718
0
  gchar *str;
1719
0
  size_t i, j;
1720
1721
0
  token_stream_start_ref (stream, &ref);
1722
0
  token = token_stream_get (stream);
1723
0
  token_stream_end_ref (stream, &ref);
1724
0
  length = strlen (token);
1725
0
  quote = token[0];
1726
1727
  /* The output will always be at least one byte smaller than the input,
1728
   * because we skip over the initial quote character.
1729
   */
1730
0
  str = g_malloc (length);
1731
0
  g_assert (quote == '"' || quote == '\'');
1732
0
  j = 0;
1733
0
  i = 1;
1734
0
  while (token[i] != quote)
1735
0
    switch (token[i])
1736
0
      {
1737
0
      case '\0':
1738
0
        parser_set_error (error, &ref, NULL,
1739
0
                          G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1740
0
                          "unterminated string constant");
1741
0
        g_free (token);
1742
0
        g_free (str);
1743
0
        return NULL;
1744
1745
0
      case '\\':
1746
0
        switch (token[++i])
1747
0
          {
1748
0
          case '\0':
1749
0
            parser_set_error (error, &ref, NULL,
1750
0
                              G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1751
0
                              "unterminated string constant");
1752
0
            g_free (token);
1753
0
            g_free (str);
1754
0
            return NULL;
1755
1756
0
          case 'u':
1757
0
            if (!unicode_unescape (token, &i, str, &j, 4, &ref, error))
1758
0
              {
1759
0
                g_free (token);
1760
0
                g_free (str);
1761
0
                return NULL;
1762
0
              }
1763
0
            continue;
1764
1765
0
          case 'U':
1766
0
            if (!unicode_unescape (token, &i, str, &j, 8, &ref, error))
1767
0
              {
1768
0
                g_free (token);
1769
0
                g_free (str);
1770
0
                return NULL;
1771
0
              }
1772
0
            continue;
1773
1774
0
          case 'a': str[j++] = '\a'; i++; continue;
1775
0
          case 'b': str[j++] = '\b'; i++; continue;
1776
0
          case 'f': str[j++] = '\f'; i++; continue;
1777
0
          case 'n': str[j++] = '\n'; i++; continue;
1778
0
          case 'r': str[j++] = '\r'; i++; continue;
1779
0
          case 't': str[j++] = '\t'; i++; continue;
1780
0
          case 'v': str[j++] = '\v'; i++; continue;
1781
0
          case '\n': i++; continue;
1782
0
          }
1783
1784
0
        G_GNUC_FALLTHROUGH;
1785
1786
0
      default:
1787
0
        str[j++] = token[i++];
1788
0
      }
1789
0
  str[j++] = '\0';
1790
0
  g_free (token);
1791
1792
0
  string = g_slice_new (String);
1793
0
  string->ast.class = &string_class;
1794
0
  string->string = str;
1795
1796
0
  token_stream_next (stream);
1797
1798
0
  return (AST *) string;
1799
0
}
1800
1801
typedef struct
1802
{
1803
  AST ast;
1804
  gchar *string;
1805
} ByteString;
1806
1807
static gchar *
1808
bytestring_get_pattern (AST     *ast,
1809
                        GError **error)
1810
0
{
1811
0
  return g_strdup ("May");
1812
0
}
1813
1814
static GVariant *
1815
bytestring_get_value (AST                 *ast,
1816
                      const GVariantType  *type,
1817
                      GError             **error)
1818
0
{
1819
0
  ByteString *string = (ByteString *) ast;
1820
1821
0
  if (!g_variant_type_equal (type, G_VARIANT_TYPE_BYTESTRING))
1822
0
    return ast_type_error (ast, type, error);
1823
1824
0
  return g_variant_new_bytestring (string->string);
1825
0
}
1826
1827
static void
1828
bytestring_free (AST *ast)
1829
0
{
1830
0
  ByteString *string = (ByteString *) ast;
1831
1832
0
  g_free (string->string);
1833
0
  g_slice_free (ByteString, string);
1834
0
}
1835
1836
static AST *
1837
bytestring_parse (TokenStream  *stream,
1838
                  va_list      *app,
1839
                  GError      **error)
1840
0
{
1841
0
  static const ASTClass bytestring_class = {
1842
0
    bytestring_get_pattern,
1843
0
    maybe_wrapper, bytestring_get_value,
1844
0
    bytestring_free
1845
0
  };
1846
0
  ByteString *string;
1847
0
  SourceRef ref;
1848
0
  gchar *token;
1849
0
  gsize length;
1850
0
  gchar quote;
1851
0
  gchar *str;
1852
0
  size_t i, j;
1853
1854
0
  token_stream_start_ref (stream, &ref);
1855
0
  token = token_stream_get (stream);
1856
0
  token_stream_end_ref (stream, &ref);
1857
0
  g_assert (token[0] == 'b');
1858
0
  length = strlen (token);
1859
0
  quote = token[1];
1860
1861
  /* The output will always be smaller than the input, because we skip over the
1862
   * initial b and the quote character.
1863
   */
1864
0
  str = g_malloc (length);
1865
0
  g_assert (quote == '"' || quote == '\'');
1866
0
  j = 0;
1867
0
  i = 2;
1868
0
  while (token[i] != quote)
1869
0
    switch (token[i])
1870
0
      {
1871
0
      case '\0':
1872
0
        parser_set_error (error, &ref, NULL,
1873
0
                          G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1874
0
                          "unterminated string constant");
1875
0
        g_free (str);
1876
0
        g_free (token);
1877
0
        return NULL;
1878
1879
0
      case '\\':
1880
0
        switch (token[++i])
1881
0
          {
1882
0
          case '\0':
1883
0
            parser_set_error (error, &ref, NULL,
1884
0
                              G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1885
0
                              "unterminated string constant");
1886
0
            g_free (str);
1887
0
            g_free (token);
1888
0
            return NULL;
1889
1890
0
          case '0': case '1': case '2': case '3':
1891
0
          case '4': case '5': case '6': case '7':
1892
0
            {
1893
              /* up to 3 characters */
1894
0
              guchar val = token[i++] - '0';
1895
1896
0
              if ('0' <= token[i] && token[i] < '8')
1897
0
                val = (val << 3) | (token[i++] - '0');
1898
1899
0
              if ('0' <= token[i] && token[i] < '8')
1900
0
                val = (val << 3) | (token[i++] - '0');
1901
1902
0
              str[j++] = val;
1903
0
            }
1904
0
            continue;
1905
1906
0
          case 'a': str[j++] = '\a'; i++; continue;
1907
0
          case 'b': str[j++] = '\b'; i++; continue;
1908
0
          case 'f': str[j++] = '\f'; i++; continue;
1909
0
          case 'n': str[j++] = '\n'; i++; continue;
1910
0
          case 'r': str[j++] = '\r'; i++; continue;
1911
0
          case 't': str[j++] = '\t'; i++; continue;
1912
0
          case 'v': str[j++] = '\v'; i++; continue;
1913
0
          case '\n': i++; continue;
1914
0
          }
1915
1916
0
        G_GNUC_FALLTHROUGH;
1917
1918
0
      default:
1919
0
        str[j++] = token[i++];
1920
0
      }
1921
0
  str[j++] = '\0';
1922
0
  g_free (token);
1923
1924
0
  string = g_slice_new (ByteString);
1925
0
  string->ast.class = &bytestring_class;
1926
0
  string->string = str;
1927
1928
0
  token_stream_next (stream);
1929
1930
0
  return (AST *) string;
1931
0
}
1932
1933
typedef struct
1934
{
1935
  AST ast;
1936
1937
  gchar *token;
1938
} Number;
1939
1940
static gchar *
1941
number_get_pattern (AST     *ast,
1942
                    GError **error)
1943
0
{
1944
0
  Number *number = (Number *) ast;
1945
1946
0
  if (strchr (number->token, '.') ||
1947
0
      (!g_str_has_prefix (number->token, "0x") && strchr (number->token, 'e')) ||
1948
0
      strstr (number->token, "inf") ||
1949
0
      strstr (number->token, "nan"))
1950
0
    return g_strdup ("Md");
1951
1952
0
  return g_strdup ("MN");
1953
0
}
1954
1955
static GVariant *
1956
number_overflow (AST                 *ast,
1957
                 const GVariantType  *type,
1958
                 GError             **error)
1959
0
{
1960
0
  ast_set_error (ast, error, NULL,
1961
0
                 G_VARIANT_PARSE_ERROR_NUMBER_OUT_OF_RANGE,
1962
0
                 "number out of range for type '%c'",
1963
0
                 g_variant_type_peek_string (type)[0]);
1964
0
  return NULL;
1965
0
}
1966
1967
static GVariant *
1968
number_get_value (AST                 *ast,
1969
                  const GVariantType  *type,
1970
                  GError             **error)
1971
0
{
1972
0
  Number *number = (Number *) ast;
1973
0
  const gchar *token;
1974
0
  gboolean negative;
1975
0
  gboolean floating;
1976
0
  guint64 abs_val;
1977
0
  gdouble dbl_val;
1978
0
  gchar *end;
1979
1980
0
  token = number->token;
1981
1982
0
  if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
1983
0
    {
1984
0
      floating = TRUE;
1985
1986
0
      errno = 0;
1987
0
      dbl_val = g_ascii_strtod (token, &end);
1988
0
      if (dbl_val != 0.0 && errno == ERANGE)
1989
0
        {
1990
0
          ast_set_error (ast, error, NULL,
1991
0
                         G_VARIANT_PARSE_ERROR_NUMBER_TOO_BIG,
1992
0
                         "number too big for any type");
1993
0
          return NULL;
1994
0
        }
1995
1996
      /* silence uninitialised warnings... */
1997
0
      negative = FALSE;
1998
0
      abs_val = 0;
1999
0
    }
2000
0
  else
2001
0
    {
2002
0
      floating = FALSE;
2003
0
      negative = token[0] == '-';
2004
0
      if (token[0] == '-')
2005
0
        token++;
2006
2007
0
      errno = 0;
2008
0
      abs_val = g_ascii_strtoull (token, &end, 0);
2009
0
      if (abs_val == G_MAXUINT64 && errno == ERANGE)
2010
0
        {
2011
0
          ast_set_error (ast, error, NULL,
2012
0
                         G_VARIANT_PARSE_ERROR_NUMBER_TOO_BIG,
2013
0
                         "integer too big for any type");
2014
0
          return NULL;
2015
0
        }
2016
2017
0
      if (abs_val == 0)
2018
0
        negative = FALSE;
2019
2020
      /* silence uninitialised warning... */
2021
0
      dbl_val = 0.0;
2022
0
    }
2023
2024
0
  if (*end != '\0')
2025
0
    {
2026
0
      SourceRef ref;
2027
2028
0
      ref = ast->source_ref;
2029
0
      ref.start += end - number->token;
2030
0
      ref.end = ref.start + 1;
2031
2032
0
      parser_set_error (error, &ref, NULL,
2033
0
                        G_VARIANT_PARSE_ERROR_INVALID_CHARACTER,
2034
0
                        "invalid character in number");
2035
0
      return NULL;
2036
0
     }
2037
2038
0
  if (floating)
2039
0
    return g_variant_new_double (dbl_val);
2040
2041
0
  switch (*g_variant_type_peek_string (type))
2042
0
    {
2043
0
    case 'y':
2044
0
      if (negative || abs_val > G_MAXUINT8)
2045
0
        return number_overflow (ast, type, error);
2046
0
      return g_variant_new_byte (abs_val);
2047
2048
0
    case 'n':
2049
0
      if (abs_val - negative > G_MAXINT16)
2050
0
        return number_overflow (ast, type, error);
2051
0
      if (negative && abs_val > G_MAXINT16)
2052
0
        return g_variant_new_int16 (G_MININT16);
2053
0
      return g_variant_new_int16 (negative ?
2054
0
                                  -((gint16) abs_val) : ((gint16) abs_val));
2055
2056
0
    case 'q':
2057
0
      if (negative || abs_val > G_MAXUINT16)
2058
0
        return number_overflow (ast, type, error);
2059
0
      return g_variant_new_uint16 (abs_val);
2060
2061
0
    case 'i':
2062
0
      if (abs_val - negative > G_MAXINT32)
2063
0
        return number_overflow (ast, type, error);
2064
0
      if (negative && abs_val > G_MAXINT32)
2065
0
        return g_variant_new_int32 (G_MININT32);
2066
0
      return g_variant_new_int32 (negative ?
2067
0
                                  -((gint32) abs_val) : ((gint32) abs_val));
2068
2069
0
    case 'u':
2070
0
      if (negative || abs_val > G_MAXUINT32)
2071
0
        return number_overflow (ast, type, error);
2072
0
      return g_variant_new_uint32 (abs_val);
2073
2074
0
    case 'x':
2075
0
      if (abs_val - negative > G_MAXINT64)
2076
0
        return number_overflow (ast, type, error);
2077
0
      if (negative && abs_val > G_MAXINT64)
2078
0
        return g_variant_new_int64 (G_MININT64);
2079
0
      return g_variant_new_int64 (negative ?
2080
0
                                  -((gint64) abs_val) : ((gint64) abs_val));
2081
2082
0
    case 't':
2083
0
      if (negative)
2084
0
        return number_overflow (ast, type, error);
2085
0
      return g_variant_new_uint64 (abs_val);
2086
2087
0
    case 'h':
2088
0
      if (abs_val - negative > G_MAXINT32)
2089
0
        return number_overflow (ast, type, error);
2090
0
      if (negative && abs_val > G_MAXINT32)
2091
0
        return g_variant_new_handle (G_MININT32);
2092
0
      return g_variant_new_handle (negative ?
2093
0
                                   -((gint32) abs_val) : ((gint32) abs_val));
2094
2095
0
    default:
2096
0
      return ast_type_error (ast, type, error);
2097
0
    }
2098
0
}
2099
2100
static void
2101
number_free (AST *ast)
2102
0
{
2103
0
  Number *number = (Number *) ast;
2104
2105
0
  g_free (number->token);
2106
0
  g_slice_free (Number, number);
2107
0
}
2108
2109
static AST *
2110
number_parse (TokenStream  *stream,
2111
              va_list      *app,
2112
              GError      **error)
2113
0
{
2114
0
  static const ASTClass number_class = {
2115
0
    number_get_pattern,
2116
0
    maybe_wrapper, number_get_value,
2117
0
    number_free
2118
0
  };
2119
0
  Number *number;
2120
2121
0
  number = g_slice_new (Number);
2122
0
  number->ast.class = &number_class;
2123
0
  number->token = token_stream_get (stream);
2124
0
  token_stream_next (stream);
2125
2126
0
  return (AST *) number;
2127
0
}
2128
2129
typedef struct
2130
{
2131
  AST ast;
2132
  gboolean value;
2133
} Boolean;
2134
2135
static gchar *
2136
boolean_get_pattern (AST     *ast,
2137
                     GError **error)
2138
0
{
2139
0
  return g_strdup ("Mb");
2140
0
}
2141
2142
static GVariant *
2143
boolean_get_value (AST                 *ast,
2144
                   const GVariantType  *type,
2145
                   GError             **error)
2146
0
{
2147
0
  Boolean *boolean = (Boolean *) ast;
2148
2149
0
  if (!g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
2150
0
    return ast_type_error (ast, type, error);
2151
2152
0
  return g_variant_new_boolean (boolean->value);
2153
0
}
2154
2155
static void
2156
boolean_free (AST *ast)
2157
0
{
2158
0
  Boolean *boolean = (Boolean *) ast;
2159
2160
0
  g_slice_free (Boolean, boolean);
2161
0
}
2162
2163
static AST *
2164
boolean_new (gboolean value)
2165
0
{
2166
0
  static const ASTClass boolean_class = {
2167
0
    boolean_get_pattern,
2168
0
    maybe_wrapper, boolean_get_value,
2169
0
    boolean_free
2170
0
  };
2171
0
  Boolean *boolean;
2172
2173
0
  boolean = g_slice_new (Boolean);
2174
0
  boolean->ast.class = &boolean_class;
2175
0
  boolean->value = value;
2176
2177
0
  return (AST *) boolean;
2178
0
}
2179
2180
typedef struct
2181
{
2182
  AST ast;
2183
2184
  GVariant *value;
2185
} Positional;
2186
2187
static gchar *
2188
positional_get_pattern (AST     *ast,
2189
                        GError **error)
2190
0
{
2191
0
  Positional *positional = (Positional *) ast;
2192
2193
0
  return g_strdup (g_variant_get_type_string (positional->value));
2194
0
}
2195
2196
static GVariant *
2197
positional_get_value (AST                 *ast,
2198
                      const GVariantType  *type,
2199
                      GError             **error)
2200
0
{
2201
0
  Positional *positional = (Positional *) ast;
2202
0
  GVariant *value;
2203
2204
0
  g_assert (positional->value != NULL);
2205
2206
0
  if G_UNLIKELY (!g_variant_is_of_type (positional->value, type))
2207
0
    return ast_type_error (ast, type, error);
2208
2209
  /* NOTE: if _get is called more than once then
2210
   * things get messed up with respect to floating refs.
2211
   *
2212
   * fortunately, this function should only ever get called once.
2213
   */
2214
0
  g_assert (positional->value != NULL);
2215
0
  value = positional->value;
2216
0
  positional->value = NULL;
2217
2218
0
  return value;
2219
0
}
2220
2221
static void
2222
positional_free (AST *ast)
2223
0
{
2224
0
  Positional *positional = (Positional *) ast;
2225
2226
  /* if positional->value is set, just leave it.
2227
   * memory management doesn't matter in case of programmer error.
2228
   */
2229
0
  g_slice_free (Positional, positional);
2230
0
}
2231
2232
static AST *
2233
positional_parse (TokenStream  *stream,
2234
                  va_list      *app,
2235
                  GError      **error)
2236
0
{
2237
0
  static const ASTClass positional_class = {
2238
0
    positional_get_pattern,
2239
0
    positional_get_value, NULL,
2240
0
    positional_free
2241
0
  };
2242
0
  Positional *positional;
2243
0
  const gchar *endptr;
2244
0
  gchar *token;
2245
2246
0
  token = token_stream_get (stream);
2247
0
  g_assert (token[0] == '%');
2248
2249
0
  positional = g_slice_new (Positional);
2250
0
  positional->ast.class = &positional_class;
2251
0
  positional->value = g_variant_new_va (token + 1, &endptr, app);
2252
2253
0
  if (*endptr || positional->value == NULL)
2254
0
    {
2255
0
      token_stream_set_error (stream, error, TRUE,
2256
0
                              G_VARIANT_PARSE_ERROR_INVALID_FORMAT_STRING,
2257
0
                              "invalid GVariant format string");
2258
      /* memory management doesn't matter in case of programmer error. */
2259
0
      return NULL;
2260
0
    }
2261
2262
0
  token_stream_next (stream);
2263
0
  g_free (token);
2264
2265
0
  return (AST *) positional;
2266
0
}
2267
2268
typedef struct
2269
{
2270
  AST ast;
2271
2272
  GVariantType *type;
2273
  AST *child;
2274
} TypeDecl;
2275
2276
static gchar *
2277
typedecl_get_pattern (AST     *ast,
2278
                      GError **error)
2279
0
{
2280
0
  TypeDecl *decl = (TypeDecl *) ast;
2281
2282
0
  return g_variant_type_dup_string (decl->type);
2283
0
}
2284
2285
static GVariant *
2286
typedecl_get_value (AST                 *ast,
2287
                    const GVariantType  *type,
2288
                    GError             **error)
2289
0
{
2290
0
  TypeDecl *decl = (TypeDecl *) ast;
2291
2292
0
  return ast_get_value (decl->child, type, error);
2293
0
}
2294
2295
static void
2296
typedecl_free (AST *ast)
2297
0
{
2298
0
  TypeDecl *decl = (TypeDecl *) ast;
2299
2300
0
  ast_free (decl->child);
2301
0
  g_variant_type_free (decl->type);
2302
0
  g_slice_free (TypeDecl, decl);
2303
0
}
2304
2305
static AST *
2306
typedecl_parse (TokenStream  *stream,
2307
                guint         max_depth,
2308
                va_list      *app,
2309
                GError      **error)
2310
0
{
2311
0
  static const ASTClass typedecl_class = {
2312
0
    typedecl_get_pattern,
2313
0
    typedecl_get_value, NULL,
2314
0
    typedecl_free
2315
0
  };
2316
0
  GVariantType *type;
2317
0
  TypeDecl *decl;
2318
0
  AST *child;
2319
2320
0
  if (token_stream_peek (stream, '@'))
2321
0
    {
2322
0
      gchar *token;
2323
2324
0
      token = token_stream_get (stream);
2325
2326
0
      if (!g_variant_type_string_is_valid (token + 1))
2327
0
        {
2328
0
          token_stream_set_error (stream, error, TRUE,
2329
0
                                  G_VARIANT_PARSE_ERROR_INVALID_TYPE_STRING,
2330
0
                                  "invalid type declaration");
2331
0
          g_free (token);
2332
2333
0
          return NULL;
2334
0
        }
2335
2336
0
      if (g_variant_type_string_get_depth_ (token + 1) > max_depth)
2337
0
        {
2338
0
          token_stream_set_error (stream, error, TRUE,
2339
0
                                  G_VARIANT_PARSE_ERROR_RECURSION,
2340
0
                                  "type declaration recurses too deeply");
2341
0
          g_free (token);
2342
2343
0
          return NULL;
2344
0
        }
2345
2346
0
      type = g_variant_type_new (token + 1);
2347
2348
0
      if (!g_variant_type_is_definite (type))
2349
0
        {
2350
0
          token_stream_set_error (stream, error, TRUE,
2351
0
                                  G_VARIANT_PARSE_ERROR_DEFINITE_TYPE_EXPECTED,
2352
0
                                  "type declarations must be definite");
2353
0
          g_variant_type_free (type);
2354
0
          g_free (token);
2355
2356
0
          return NULL;
2357
0
        }
2358
2359
0
      token_stream_next (stream);
2360
0
      g_free (token);
2361
0
    }
2362
0
  else
2363
0
    {
2364
0
      if (token_stream_consume (stream, "boolean"))
2365
0
        type = g_variant_type_copy (G_VARIANT_TYPE_BOOLEAN);
2366
2367
0
      else if (token_stream_consume (stream, "byte"))
2368
0
        type = g_variant_type_copy (G_VARIANT_TYPE_BYTE);
2369
2370
0
      else if (token_stream_consume (stream, "int16"))
2371
0
        type = g_variant_type_copy (G_VARIANT_TYPE_INT16);
2372
2373
0
      else if (token_stream_consume (stream, "uint16"))
2374
0
        type = g_variant_type_copy (G_VARIANT_TYPE_UINT16);
2375
2376
0
      else if (token_stream_consume (stream, "int32"))
2377
0
        type = g_variant_type_copy (G_VARIANT_TYPE_INT32);
2378
2379
0
      else if (token_stream_consume (stream, "handle"))
2380
0
        type = g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
2381
2382
0
      else if (token_stream_consume (stream, "uint32"))
2383
0
        type = g_variant_type_copy (G_VARIANT_TYPE_UINT32);
2384
2385
0
      else if (token_stream_consume (stream, "int64"))
2386
0
        type = g_variant_type_copy (G_VARIANT_TYPE_INT64);
2387
2388
0
      else if (token_stream_consume (stream, "uint64"))
2389
0
        type = g_variant_type_copy (G_VARIANT_TYPE_UINT64);
2390
2391
0
      else if (token_stream_consume (stream, "double"))
2392
0
        type = g_variant_type_copy (G_VARIANT_TYPE_DOUBLE);
2393
2394
0
      else if (token_stream_consume (stream, "string"))
2395
0
        type = g_variant_type_copy (G_VARIANT_TYPE_STRING);
2396
2397
0
      else if (token_stream_consume (stream, "objectpath"))
2398
0
        type = g_variant_type_copy (G_VARIANT_TYPE_OBJECT_PATH);
2399
2400
0
      else if (token_stream_consume (stream, "signature"))
2401
0
        type = g_variant_type_copy (G_VARIANT_TYPE_SIGNATURE);
2402
2403
0
      else
2404
0
        {
2405
0
          token_stream_set_error (stream, error, TRUE,
2406
0
                                  G_VARIANT_PARSE_ERROR_UNKNOWN_KEYWORD,
2407
0
                                  "unknown keyword");
2408
0
          return NULL;
2409
0
        }
2410
0
    }
2411
2412
0
  if ((child = parse (stream, max_depth - 1, app, error)) == NULL)
2413
0
    {
2414
0
      g_variant_type_free (type);
2415
0
      return NULL;
2416
0
    }
2417
2418
0
  decl = g_slice_new (TypeDecl);
2419
0
  decl->ast.class = &typedecl_class;
2420
0
  decl->type = type;
2421
0
  decl->child = child;
2422
2423
0
  return (AST *) decl;
2424
0
}
2425
2426
static AST *
2427
parse (TokenStream  *stream,
2428
       guint         max_depth,
2429
       va_list      *app,
2430
       GError      **error)
2431
0
{
2432
0
  SourceRef source_ref;
2433
0
  AST *result;
2434
2435
0
  if (max_depth == 0)
2436
0
    {
2437
0
      token_stream_set_error (stream, error, FALSE,
2438
0
                              G_VARIANT_PARSE_ERROR_RECURSION,
2439
0
                              "variant nested too deeply");
2440
0
      return NULL;
2441
0
    }
2442
2443
0
  token_stream_prepare (stream);
2444
0
  token_stream_start_ref (stream, &source_ref);
2445
2446
0
  if (token_stream_peek (stream, '['))
2447
0
    result = array_parse (stream, max_depth, app, error);
2448
2449
0
  else if (token_stream_peek (stream, '('))
2450
0
    result = tuple_parse (stream, max_depth, app, error);
2451
2452
0
  else if (token_stream_peek (stream, '<'))
2453
0
    result = variant_parse (stream, max_depth, app, error);
2454
2455
0
  else if (token_stream_peek (stream, '{'))
2456
0
    result = dictionary_parse (stream, max_depth, app, error);
2457
2458
0
  else if (app && token_stream_peek (stream, '%'))
2459
0
    result = positional_parse (stream, app, error);
2460
2461
0
  else if (token_stream_consume (stream, "true"))
2462
0
    result = boolean_new (TRUE);
2463
2464
0
  else if (token_stream_consume (stream, "false"))
2465
0
    result = boolean_new (FALSE);
2466
2467
0
  else if (token_stream_is_numeric (stream) ||
2468
0
           token_stream_peek_string (stream, "inf") ||
2469
0
           token_stream_peek_string (stream, "nan"))
2470
0
    result = number_parse (stream, app, error);
2471
2472
0
  else if (token_stream_peek (stream, 'n') ||
2473
0
           token_stream_peek (stream, 'j'))
2474
0
    result = maybe_parse (stream, max_depth, app, error);
2475
2476
0
  else if (token_stream_peek (stream, '@') ||
2477
0
           token_stream_is_keyword (stream))
2478
0
    result = typedecl_parse (stream, max_depth, app, error);
2479
2480
0
  else if (token_stream_peek (stream, '\'') ||
2481
0
           token_stream_peek (stream, '"'))
2482
0
    result = string_parse (stream, app, error);
2483
2484
0
  else if (token_stream_peek2 (stream, 'b', '\'') ||
2485
0
           token_stream_peek2 (stream, 'b', '"'))
2486
0
    result = bytestring_parse (stream, app, error);
2487
2488
0
  else
2489
0
    {
2490
0
      token_stream_set_error (stream, error, FALSE,
2491
0
                              G_VARIANT_PARSE_ERROR_VALUE_EXPECTED,
2492
0
                              "expected value");
2493
0
      return NULL;
2494
0
    }
2495
2496
0
  if (result != NULL)
2497
0
    {
2498
0
      token_stream_end_ref (stream, &source_ref);
2499
0
      result->source_ref = source_ref;
2500
0
    }
2501
2502
0
  return result;
2503
0
}
2504
2505
/**
2506
 * g_variant_parse:
2507
 * @type: (nullable): a #GVariantType, or %NULL
2508
 * @text: a string containing a GVariant in text form
2509
 * @limit: (nullable): a pointer to the end of @text, or %NULL
2510
 * @endptr: (nullable): a location to store the end pointer, or %NULL
2511
 * @error: (nullable): a pointer to a %NULL #GError pointer, or %NULL
2512
 *
2513
 * Parses a #GVariant from a text representation.
2514
 *
2515
 * A single #GVariant is parsed from the content of @text.
2516
 *
2517
 * The format is described [here](gvariant-text-format.html).
2518
 *
2519
 * The memory at @limit will never be accessed and the parser behaves as
2520
 * if the character at @limit is the nul terminator.  This has the
2521
 * effect of bounding @text.
2522
 *
2523
 * If @endptr is non-%NULL then @text is permitted to contain data
2524
 * following the value that this function parses and @endptr will be
2525
 * updated to point to the first character past the end of the text
2526
 * parsed by this function.  If @endptr is %NULL and there is extra data
2527
 * then an error is returned.
2528
 *
2529
 * If @type is non-%NULL then the value will be parsed to have that
2530
 * type.  This may result in additional parse errors (in the case that
2531
 * the parsed value doesn't fit the type) but may also result in fewer
2532
 * errors (in the case that the type would have been ambiguous, such as
2533
 * with empty arrays).
2534
 *
2535
 * In the event that the parsing is successful, the resulting #GVariant
2536
 * is returned. It is never floating, and must be freed with
2537
 * [method@GLib.Variant.unref].
2538
 *
2539
 * In case of any error, %NULL will be returned.  If @error is non-%NULL
2540
 * then it will be set to reflect the error that occurred.
2541
 *
2542
 * Officially, the language understood by the parser is “any string
2543
 * produced by [method@GLib.Variant.print]”. This explicitly includes
2544
 * `g_variant_print()`’s annotated types like `int64 -1000`.
2545
 *
2546
 * There may be implementation specific restrictions on deeply nested values,
2547
 * which would result in a %G_VARIANT_PARSE_ERROR_RECURSION error. #GVariant is
2548
 * guaranteed to handle nesting up to at least 64 levels.
2549
 *
2550
 * Returns: a non-floating reference to a #GVariant, or %NULL
2551
 **/
2552
GVariant *
2553
g_variant_parse (const GVariantType  *type,
2554
                 const gchar         *text,
2555
                 const gchar         *limit,
2556
                 const gchar        **endptr,
2557
                 GError             **error)
2558
0
{
2559
0
  TokenStream stream = { 0, };
2560
0
  GVariant *result = NULL;
2561
0
  AST *ast;
2562
2563
0
  g_return_val_if_fail (text != NULL, NULL);
2564
0
  g_return_val_if_fail (text == limit || text != NULL, NULL);
2565
2566
0
  stream.start = text;
2567
0
  stream.stream = text;
2568
0
  stream.end = limit;
2569
2570
0
  if ((ast = parse (&stream, G_VARIANT_MAX_RECURSION_DEPTH, NULL, error)))
2571
0
    {
2572
0
      if (type == NULL)
2573
0
        result = ast_resolve (ast, error);
2574
0
      else
2575
0
        result = ast_get_value (ast, type, error);
2576
2577
0
      if (result != NULL)
2578
0
        {
2579
0
          g_variant_ref_sink (result);
2580
2581
0
          if (endptr == NULL)
2582
0
            {
2583
0
              while (stream.stream != limit &&
2584
0
                     g_ascii_isspace (*stream.stream))
2585
0
                stream.stream++;
2586
2587
0
              if (stream.stream != limit && *stream.stream != '\0')
2588
0
                {
2589
0
                  SourceRef ref = { stream.stream - text,
2590
0
                                    stream.stream - text };
2591
2592
0
                  parser_set_error (error, &ref, NULL,
2593
0
                                    G_VARIANT_PARSE_ERROR_INPUT_NOT_AT_END,
2594
0
                                    "expected end of input");
2595
0
                  g_variant_unref (result);
2596
2597
0
                  result = NULL;
2598
0
                }
2599
0
            }
2600
0
          else
2601
0
            *endptr = stream.stream;
2602
0
        }
2603
2604
0
      ast_free (ast);
2605
0
    }
2606
2607
0
  return result;
2608
0
}
2609
2610
/**
2611
 * g_variant_new_parsed_va:
2612
 * @format: a text format #GVariant
2613
 * @app: a pointer to a #va_list
2614
 *
2615
 * Parses @format and returns the result.
2616
 *
2617
 * This is the version of g_variant_new_parsed() intended to be used
2618
 * from libraries.
2619
 *
2620
 * The return value will be floating if it was a newly created GVariant
2621
 * instance.  In the case that @format simply specified the collection
2622
 * of a #GVariant pointer (eg: @format was "%*") then the collected
2623
 * #GVariant pointer will be returned unmodified, without adding any
2624
 * additional references.
2625
 *
2626
 * Note that the arguments in @app must be of the correct width for their types
2627
 * specified in @format when collected into the #va_list. See
2628
 * the [GVariant varargs documentation](gvariant-format-strings.html#varargs).
2629
 *
2630
 * In order to behave correctly in all cases it is necessary for the
2631
 * calling function to g_variant_ref_sink() the return result before
2632
 * returning control to the user that originally provided the pointer.
2633
 * At this point, the caller will have their own full reference to the
2634
 * result.  This can also be done by adding the result to a container,
2635
 * or by passing it to another g_variant_new() call.
2636
 *
2637
 * Returns: a new, usually floating, #GVariant
2638
 **/
2639
GVariant *
2640
g_variant_new_parsed_va (const gchar *format,
2641
                         va_list     *app)
2642
0
{
2643
0
  TokenStream stream = { 0, };
2644
0
  GVariant *result = NULL;
2645
0
  GError *error = NULL;
2646
0
  AST *ast;
2647
2648
0
  g_return_val_if_fail (format != NULL, NULL);
2649
0
  g_return_val_if_fail (app != NULL, NULL);
2650
2651
0
  stream.start = format;
2652
0
  stream.stream = format;
2653
0
  stream.end = NULL;
2654
2655
0
  if ((ast = parse (&stream, G_VARIANT_MAX_RECURSION_DEPTH, app, &error)))
2656
0
    {
2657
0
      result = ast_resolve (ast, &error);
2658
0
      ast_free (ast);
2659
0
    }
2660
2661
0
  if (error != NULL)
2662
0
    g_error ("g_variant_new_parsed: %s", error->message);
2663
2664
0
  if (*stream.stream)
2665
0
    g_error ("g_variant_new_parsed: trailing text after value");
2666
2667
0
  g_clear_error (&error);
2668
2669
0
  return result;
2670
0
}
2671
2672
/**
2673
 * g_variant_new_parsed:
2674
 * @format: a text format #GVariant
2675
 * @...: arguments as per @format
2676
 *
2677
 * Parses @format and returns the result.
2678
 *
2679
 * @format must be a text format #GVariant with one extension: at any
2680
 * point that a value may appear in the text, a '%' character followed
2681
 * by a GVariant format string (as per g_variant_new()) may appear.  In
2682
 * that case, the same arguments are collected from the argument list as
2683
 * g_variant_new() would have collected.
2684
 *
2685
 * Note that the arguments must be of the correct width for their types
2686
 * specified in @format. This can be achieved by casting them. See
2687
 * the [GVariant varargs documentation](gvariant-format-strings.html#varargs).
2688
 *
2689
 * Consider this simple example:
2690
 * |[<!-- language="C" --> 
2691
 *  g_variant_new_parsed ("[('one', 1), ('two', %i), (%s, 3)]", 2, "three");
2692
 * ]|
2693
 *
2694
 * In the example, the variable argument parameters are collected and
2695
 * filled in as if they were part of the original string to produce the
2696
 * result of
2697
 * |[<!-- language="C" --> 
2698
 * [('one', 1), ('two', 2), ('three', 3)]
2699
 * ]|
2700
 *
2701
 * This function is intended only to be used with @format as a string
2702
 * literal.  Any parse error is fatal to the calling process.  If you
2703
 * want to parse data from untrusted sources, use g_variant_parse().
2704
 *
2705
 * You may not use this function to return, unmodified, a single
2706
 * #GVariant pointer from the argument list.  ie: @format may not solely
2707
 * be anything along the lines of "%*", "%?", "\%r", or anything starting
2708
 * with "%@".
2709
 *
2710
 * Returns: a new floating #GVariant instance
2711
 **/
2712
GVariant *
2713
g_variant_new_parsed (const gchar *format,
2714
                      ...)
2715
0
{
2716
0
  GVariant *result;
2717
0
  va_list ap;
2718
2719
0
  va_start (ap, format);
2720
0
  result = g_variant_new_parsed_va (format, &ap);
2721
0
  va_end (ap);
2722
2723
0
  return result;
2724
0
}
2725
2726
/**
2727
 * g_variant_builder_add_parsed:
2728
 * @builder: a #GVariantBuilder
2729
 * @format: a text format #GVariant
2730
 * @...: arguments as per @format
2731
 *
2732
 * Adds to a #GVariantBuilder.
2733
 *
2734
 * This call is a convenience wrapper that is exactly equivalent to
2735
 * calling g_variant_new_parsed() followed by
2736
 * g_variant_builder_add_value().
2737
 *
2738
 * Note that the arguments must be of the correct width for their types
2739
 * specified in @format_string. This can be achieved by casting them. See
2740
 * the [GVariant varargs documentation](gvariant-format-strings.html#varargs).
2741
 *
2742
 * This function might be used as follows:
2743
 *
2744
 * |[<!-- language="C" --> 
2745
 * GVariant *
2746
 * make_pointless_dictionary (void)
2747
 * {
2748
 *   GVariantBuilder builder;
2749
 *   int i;
2750
 *
2751
 *   g_variant_builder_init_static (&builder, G_VARIANT_TYPE_ARRAY);
2752
 *   g_variant_builder_add_parsed (&builder, "{'width', <%i>}", 600);
2753
 *   g_variant_builder_add_parsed (&builder, "{'title', <%s>}", "foo");
2754
 *   g_variant_builder_add_parsed (&builder, "{'transparency', <0.5>}");
2755
 *   return g_variant_builder_end (&builder);
2756
 * }
2757
 * ]|
2758
 *
2759
 * Since: 2.26
2760
 */
2761
void
2762
g_variant_builder_add_parsed (GVariantBuilder *builder,
2763
                              const gchar     *format,
2764
                              ...)
2765
0
{
2766
0
  va_list ap;
2767
2768
0
  va_start (ap, format);
2769
0
  g_variant_builder_add_value (builder, g_variant_new_parsed_va (format, &ap));
2770
0
  va_end (ap);
2771
0
}
2772
2773
static gboolean
2774
parse_num (const gchar *num,
2775
           const gchar *limit,
2776
           size_t      *result)
2777
0
{
2778
0
  gchar *endptr;
2779
0
  gint64 bignum;
2780
2781
0
  bignum = g_ascii_strtoll (num, &endptr, 10);
2782
2783
0
  if (endptr != limit)
2784
0
    return FALSE;
2785
2786
  /* The upper bound here is more restrictive than it technically needs to be,
2787
   * but should be enough for any practical situation: */
2788
0
  if (bignum < 0 || bignum > G_MAXINT)
2789
0
    return FALSE;
2790
2791
0
  *result = (size_t) bignum;
2792
2793
0
  return TRUE;
2794
0
}
2795
2796
static void
2797
add_last_line (GString     *err,
2798
               const gchar *str)
2799
0
{
2800
0
  const gchar *last_nl;
2801
0
  gchar *chomped;
2802
0
  size_t i;
2803
2804
  /* This is an error at the end of input.  If we have a file
2805
   * with newlines, that's probably the empty string after the
2806
   * last newline, which is not the most useful thing to show.
2807
   *
2808
   * Instead, show the last line of non-whitespace that we have
2809
   * and put the pointer at the end of it.
2810
   */
2811
0
  chomped = g_strchomp (g_strdup (str));
2812
0
  last_nl = strrchr (chomped, '\n');
2813
0
  if (last_nl == NULL)
2814
0
    last_nl = chomped;
2815
0
  else
2816
0
    last_nl++;
2817
2818
  /* Print the last line like so:
2819
   *
2820
   *   [1, 2, 3,
2821
   *            ^
2822
   */
2823
0
  g_string_append (err, "  ");
2824
0
  if (last_nl[0])
2825
0
    g_string_append (err, last_nl);
2826
0
  else
2827
0
    g_string_append (err, "(empty input)");
2828
0
  g_string_append (err, "\n  ");
2829
0
  for (i = 0; last_nl[i]; i++)
2830
0
    g_string_append_c (err, ' ');
2831
0
  g_string_append (err, "^\n");
2832
0
  g_free (chomped);
2833
0
}
2834
2835
static void
2836
add_lines_from_range (GString     *err,
2837
                      const gchar *str,
2838
                      const gchar *start1,
2839
                      const gchar *end1,
2840
                      const gchar *start2,
2841
                      const gchar *end2)
2842
0
{
2843
0
  while (str < end1 || str < end2)
2844
0
    {
2845
0
      const gchar *nl;
2846
2847
0
      nl = str + strcspn (str, "\n");
2848
2849
0
      if ((start1 < nl && str < end1) || (start2 < nl && str < end2))
2850
0
        {
2851
0
          const gchar *s;
2852
2853
          /* We're going to print this line */
2854
0
          g_string_append (err, "  ");
2855
0
          g_string_append_len (err, str, nl - str);
2856
0
          g_string_append (err, "\n  ");
2857
2858
          /* And add underlines... */
2859
0
          for (s = str; s < nl; s++)
2860
0
            {
2861
0
              if ((start1 <= s && s < end1) || (start2 <= s && s < end2))
2862
0
                g_string_append_c (err, '^');
2863
0
              else
2864
0
                g_string_append_c (err, ' ');
2865
0
            }
2866
0
          g_string_append_c (err, '\n');
2867
0
        }
2868
2869
0
      if (!*nl)
2870
0
        break;
2871
2872
0
      str = nl + 1;
2873
0
    }
2874
0
}
2875
2876
/**
2877
 * g_variant_parse_error_print_context:
2878
 * @error: a #GError from the #GVariantParseError domain
2879
 * @source_str: the string that was given to the parser
2880
 *
2881
 * Pretty-prints a message showing the context of a #GVariant parse
2882
 * error within the string for which parsing was attempted.
2883
 *
2884
 * The resulting string is suitable for output to the console or other
2885
 * monospace media where newlines are treated in the usual way.
2886
 *
2887
 * The message will typically look something like one of the following:
2888
 *
2889
 * |[
2890
 * unterminated string constant:
2891
 *   (1, 2, 3, 'abc
2892
 *             ^^^^
2893
 * ]|
2894
 *
2895
 * or
2896
 *
2897
 * |[
2898
 * unable to find a common type:
2899
 *   [1, 2, 3, 'str']
2900
 *    ^        ^^^^^
2901
 * ]|
2902
 *
2903
 * The format of the message may change in a future version.
2904
 *
2905
 * @error must have come from a failed attempt to g_variant_parse() and
2906
 * @source_str must be exactly the same string that caused the error.
2907
 * If @source_str was not nul-terminated when you passed it to
2908
 * g_variant_parse() then you must add nul termination before using this
2909
 * function.
2910
 *
2911
 * Returns: (transfer full): the printed message
2912
 *
2913
 * Since: 2.40
2914
 **/
2915
gchar *
2916
g_variant_parse_error_print_context (GError      *error,
2917
                                     const gchar *source_str)
2918
0
{
2919
0
  const gchar *colon, *dash, *comma;
2920
0
  gboolean success = FALSE;
2921
0
  GString *err;
2922
2923
0
  g_return_val_if_fail (error->domain == G_VARIANT_PARSE_ERROR, FALSE);
2924
2925
  /* We can only have a limited number of possible types of ranges
2926
   * emitted from the parser:
2927
   *
2928
   *  - a:          -- usually errors from the tokeniser (eof, invalid char, etc.)
2929
   *  - a-b:        -- usually errors from handling one single token
2930
   *  - a-b,c-d:    -- errors involving two tokens (ie: type inferencing)
2931
   *
2932
   * We never see, for example "a,c".
2933
   */
2934
2935
0
  colon = strchr (error->message, ':');
2936
0
  dash = strchr (error->message, '-');
2937
0
  comma = strchr (error->message, ',');
2938
2939
0
  if (!colon)
2940
0
    return NULL;
2941
2942
0
  err = g_string_new (colon + 1);
2943
0
  g_string_append (err, ":\n");
2944
2945
0
  if (dash == NULL || colon < dash)
2946
0
    {
2947
0
      size_t point;
2948
2949
      /* we have a single point */
2950
0
      if (!parse_num (error->message, colon, &point))
2951
0
        goto out;
2952
2953
0
      if (point >= strlen (source_str))
2954
        /* the error is at the end of the input */
2955
0
        add_last_line (err, source_str);
2956
0
      else
2957
        /* otherwise just treat it as an error at a thin range */
2958
0
        add_lines_from_range (err, source_str, source_str + point, source_str + point + 1, NULL, NULL);
2959
0
    }
2960
0
  else
2961
0
    {
2962
      /* We have one or two ranges... */
2963
0
      if (comma && comma < colon)
2964
0
        {
2965
0
          size_t start1, end1, start2, end2;
2966
0
          const gchar *dash2;
2967
2968
          /* Two ranges */
2969
0
          dash2 = strchr (comma, '-');
2970
2971
0
          if (!parse_num (error->message, dash, &start1) || !parse_num (dash + 1, comma, &end1) ||
2972
0
              !parse_num (comma + 1, dash2, &start2) || !parse_num (dash2 + 1, colon, &end2))
2973
0
            goto out;
2974
2975
0
          add_lines_from_range (err, source_str,
2976
0
                                source_str + start1, source_str + end1,
2977
0
                                source_str + start2, source_str + end2);
2978
0
        }
2979
0
      else
2980
0
        {
2981
0
          size_t start, end;
2982
2983
          /* One range */
2984
0
          if (!parse_num (error->message, dash, &start) || !parse_num (dash + 1, colon, &end))
2985
0
            goto out;
2986
2987
0
          add_lines_from_range (err, source_str, source_str + start, source_str + end, NULL, NULL);
2988
0
        }
2989
0
    }
2990
2991
0
  success = TRUE;
2992
2993
0
out:
2994
0
  return g_string_free (err, !success);
2995
0
}