1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <errno.h>
4 #include <locale.h>
5 #include <math.h>
6 #include <stdarg.h>
7 #include <stdlib.h>
8 #include <sys/types.h>
9 
10 #include "sd-messages.h"
11 
12 #include "alloc-util.h"
13 #include "errno-util.h"
14 #include "fd-util.h"
15 #include "fileio.h"
16 #include "float.h"
17 #include "hexdecoct.h"
18 #include "json-internal.h"
19 #include "json.h"
20 #include "macro.h"
21 #include "memory-util.h"
22 #include "string-table.h"
23 #include "string-util.h"
24 #include "strv.h"
25 #include "terminal-util.h"
26 #include "user-util.h"
27 #include "utf8.h"
28 
29 /* Refuse putting together variants with a larger depth than 2K by default (as a protection against overflowing stacks
30  * if code processes JSON objects recursively. Note that we store the depth in an uint16_t, hence make sure this
31  * remains under 2^16.
32  *
33  * The value first was 16k, but it was discovered to be too high on llvm/x86-64. See also:
34  * https://github.com/systemd/systemd/issues/10738
35  *
36  * The value then was 4k, but it was discovered to be too high on s390x/aarch64. See also:
37  * https://github.com/systemd/systemd/issues/14396 */
38 
39 #define DEPTH_MAX (2U*1024U)
40 assert_cc(DEPTH_MAX <= UINT16_MAX);
41 
42 typedef struct JsonSource {
43         /* When we parse from a file or similar, encodes the filename, to indicate the source of a json variant */
44         unsigned n_ref;
45         unsigned max_line;
46         unsigned max_column;
47         char name[];
48 } JsonSource;
49 
50 /* On x86-64 this whole structure should have a size of 6 * 64 bit = 48 bytes */
51 struct JsonVariant {
52         union {
53                 /* We either maintain a reference counter for this variant itself, or we are embedded into an
54                  * array/object, in which case only that surrounding object is ref-counted. (If 'embedded' is false,
55                  * see below.) */
56                 unsigned n_ref;
57 
58                 /* If this JsonVariant is part of an array/object, then this field points to the surrounding
59                  * JSON_VARIANT_ARRAY/JSON_VARIANT_OBJECT object. (If 'embedded' is true, see below.) */
60                 JsonVariant *parent;
61         };
62 
63         /* If this was parsed from some file or buffer, this stores where from, as well as the source line/column */
64         JsonSource *source;
65         unsigned line, column;
66 
67         /* The current 'depth' of the JsonVariant, i.e. how many levels of member variants this has */
68         uint16_t depth;
69 
70         JsonVariantType type:8;
71 
72         /* A marker whether this variant is embedded into in array/object or not. If true, the 'parent' pointer above
73          * is valid. If false, the 'n_ref' field above is valid instead. */
74         bool is_embedded:1;
75 
76         /* In some conditions (for example, if this object is part of an array of strings or objects), we don't store
77          * any data inline, but instead simply reference an external object and act as surrogate of it. In that case
78          * this bool is set, and the external object is referenced through the .reference field below. */
79         bool is_reference:1;
80 
81         /* While comparing two arrays, we use this for marking what we already have seen */
82         bool is_marked:1;
83 
84         /* Erase from memory when freeing */
85         bool sensitive:1;
86 
87         /* If this is an object the fields are strictly ordered by name */
88         bool sorted:1;
89 
90         /* If in addition to this object all objects referenced by it are also ordered strictly by name */
91         bool normalized:1;
92 
93         union {
94                 /* For simple types we store the value in-line. */
95                 JsonValue value;
96 
97                 /* For objects and arrays we store the number of elements immediately following */
98                 size_t n_elements;
99 
100                 /* If is_reference as indicated above is set, this is where the reference object is actually stored. */
101                 JsonVariant *reference;
102 
103                 /* Strings are placed immediately after the structure. Note that when this is a JsonVariant embedded
104                  * into an array we might encode strings up to INLINE_STRING_LENGTH characters directly inside the
105                  * element, while longer strings are stored as references. When this object is not embedded into an
106                  * array, but stand-alone we allocate the right size for the whole structure, i.e. the array might be
107                  * much larger than INLINE_STRING_LENGTH.
108                  *
109                  * Note that because we want to allocate arrays of the JsonVariant structure we specify [0] here,
110                  * rather than the prettier []. If we wouldn't, then this char array would have undefined size, and so
111                  * would the union and then the struct this is included in. And of structures with undefined size we
112                  * can't allocate arrays (at least not easily). */
113                 char string[0];
114         };
115 };
116 
117 /* Inside string arrays we have a series of JsonVariant structures one after the other. In this case, strings longer
118  * than INLINE_STRING_MAX are stored as references, and all shorter ones inline. (This means — on x86-64 — strings up
119  * to 7 chars are stored within the array elements, and all others in separate allocations) */
120 #define INLINE_STRING_MAX (sizeof(JsonVariant) - offsetof(JsonVariant, string) - 1U)
121 
122 /* Let's make sure this structure isn't increased in size accidentally. This check is only for our most relevant arch
123  * (x86-64). */
124 #if defined(__x86_64__) && __SIZEOF_POINTER__ == 8
125 assert_cc(sizeof(JsonVariant) == 40U);
126 assert_cc(INLINE_STRING_MAX == 7U);
127 #endif
128 
json_source_new(const char * name)129 static JsonSource* json_source_new(const char *name) {
130         JsonSource *s;
131 
132         assert(name);
133 
134         s = malloc(offsetof(JsonSource, name) + strlen(name) + 1);
135         if (!s)
136                 return NULL;
137 
138         *s = (JsonSource) {
139                 .n_ref = 1,
140         };
141         strcpy(s->name, name);
142 
143         return s;
144 }
145 
146 DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(JsonSource, json_source, mfree);
147 
json_source_equal(JsonSource * a,JsonSource * b)148 static bool json_source_equal(JsonSource *a, JsonSource *b) {
149         if (a == b)
150                 return true;
151 
152         if (!a || !b)
153                 return false;
154 
155         return streq(a->name, b->name);
156 }
157 
158 DEFINE_TRIVIAL_CLEANUP_FUNC(JsonSource*, json_source_unref);
159 
160 /* There are four kind of JsonVariant* pointers:
161  *
162  *    1. NULL
163  *    2. A 'regular' one, i.e. pointing to malloc() memory
164  *    3. A 'magic' one, i.e. one of the special JSON_VARIANT_MAGIC_XYZ values, that encode a few very basic values directly in the pointer.
165  *    4. A 'const string' one, i.e. a pointer to a const string.
166  *
167  * The four kinds of pointers can be discerned like this:
168  *
169  *    Detecting #1 is easy, just compare with NULL. Detecting #3 is similarly easy: all magic pointers are below
170  *    _JSON_VARIANT_MAGIC_MAX (which is pretty low, within the first memory page, which is special on Linux and other
171  *    OSes, as it is a faulting page). In order to discern #2 and #4 we check the lowest bit. If it's off it's #2,
172  *    otherwise #4. This makes use of the fact that malloc() will return "maximum aligned" memory, which definitely
173  *    means the pointer is even. This means we can use the uneven pointers to reference static strings, as long as we
174  *    make sure that all static strings used like this are aligned to 2 (or higher), and that we mask the bit on
175  *    access. The JSON_VARIANT_STRING_CONST() macro encodes strings as JsonVariant* pointers, with the bit set. */
176 
json_variant_is_magic(const JsonVariant * v)177 static bool json_variant_is_magic(const JsonVariant *v) {
178         if (!v)
179                 return false;
180 
181         return v < _JSON_VARIANT_MAGIC_MAX;
182 }
183 
json_variant_is_const_string(const JsonVariant * v)184 static bool json_variant_is_const_string(const JsonVariant *v) {
185 
186         if (v < _JSON_VARIANT_MAGIC_MAX)
187                 return false;
188 
189         /* A proper JsonVariant is aligned to whatever malloc() aligns things too, which is definitely not uneven. We
190          * hence use all uneven pointers as indicators for const strings. */
191 
192         return (((uintptr_t) v) & 1) != 0;
193 }
194 
json_variant_is_regular(const JsonVariant * v)195 static bool json_variant_is_regular(const JsonVariant *v) {
196 
197         if (v < _JSON_VARIANT_MAGIC_MAX)
198                 return false;
199 
200         return (((uintptr_t) v) & 1) == 0;
201 }
202 
json_variant_dereference(JsonVariant * v)203 static JsonVariant *json_variant_dereference(JsonVariant *v) {
204 
205         /* Recursively dereference variants that are references to other variants */
206 
207         if (!v)
208                 return NULL;
209 
210         if (!json_variant_is_regular(v))
211                 return v;
212 
213         if (!v->is_reference)
214                 return v;
215 
216         return json_variant_dereference(v->reference);
217 }
218 
json_variant_depth(JsonVariant * v)219 static uint16_t json_variant_depth(JsonVariant *v) {
220 
221         v = json_variant_dereference(v);
222         if (!v)
223                 return 0;
224 
225         if (!json_variant_is_regular(v))
226                 return 0;
227 
228         return v->depth;
229 }
230 
json_variant_formalize(JsonVariant * v)231 static JsonVariant *json_variant_formalize(JsonVariant *v) {
232 
233         /* Converts json variant pointers to their normalized form, i.e. fully dereferenced and wherever
234          * possible converted to the "magic" version if there is one */
235 
236         if (!v)
237                 return NULL;
238 
239         v = json_variant_dereference(v);
240 
241         switch (json_variant_type(v)) {
242 
243         case JSON_VARIANT_BOOLEAN:
244                 return json_variant_boolean(v) ? JSON_VARIANT_MAGIC_TRUE : JSON_VARIANT_MAGIC_FALSE;
245 
246         case JSON_VARIANT_NULL:
247                 return JSON_VARIANT_MAGIC_NULL;
248 
249         case JSON_VARIANT_INTEGER:
250                 return json_variant_integer(v) == 0 ? JSON_VARIANT_MAGIC_ZERO_INTEGER : v;
251 
252         case JSON_VARIANT_UNSIGNED:
253                 return json_variant_unsigned(v) == 0 ? JSON_VARIANT_MAGIC_ZERO_UNSIGNED : v;
254 
255         case JSON_VARIANT_REAL:
256                 DISABLE_WARNING_FLOAT_EQUAL;
257                 return json_variant_real(v) == 0.0 ? JSON_VARIANT_MAGIC_ZERO_REAL : v;
258                 REENABLE_WARNING;
259 
260         case JSON_VARIANT_STRING:
261                 return isempty(json_variant_string(v)) ? JSON_VARIANT_MAGIC_EMPTY_STRING : v;
262 
263         case JSON_VARIANT_ARRAY:
264                 return json_variant_elements(v) == 0 ? JSON_VARIANT_MAGIC_EMPTY_ARRAY : v;
265 
266         case JSON_VARIANT_OBJECT:
267                 return json_variant_elements(v) == 0 ? JSON_VARIANT_MAGIC_EMPTY_OBJECT : v;
268 
269         default:
270                 return v;
271         }
272 }
273 
json_variant_conservative_formalize(JsonVariant * v)274 static JsonVariant *json_variant_conservative_formalize(JsonVariant *v) {
275 
276         /* Much like json_variant_formalize(), but won't simplify if the variant has a source/line location
277          * attached to it, in order not to lose context */
278 
279         if (!v)
280                 return NULL;
281 
282         if (!json_variant_is_regular(v))
283                 return v;
284 
285         if (v->source || v->line > 0 || v->column > 0)
286                 return v;
287 
288         return json_variant_formalize(v);
289 }
290 
json_variant_new(JsonVariant ** ret,JsonVariantType type,size_t space)291 static int json_variant_new(JsonVariant **ret, JsonVariantType type, size_t space) {
292         JsonVariant *v;
293 
294         assert_return(ret, -EINVAL);
295 
296         v = malloc0(MAX(sizeof(JsonVariant),
297                         offsetof(JsonVariant, value) + space));
298         if (!v)
299                 return -ENOMEM;
300 
301         v->n_ref = 1;
302         v->type = type;
303 
304         *ret = v;
305         return 0;
306 }
307 
json_variant_new_integer(JsonVariant ** ret,int64_t i)308 int json_variant_new_integer(JsonVariant **ret, int64_t i) {
309         JsonVariant *v;
310         int r;
311 
312         assert_return(ret, -EINVAL);
313 
314         if (i == 0) {
315                 *ret = JSON_VARIANT_MAGIC_ZERO_INTEGER;
316                 return 0;
317         }
318 
319         r = json_variant_new(&v, JSON_VARIANT_INTEGER, sizeof(i));
320         if (r < 0)
321                 return r;
322 
323         v->value.integer = i;
324         *ret = v;
325 
326         return 0;
327 }
328 
json_variant_new_unsigned(JsonVariant ** ret,uint64_t u)329 int json_variant_new_unsigned(JsonVariant **ret, uint64_t u) {
330         JsonVariant *v;
331         int r;
332 
333         assert_return(ret, -EINVAL);
334         if (u == 0) {
335                 *ret = JSON_VARIANT_MAGIC_ZERO_UNSIGNED;
336                 return 0;
337         }
338 
339         r = json_variant_new(&v, JSON_VARIANT_UNSIGNED, sizeof(u));
340         if (r < 0)
341                 return r;
342 
343         v->value.unsig = u;
344         *ret = v;
345 
346         return 0;
347 }
348 
json_variant_new_real(JsonVariant ** ret,double d)349 int json_variant_new_real(JsonVariant **ret, double d) {
350         JsonVariant *v;
351         int r;
352 
353         assert_return(ret, -EINVAL);
354 
355         DISABLE_WARNING_FLOAT_EQUAL;
356         if (d == 0.0) {
357                 *ret = JSON_VARIANT_MAGIC_ZERO_REAL;
358                 return 0;
359         }
360         REENABLE_WARNING;
361 
362         /* JSON doesn't know NaN, +Infinity or -Infinity. Let's silently convert to 'null'. */
363         if (isnan(d) || isinf(d)) {
364                 *ret = JSON_VARIANT_MAGIC_NULL;
365                 return 0;
366         }
367 
368         r = json_variant_new(&v, JSON_VARIANT_REAL, sizeof(d));
369         if (r < 0)
370                 return r;
371 
372         v->value.real = d;
373         *ret = v;
374 
375         return 0;
376 }
377 
json_variant_new_boolean(JsonVariant ** ret,bool b)378 int json_variant_new_boolean(JsonVariant **ret, bool b) {
379         assert_return(ret, -EINVAL);
380 
381         if (b)
382                 *ret = JSON_VARIANT_MAGIC_TRUE;
383         else
384                 *ret = JSON_VARIANT_MAGIC_FALSE;
385 
386         return 0;
387 }
388 
json_variant_new_null(JsonVariant ** ret)389 int json_variant_new_null(JsonVariant **ret) {
390         assert_return(ret, -EINVAL);
391 
392         *ret = JSON_VARIANT_MAGIC_NULL;
393         return 0;
394 }
395 
json_variant_new_stringn(JsonVariant ** ret,const char * s,size_t n)396 int json_variant_new_stringn(JsonVariant **ret, const char *s, size_t n) {
397         JsonVariant *v;
398         int r;
399 
400         assert_return(ret, -EINVAL);
401         if (!s) {
402                 assert_return(IN_SET(n, 0, SIZE_MAX), -EINVAL);
403                 return json_variant_new_null(ret);
404         }
405         if (n == SIZE_MAX) /* determine length automatically */
406                 n = strlen(s);
407         else if (memchr(s, 0, n)) /* don't allow embedded NUL, as we can't express that in JSON */
408                 return -EINVAL;
409         if (n == 0) {
410                 *ret = JSON_VARIANT_MAGIC_EMPTY_STRING;
411                 return 0;
412         }
413 
414         if (!utf8_is_valid_n(s, n)) /* JSON strings must be valid UTF-8 */
415                 return -EUCLEAN;
416 
417         r = json_variant_new(&v, JSON_VARIANT_STRING, n + 1);
418         if (r < 0)
419                 return r;
420 
421         memcpy(v->string, s, n);
422         v->string[n] = 0;
423 
424         *ret = v;
425         return 0;
426 }
427 
json_variant_new_base64(JsonVariant ** ret,const void * p,size_t n)428 int json_variant_new_base64(JsonVariant **ret, const void *p, size_t n) {
429         _cleanup_free_ char *s = NULL;
430         ssize_t k;
431 
432         assert_return(ret, -EINVAL);
433         assert_return(n == 0 || p, -EINVAL);
434 
435         k = base64mem(p, n, &s);
436         if (k < 0)
437                 return k;
438 
439         return json_variant_new_stringn(ret, s, k);
440 }
441 
json_variant_new_hex(JsonVariant ** ret,const void * p,size_t n)442 int json_variant_new_hex(JsonVariant **ret, const void *p, size_t n) {
443         _cleanup_free_ char *s = NULL;
444 
445         assert_return(ret, -EINVAL);
446         assert_return(n == 0 || p, -EINVAL);
447 
448         s = hexmem(p, n);
449         if (!s)
450                 return -ENOMEM;
451 
452         return json_variant_new_stringn(ret, s, n*2);
453 }
454 
json_variant_new_id128(JsonVariant ** ret,sd_id128_t id)455 int json_variant_new_id128(JsonVariant **ret, sd_id128_t id) {
456         return json_variant_new_string(ret, SD_ID128_TO_STRING(id));
457 }
458 
json_variant_set(JsonVariant * a,JsonVariant * b)459 static void json_variant_set(JsonVariant *a, JsonVariant *b) {
460         assert(a);
461 
462         b = json_variant_dereference(b);
463         if (!b) {
464                 a->type = JSON_VARIANT_NULL;
465                 return;
466         }
467 
468         a->type = json_variant_type(b);
469         switch (a->type) {
470 
471         case JSON_VARIANT_INTEGER:
472                 a->value.integer = json_variant_integer(b);
473                 break;
474 
475         case JSON_VARIANT_UNSIGNED:
476                 a->value.unsig = json_variant_unsigned(b);
477                 break;
478 
479         case JSON_VARIANT_REAL:
480                 a->value.real = json_variant_real(b);
481                 break;
482 
483         case JSON_VARIANT_BOOLEAN:
484                 a->value.boolean = json_variant_boolean(b);
485                 break;
486 
487         case JSON_VARIANT_STRING: {
488                 const char *s;
489 
490                 assert_se(s = json_variant_string(b));
491 
492                 /* Short strings we can store inline */
493                 if (strnlen(s, INLINE_STRING_MAX+1) <= INLINE_STRING_MAX) {
494                         strcpy(a->string, s);
495                         break;
496                 }
497 
498                 /* For longer strings, use a reference… */
499                 _fallthrough_;
500         }
501 
502         case JSON_VARIANT_ARRAY:
503         case JSON_VARIANT_OBJECT:
504                 a->is_reference = true;
505                 a->reference = json_variant_ref(json_variant_conservative_formalize(b));
506                 break;
507 
508         case JSON_VARIANT_NULL:
509                 break;
510 
511         default:
512                 assert_not_reached();
513         }
514 }
515 
json_variant_copy_source(JsonVariant * v,JsonVariant * from)516 static void json_variant_copy_source(JsonVariant *v, JsonVariant *from) {
517         assert(v);
518 
519         if (!json_variant_is_regular(from))
520                 return;
521 
522         v->line = from->line;
523         v->column = from->column;
524         v->source = json_source_ref(from->source);
525 }
526 
json_variant_new_array(JsonVariant ** ret,JsonVariant ** array,size_t n)527 int json_variant_new_array(JsonVariant **ret, JsonVariant **array, size_t n) {
528         _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
529         bool normalized = true;
530 
531         assert_return(ret, -EINVAL);
532         if (n == 0) {
533                 *ret = JSON_VARIANT_MAGIC_EMPTY_ARRAY;
534                 return 0;
535         }
536         assert_return(array, -EINVAL);
537 
538         v = new(JsonVariant, n + 1);
539         if (!v)
540                 return -ENOMEM;
541 
542         *v = (JsonVariant) {
543                 .n_ref = 1,
544                 .type = JSON_VARIANT_ARRAY,
545         };
546 
547         for (v->n_elements = 0; v->n_elements < n; v->n_elements++) {
548                 JsonVariant *w = v + 1 + v->n_elements,
549                             *c = array[v->n_elements];
550                 uint16_t d;
551 
552                 d = json_variant_depth(c);
553                 if (d >= DEPTH_MAX) /* Refuse too deep nesting */
554                         return -ELNRNG;
555                 if (d >= v->depth)
556                         v->depth = d + 1;
557 
558                 *w = (JsonVariant) {
559                         .is_embedded = true,
560                         .parent = v,
561                 };
562 
563                 json_variant_set(w, c);
564                 json_variant_copy_source(w, c);
565 
566                 if (!json_variant_is_normalized(c))
567                         normalized = false;
568         }
569 
570         v->normalized = normalized;
571 
572         *ret = TAKE_PTR(v);
573         return 0;
574 }
575 
json_variant_new_array_bytes(JsonVariant ** ret,const void * p,size_t n)576 int json_variant_new_array_bytes(JsonVariant **ret, const void *p, size_t n) {
577         assert_return(ret, -EINVAL);
578         if (n == 0) {
579                 *ret = JSON_VARIANT_MAGIC_EMPTY_ARRAY;
580                 return 0;
581         }
582         assert_return(p, -EINVAL);
583 
584         JsonVariant *v = new(JsonVariant, n + 1);
585         if (!v)
586                 return -ENOMEM;
587 
588         *v = (JsonVariant) {
589                 .n_ref = 1,
590                 .type = JSON_VARIANT_ARRAY,
591                 .n_elements = n,
592                 .depth = 1,
593         };
594 
595         for (size_t i = 0; i < n; i++) {
596                 JsonVariant *w = v + 1 + i;
597 
598                 *w = (JsonVariant) {
599                         .is_embedded = true,
600                         .parent = v,
601                         .type = JSON_VARIANT_UNSIGNED,
602                         .value.unsig = ((const uint8_t*) p)[i],
603                 };
604         }
605 
606         v->normalized = true;
607 
608         *ret = v;
609         return 0;
610 }
611 
json_variant_new_array_strv(JsonVariant ** ret,char ** l)612 int json_variant_new_array_strv(JsonVariant **ret, char **l) {
613         _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
614         size_t n;
615         int r;
616 
617         assert(ret);
618 
619         n = strv_length(l);
620         if (n == 0) {
621                 *ret = JSON_VARIANT_MAGIC_EMPTY_ARRAY;
622                 return 0;
623         }
624 
625         v = new(JsonVariant, n + 1);
626         if (!v)
627                 return -ENOMEM;
628 
629         *v = (JsonVariant) {
630                 .n_ref = 1,
631                 .type = JSON_VARIANT_ARRAY,
632                 .depth = 1,
633         };
634 
635         for (v->n_elements = 0; v->n_elements < n; v->n_elements++) {
636                 JsonVariant *w = v + 1 + v->n_elements;
637                 size_t k;
638 
639                 *w = (JsonVariant) {
640                         .is_embedded = true,
641                         .parent = v,
642                         .type = JSON_VARIANT_STRING,
643                 };
644 
645                 k = strlen(l[v->n_elements]);
646 
647                 if (k > INLINE_STRING_MAX) {
648                         /* If string is too long, store it as reference. */
649 
650                         r = json_variant_new_string(&w->reference, l[v->n_elements]);
651                         if (r < 0)
652                                 return r;
653 
654                         w->is_reference = true;
655                 } else {
656                         if (!utf8_is_valid_n(l[v->n_elements], k)) /* JSON strings must be valid UTF-8 */
657                                 return -EUCLEAN;
658 
659                         memcpy(w->string, l[v->n_elements], k+1);
660                 }
661         }
662 
663         v->normalized = true;
664 
665         *ret = TAKE_PTR(v);
666         return 0;
667 }
668 
json_variant_new_object(JsonVariant ** ret,JsonVariant ** array,size_t n)669 int json_variant_new_object(JsonVariant **ret, JsonVariant **array, size_t n) {
670         _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
671         const char *prev = NULL;
672         bool sorted = true, normalized = true;
673 
674         assert_return(ret, -EINVAL);
675         if (n == 0) {
676                 *ret = JSON_VARIANT_MAGIC_EMPTY_OBJECT;
677                 return 0;
678         }
679         assert_return(array, -EINVAL);
680         assert_return(n % 2 == 0, -EINVAL);
681 
682         v = new(JsonVariant, n + 1);
683         if (!v)
684                 return -ENOMEM;
685 
686         *v = (JsonVariant) {
687                 .n_ref = 1,
688                 .type = JSON_VARIANT_OBJECT,
689         };
690 
691         for (v->n_elements = 0; v->n_elements < n; v->n_elements++) {
692                 JsonVariant *w = v + 1 + v->n_elements,
693                             *c = array[v->n_elements];
694                 uint16_t d;
695 
696                 if ((v->n_elements & 1) == 0) {
697                         const char *k;
698 
699                         if (!json_variant_is_string(c))
700                                 return -EINVAL; /* Every second one needs to be a string, as it is the key name */
701 
702                         assert_se(k = json_variant_string(c));
703 
704                         if (prev && strcmp(k, prev) <= 0)
705                                 sorted = normalized = false;
706 
707                         prev = k;
708                 } else if (!json_variant_is_normalized(c))
709                         normalized = false;
710 
711                 d = json_variant_depth(c);
712                 if (d >= DEPTH_MAX) /* Refuse too deep nesting */
713                         return -ELNRNG;
714                 if (d >= v->depth)
715                         v->depth = d + 1;
716 
717                 *w = (JsonVariant) {
718                         .is_embedded = true,
719                         .parent = v,
720                 };
721 
722                 json_variant_set(w, c);
723                 json_variant_copy_source(w, c);
724         }
725 
726         v->normalized = normalized;
727         v->sorted = sorted;
728 
729         *ret = TAKE_PTR(v);
730         return 0;
731 }
732 
json_variant_size(JsonVariant * v)733 static size_t json_variant_size(JsonVariant* v) {
734         if (!json_variant_is_regular(v))
735                 return 0;
736 
737         if (v->is_reference)
738                 return offsetof(JsonVariant, reference) + sizeof(JsonVariant*);
739 
740         switch (v->type) {
741 
742         case JSON_VARIANT_STRING:
743                 return offsetof(JsonVariant, string) + strlen(v->string) + 1;
744 
745         case JSON_VARIANT_REAL:
746                 return offsetof(JsonVariant, value) + sizeof(double);
747 
748         case JSON_VARIANT_UNSIGNED:
749                 return offsetof(JsonVariant, value) + sizeof(uint64_t);
750 
751         case JSON_VARIANT_INTEGER:
752                 return offsetof(JsonVariant, value) + sizeof(int64_t);
753 
754         case JSON_VARIANT_BOOLEAN:
755                 return offsetof(JsonVariant, value) + sizeof(bool);
756 
757         case JSON_VARIANT_ARRAY:
758         case JSON_VARIANT_OBJECT:
759                 return offsetof(JsonVariant, n_elements) + sizeof(size_t);
760 
761         case JSON_VARIANT_NULL:
762                 return offsetof(JsonVariant, value);
763 
764         default:
765                 assert_not_reached();
766         }
767 }
768 
json_variant_free_inner(JsonVariant * v,bool force_sensitive)769 static void json_variant_free_inner(JsonVariant *v, bool force_sensitive) {
770         bool sensitive;
771 
772         assert(v);
773 
774         if (!json_variant_is_regular(v))
775                 return;
776 
777         json_source_unref(v->source);
778 
779         sensitive = v->sensitive || force_sensitive;
780 
781         if (v->is_reference) {
782                 if (sensitive)
783                         json_variant_sensitive(v->reference);
784 
785                 json_variant_unref(v->reference);
786                 return;
787         }
788 
789         if (IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT))
790                 for (size_t i = 0; i < v->n_elements; i++)
791                         json_variant_free_inner(v + 1 + i, sensitive);
792 
793         if (sensitive)
794                 explicit_bzero_safe(v, json_variant_size(v));
795 }
796 
json_variant_ref(JsonVariant * v)797 JsonVariant *json_variant_ref(JsonVariant *v) {
798         if (!v)
799                 return NULL;
800         if (!json_variant_is_regular(v))
801                 return v;
802 
803         if (v->is_embedded)
804                 json_variant_ref(v->parent); /* ref the compounding variant instead */
805         else {
806                 assert(v->n_ref > 0);
807                 v->n_ref++;
808         }
809 
810         return v;
811 }
812 
json_variant_unref(JsonVariant * v)813 JsonVariant *json_variant_unref(JsonVariant *v) {
814         if (!v)
815                 return NULL;
816         if (!json_variant_is_regular(v))
817                 return NULL;
818 
819         if (v->is_embedded)
820                 json_variant_unref(v->parent);
821         else {
822                 assert(v->n_ref > 0);
823                 v->n_ref--;
824 
825                 if (v->n_ref == 0) {
826                         json_variant_free_inner(v, false);
827                         free(v);
828                 }
829         }
830 
831         return NULL;
832 }
833 
json_variant_unref_many(JsonVariant ** array,size_t n)834 void json_variant_unref_many(JsonVariant **array, size_t n) {
835         assert(array || n == 0);
836 
837         for (size_t i = 0; i < n; i++)
838                 json_variant_unref(array[i]);
839 }
840 
json_variant_string(JsonVariant * v)841 const char *json_variant_string(JsonVariant *v) {
842         if (!v)
843                 return NULL;
844         if (v == JSON_VARIANT_MAGIC_EMPTY_STRING)
845                 return "";
846         if (json_variant_is_magic(v))
847                 goto mismatch;
848         if (json_variant_is_const_string(v)) {
849                 uintptr_t p = (uintptr_t) v;
850 
851                 assert((p & 1) != 0);
852                 return (const char*) (p ^ 1U);
853         }
854 
855         if (v->is_reference)
856                 return json_variant_string(v->reference);
857         if (v->type != JSON_VARIANT_STRING)
858                 goto mismatch;
859 
860         return v->string;
861 
862 mismatch:
863         log_debug("Non-string JSON variant requested as string, returning NULL.");
864         return NULL;
865 }
866 
json_variant_boolean(JsonVariant * v)867 bool json_variant_boolean(JsonVariant *v) {
868         if (!v)
869                 goto mismatch;
870         if (v == JSON_VARIANT_MAGIC_TRUE)
871                 return true;
872         if (v == JSON_VARIANT_MAGIC_FALSE)
873                 return false;
874         if (!json_variant_is_regular(v))
875                 goto mismatch;
876         if (v->type != JSON_VARIANT_BOOLEAN)
877                 goto mismatch;
878         if (v->is_reference)
879                 return json_variant_boolean(v->reference);
880 
881         return v->value.boolean;
882 
883 mismatch:
884         log_debug("Non-boolean JSON variant requested as boolean, returning false.");
885         return false;
886 }
887 
json_variant_integer(JsonVariant * v)888 int64_t json_variant_integer(JsonVariant *v) {
889         if (!v)
890                 goto mismatch;
891         if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER ||
892             v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED ||
893             v == JSON_VARIANT_MAGIC_ZERO_REAL)
894                 return 0;
895         if (!json_variant_is_regular(v))
896                 goto mismatch;
897         if (v->is_reference)
898                 return json_variant_integer(v->reference);
899 
900         switch (v->type) {
901 
902         case JSON_VARIANT_INTEGER:
903                 return v->value.integer;
904 
905         case JSON_VARIANT_UNSIGNED:
906                 if (v->value.unsig <= INT64_MAX)
907                         return (int64_t) v->value.unsig;
908 
909                 log_debug("Unsigned integer %ju requested as signed integer and out of range, returning 0.", v->value.unsig);
910                 return 0;
911 
912         case JSON_VARIANT_REAL: {
913                 int64_t converted;
914 
915                 converted = (int64_t) v->value.real;
916 
917                 DISABLE_WARNING_FLOAT_EQUAL;
918                 if ((double) converted == v->value.real)
919                         return converted;
920                 REENABLE_WARNING;
921 
922                 log_debug("Real %g requested as integer, and cannot be converted losslessly, returning 0.", v->value.real);
923                 return 0;
924         }
925 
926         default:
927                 break;
928         }
929 
930 mismatch:
931         log_debug("Non-integer JSON variant requested as integer, returning 0.");
932         return 0;
933 }
934 
json_variant_unsigned(JsonVariant * v)935 uint64_t json_variant_unsigned(JsonVariant *v) {
936         if (!v)
937                 goto mismatch;
938         if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER ||
939             v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED ||
940             v == JSON_VARIANT_MAGIC_ZERO_REAL)
941                 return 0;
942         if (!json_variant_is_regular(v))
943                 goto mismatch;
944         if (v->is_reference)
945                 return json_variant_integer(v->reference);
946 
947         switch (v->type) {
948 
949         case JSON_VARIANT_INTEGER:
950                 if (v->value.integer >= 0)
951                         return (uint64_t) v->value.integer;
952 
953                 log_debug("Signed integer %ju requested as unsigned integer and out of range, returning 0.", v->value.integer);
954                 return 0;
955 
956         case JSON_VARIANT_UNSIGNED:
957                 return v->value.unsig;
958 
959         case JSON_VARIANT_REAL: {
960                 uint64_t converted;
961 
962                 converted = (uint64_t) v->value.real;
963 
964                 DISABLE_WARNING_FLOAT_EQUAL;
965                 if ((double) converted == v->value.real)
966                         return converted;
967                 REENABLE_WARNING;
968 
969                 log_debug("Real %g requested as unsigned integer, and cannot be converted losslessly, returning 0.", v->value.real);
970                 return 0;
971         }
972 
973         default:
974                 break;
975         }
976 
977 mismatch:
978         log_debug("Non-integer JSON variant requested as unsigned, returning 0.");
979         return 0;
980 }
981 
json_variant_real(JsonVariant * v)982 double json_variant_real(JsonVariant *v) {
983         if (!v)
984                 return 0.0;
985         if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER ||
986             v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED ||
987             v == JSON_VARIANT_MAGIC_ZERO_REAL)
988                 return 0.0;
989         if (!json_variant_is_regular(v))
990                 goto mismatch;
991         if (v->is_reference)
992                 return json_variant_real(v->reference);
993 
994         switch (v->type) {
995 
996         case JSON_VARIANT_REAL:
997                 return v->value.real;
998 
999         case JSON_VARIANT_INTEGER: {
1000                 double converted = (double) v->value.integer;
1001 
1002                 if ((int64_t) converted == v->value.integer)
1003                         return converted;
1004 
1005                 log_debug("Signed integer %ji requested as real, and cannot be converted losslessly, returning 0.", v->value.integer);
1006                 return 0.0;
1007         }
1008 
1009         case JSON_VARIANT_UNSIGNED: {
1010                 double converted = (double) v->value.unsig;
1011 
1012                 if ((uint64_t) converted == v->value.unsig)
1013                         return converted;
1014 
1015                 log_debug("Unsigned integer %ju requested as real, and cannot be converted losslessly, returning 0.", v->value.unsig);
1016                 return 0.0;
1017         }
1018 
1019         default:
1020                 break;
1021         }
1022 
1023 mismatch:
1024         log_debug("Non-integer JSON variant requested as integer, returning 0.");
1025         return 0.0;
1026 }
1027 
json_variant_is_negative(JsonVariant * v)1028 bool json_variant_is_negative(JsonVariant *v) {
1029         if (!v)
1030                 goto mismatch;
1031         if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER ||
1032             v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED ||
1033             v == JSON_VARIANT_MAGIC_ZERO_REAL)
1034                 return false;
1035         if (!json_variant_is_regular(v))
1036                 goto mismatch;
1037         if (v->is_reference)
1038                 return json_variant_is_negative(v->reference);
1039 
1040         /* This function is useful as checking whether numbers are negative is pretty complex since we have three types
1041          * of numbers. And some JSON code (OCI for example) uses negative numbers to mark "not defined" numeric
1042          * values. */
1043 
1044         switch (v->type) {
1045 
1046         case JSON_VARIANT_REAL:
1047                 return v->value.real < 0;
1048 
1049         case JSON_VARIANT_INTEGER:
1050                 return v->value.integer < 0;
1051 
1052         case JSON_VARIANT_UNSIGNED:
1053                 return false;
1054 
1055         default:
1056                 break;
1057         }
1058 
1059 mismatch:
1060         log_debug("Non-integer JSON variant tested for negativity, returning false.");
1061         return false;
1062 }
1063 
json_variant_is_blank_object(JsonVariant * v)1064 bool json_variant_is_blank_object(JsonVariant *v) {
1065         /* Returns true if the specified object is null or empty */
1066         return !v ||
1067                 json_variant_is_null(v) ||
1068                 (json_variant_is_object(v) && json_variant_elements(v) == 0);
1069 }
1070 
json_variant_is_blank_array(JsonVariant * v)1071 bool json_variant_is_blank_array(JsonVariant *v) {
1072         return !v ||
1073                 json_variant_is_null(v) ||
1074                 (json_variant_is_array(v) && json_variant_elements(v) == 0);
1075 }
1076 
json_variant_type(JsonVariant * v)1077 JsonVariantType json_variant_type(JsonVariant *v) {
1078 
1079         if (!v)
1080                 return _JSON_VARIANT_TYPE_INVALID;
1081 
1082         if (json_variant_is_const_string(v))
1083                 return JSON_VARIANT_STRING;
1084 
1085         if (v == JSON_VARIANT_MAGIC_TRUE || v == JSON_VARIANT_MAGIC_FALSE)
1086                 return JSON_VARIANT_BOOLEAN;
1087 
1088         if (v == JSON_VARIANT_MAGIC_NULL)
1089                 return JSON_VARIANT_NULL;
1090 
1091         if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER)
1092                 return JSON_VARIANT_INTEGER;
1093 
1094         if (v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED)
1095                 return JSON_VARIANT_UNSIGNED;
1096 
1097         if (v == JSON_VARIANT_MAGIC_ZERO_REAL)
1098                 return JSON_VARIANT_REAL;
1099 
1100         if (v == JSON_VARIANT_MAGIC_EMPTY_STRING)
1101                 return JSON_VARIANT_STRING;
1102 
1103         if (v == JSON_VARIANT_MAGIC_EMPTY_ARRAY)
1104                 return JSON_VARIANT_ARRAY;
1105 
1106         if (v == JSON_VARIANT_MAGIC_EMPTY_OBJECT)
1107                 return JSON_VARIANT_OBJECT;
1108 
1109         return v->type;
1110 }
1111 
1112 _function_no_sanitize_float_cast_overflow_
json_variant_has_type(JsonVariant * v,JsonVariantType type)1113 bool json_variant_has_type(JsonVariant *v, JsonVariantType type) {
1114         JsonVariantType rt;
1115 
1116         /* Note: we turn off ubsan float cast overflow detection for this function, since it would complain
1117          * about our float casts but we do them explicitly to detect conversion errors. */
1118 
1119         v = json_variant_dereference(v);
1120         if (!v)
1121                 return false;
1122 
1123         rt = json_variant_type(v);
1124         if (rt == type)
1125                 return true;
1126 
1127         /* If it's a const string, then it only can be a string, and if it is not, it's not */
1128         if (json_variant_is_const_string(v))
1129                 return false;
1130 
1131         /* All three magic zeroes qualify as integer, unsigned and as real */
1132         if ((v == JSON_VARIANT_MAGIC_ZERO_INTEGER || v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED || v == JSON_VARIANT_MAGIC_ZERO_REAL) &&
1133             IN_SET(type, JSON_VARIANT_INTEGER, JSON_VARIANT_UNSIGNED, JSON_VARIANT_REAL, JSON_VARIANT_NUMBER))
1134                 return true;
1135 
1136         /* All other magic variant types are only equal to themselves */
1137         if (json_variant_is_magic(v))
1138                 return false;
1139 
1140         /* Handle the "number" pseudo type */
1141         if (type == JSON_VARIANT_NUMBER)
1142                 return IN_SET(rt, JSON_VARIANT_INTEGER, JSON_VARIANT_UNSIGNED, JSON_VARIANT_REAL);
1143 
1144         /* Integer conversions are OK in many cases */
1145         if (rt == JSON_VARIANT_INTEGER && type == JSON_VARIANT_UNSIGNED)
1146                 return v->value.integer >= 0;
1147         if (rt == JSON_VARIANT_UNSIGNED && type == JSON_VARIANT_INTEGER)
1148                 return v->value.unsig <= INT64_MAX;
1149 
1150         /* Any integer that can be converted lossley to a real and back may also be considered a real */
1151         if (rt == JSON_VARIANT_INTEGER && type == JSON_VARIANT_REAL)
1152                 return (int64_t) (double) v->value.integer == v->value.integer;
1153         if (rt == JSON_VARIANT_UNSIGNED && type == JSON_VARIANT_REAL)
1154                 return (uint64_t) (double) v->value.unsig == v->value.unsig;
1155 
1156         DISABLE_WARNING_FLOAT_EQUAL;
1157 
1158         /* Any real that can be converted losslessly to an integer and back may also be considered an integer */
1159         if (rt == JSON_VARIANT_REAL && type == JSON_VARIANT_INTEGER)
1160                 return (double) (int64_t) v->value.real == v->value.real;
1161         if (rt == JSON_VARIANT_REAL && type == JSON_VARIANT_UNSIGNED)
1162                 return (double) (uint64_t) v->value.real == v->value.real;
1163 
1164         REENABLE_WARNING;
1165 
1166         return false;
1167 }
1168 
json_variant_elements(JsonVariant * v)1169 size_t json_variant_elements(JsonVariant *v) {
1170         if (!v)
1171                 return 0;
1172         if (v == JSON_VARIANT_MAGIC_EMPTY_ARRAY ||
1173             v == JSON_VARIANT_MAGIC_EMPTY_OBJECT)
1174                 return 0;
1175         if (!json_variant_is_regular(v))
1176                 goto mismatch;
1177         if (!IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT))
1178                 goto mismatch;
1179         if (v->is_reference)
1180                 return json_variant_elements(v->reference);
1181 
1182         return v->n_elements;
1183 
1184 mismatch:
1185         log_debug("Number of elements in non-array/non-object JSON variant requested, returning 0.");
1186         return 0;
1187 }
1188 
json_variant_by_index(JsonVariant * v,size_t idx)1189 JsonVariant *json_variant_by_index(JsonVariant *v, size_t idx) {
1190         if (!v)
1191                 return NULL;
1192         if (v == JSON_VARIANT_MAGIC_EMPTY_ARRAY ||
1193             v == JSON_VARIANT_MAGIC_EMPTY_OBJECT)
1194                 return NULL;
1195         if (!json_variant_is_regular(v))
1196                 goto mismatch;
1197         if (!IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT))
1198                 goto mismatch;
1199         if (v->is_reference)
1200                 return json_variant_by_index(v->reference, idx);
1201         if (idx >= v->n_elements)
1202                 return NULL;
1203 
1204         return json_variant_conservative_formalize(v + 1 + idx);
1205 
1206 mismatch:
1207         log_debug("Element in non-array/non-object JSON variant requested by index, returning NULL.");
1208         return NULL;
1209 }
1210 
json_variant_by_key_full(JsonVariant * v,const char * key,JsonVariant ** ret_key)1211 JsonVariant *json_variant_by_key_full(JsonVariant *v, const char *key, JsonVariant **ret_key) {
1212         if (!v)
1213                 goto not_found;
1214         if (!key)
1215                 goto not_found;
1216         if (v == JSON_VARIANT_MAGIC_EMPTY_OBJECT)
1217                 goto not_found;
1218         if (!json_variant_is_regular(v))
1219                 goto mismatch;
1220         if (v->type != JSON_VARIANT_OBJECT)
1221                 goto mismatch;
1222         if (v->is_reference)
1223                 return json_variant_by_key(v->reference, key);
1224 
1225         if (v->sorted) {
1226                 size_t a = 0, b = v->n_elements/2;
1227 
1228                 /* If the variant is sorted we can use bisection to find the entry we need in O(log(n)) time */
1229 
1230                 while (b > a) {
1231                         JsonVariant *p;
1232                         const char *f;
1233                         size_t i;
1234                         int c;
1235 
1236                         i = (a + b) / 2;
1237                         p = json_variant_dereference(v + 1 + i*2);
1238 
1239                         assert_se(f = json_variant_string(p));
1240 
1241                         c = strcmp(key, f);
1242                         if (c == 0) {
1243                                 if (ret_key)
1244                                         *ret_key = json_variant_conservative_formalize(v + 1 + i*2);
1245 
1246                                 return json_variant_conservative_formalize(v + 1 + i*2 + 1);
1247                         } else if (c < 0)
1248                                 b = i;
1249                         else
1250                                 a = i + 1;
1251                 }
1252 
1253                 goto not_found;
1254         }
1255 
1256         /* The variant is not sorted, hence search for the field linearly */
1257         for (size_t i = 0; i < v->n_elements; i += 2) {
1258                 JsonVariant *p;
1259 
1260                 p = json_variant_dereference(v + 1 + i);
1261 
1262                 if (!json_variant_has_type(p, JSON_VARIANT_STRING))
1263                         continue;
1264 
1265                 if (streq(json_variant_string(p), key)) {
1266 
1267                         if (ret_key)
1268                                 *ret_key = json_variant_conservative_formalize(v + 1 + i);
1269 
1270                         return json_variant_conservative_formalize(v + 1 + i + 1);
1271                 }
1272         }
1273 
1274 not_found:
1275         if (ret_key)
1276                 *ret_key = NULL;
1277 
1278         return NULL;
1279 
1280 mismatch:
1281         log_debug("Element in non-object JSON variant requested by key, returning NULL.");
1282         if (ret_key)
1283                 *ret_key = NULL;
1284 
1285         return NULL;
1286 }
1287 
json_variant_by_key(JsonVariant * v,const char * key)1288 JsonVariant *json_variant_by_key(JsonVariant *v, const char *key) {
1289         return json_variant_by_key_full(v, key, NULL);
1290 }
1291 
json_variant_equal(JsonVariant * a,JsonVariant * b)1292 bool json_variant_equal(JsonVariant *a, JsonVariant *b) {
1293         JsonVariantType t;
1294 
1295         a = json_variant_formalize(a);
1296         b = json_variant_formalize(b);
1297 
1298         if (a == b)
1299                 return true;
1300 
1301         t = json_variant_type(a);
1302         if (!json_variant_has_type(b, t))
1303                 return false;
1304 
1305         switch (t) {
1306 
1307         case JSON_VARIANT_STRING:
1308                 return streq(json_variant_string(a), json_variant_string(b));
1309 
1310         case JSON_VARIANT_INTEGER:
1311                 return json_variant_integer(a) == json_variant_integer(b);
1312 
1313         case JSON_VARIANT_UNSIGNED:
1314                 return json_variant_unsigned(a) == json_variant_unsigned(b);
1315 
1316         case JSON_VARIANT_REAL:
1317                 DISABLE_WARNING_FLOAT_EQUAL;
1318                 return json_variant_real(a) == json_variant_real(b);
1319                 REENABLE_WARNING;
1320 
1321         case JSON_VARIANT_BOOLEAN:
1322                 return json_variant_boolean(a) == json_variant_boolean(b);
1323 
1324         case JSON_VARIANT_NULL:
1325                 return true;
1326 
1327         case JSON_VARIANT_ARRAY: {
1328                 size_t n = json_variant_elements(a);
1329                 if (n != json_variant_elements(b))
1330                         return false;
1331 
1332                 for (size_t i = 0; i < n; i++)
1333                         if (!json_variant_equal(json_variant_by_index(a, i), json_variant_by_index(b, i)))
1334                                 return false;
1335 
1336                 return true;
1337         }
1338 
1339         case JSON_VARIANT_OBJECT: {
1340                 size_t n = json_variant_elements(a);
1341                 if (n != json_variant_elements(b))
1342                         return false;
1343 
1344                 /* Iterate through all keys in 'a' */
1345                 for (size_t i = 0; i < n; i += 2) {
1346                         bool found = false;
1347 
1348                         /* Match them against all keys in 'b' */
1349                         for (size_t j = 0; j < n; j += 2) {
1350                                 JsonVariant *key_b;
1351 
1352                                 key_b = json_variant_by_index(b, j);
1353 
1354                                 /* During the first iteration unmark everything */
1355                                 if (i == 0)
1356                                         key_b->is_marked = false;
1357                                 else if (key_b->is_marked) /* In later iterations if we already marked something, don't bother with it again */
1358                                         continue;
1359 
1360                                 if (found)
1361                                         continue;
1362 
1363                                 if (json_variant_equal(json_variant_by_index(a, i), key_b) &&
1364                                     json_variant_equal(json_variant_by_index(a, i+1), json_variant_by_index(b, j+1))) {
1365                                         /* Key and values match! */
1366                                         key_b->is_marked = found = true;
1367 
1368                                         /* In the first iteration we continue the inner loop since we want to mark
1369                                          * everything, otherwise exit the loop quickly after we found what we were
1370                                          * looking for. */
1371                                         if (i != 0)
1372                                                 break;
1373                                 }
1374                         }
1375 
1376                         if (!found)
1377                                 return false;
1378                 }
1379 
1380                 return true;
1381         }
1382 
1383         default:
1384                 assert_not_reached();
1385         }
1386 }
1387 
json_variant_sensitive(JsonVariant * v)1388 void json_variant_sensitive(JsonVariant *v) {
1389         assert(v);
1390 
1391         /* Marks a variant as "sensitive", so that it is erased from memory when it is destroyed. This is a
1392          * one-way operation: as soon as it is marked this way it remains marked this way until it's
1393          * destroyed. A magic variant is never sensitive though, even when asked, since it's too
1394          * basic. Similar, const string variant are never sensitive either, after all they are included in
1395          * the source code as they are, which is not suitable for inclusion of secrets.
1396          *
1397          * Note that this flag has a recursive effect: when we destroy an object or array we'll propagate the
1398          * flag to all contained variants. And if those are then destroyed this is propagated further down,
1399          * and so on. */
1400 
1401         v = json_variant_formalize(v);
1402         if (!json_variant_is_regular(v))
1403                 return;
1404 
1405         v->sensitive = true;
1406 }
1407 
json_variant_is_sensitive(JsonVariant * v)1408 bool json_variant_is_sensitive(JsonVariant *v) {
1409         v = json_variant_formalize(v);
1410         if (!json_variant_is_regular(v))
1411                 return false;
1412 
1413         return v->sensitive;
1414 }
1415 
json_variant_propagate_sensitive(JsonVariant * from,JsonVariant * to)1416 static void json_variant_propagate_sensitive(JsonVariant *from, JsonVariant *to) {
1417         if (json_variant_is_sensitive(from))
1418                 json_variant_sensitive(to);
1419 }
1420 
json_variant_get_source(JsonVariant * v,const char ** ret_source,unsigned * ret_line,unsigned * ret_column)1421 int json_variant_get_source(JsonVariant *v, const char **ret_source, unsigned *ret_line, unsigned *ret_column) {
1422         assert_return(v, -EINVAL);
1423 
1424         if (ret_source)
1425                 *ret_source = json_variant_is_regular(v) && v->source ? v->source->name : NULL;
1426 
1427         if (ret_line)
1428                 *ret_line = json_variant_is_regular(v) ? v->line : 0;
1429 
1430         if (ret_column)
1431                 *ret_column = json_variant_is_regular(v) ? v->column : 0;
1432 
1433         return 0;
1434 }
1435 
print_source(FILE * f,JsonVariant * v,JsonFormatFlags flags,bool whitespace)1436 static int print_source(FILE *f, JsonVariant *v, JsonFormatFlags flags, bool whitespace) {
1437         size_t w, k;
1438 
1439         if (!FLAGS_SET(flags, JSON_FORMAT_SOURCE|JSON_FORMAT_PRETTY))
1440                 return 0;
1441 
1442         if (!json_variant_is_regular(v))
1443                 return 0;
1444 
1445         if (!v->source && v->line == 0 && v->column == 0)
1446                 return 0;
1447 
1448         /* The max width we need to format the line numbers for this source file */
1449         w = (v->source && v->source->max_line > 0) ?
1450                 DECIMAL_STR_WIDTH(v->source->max_line) :
1451                 DECIMAL_STR_MAX(unsigned)-1;
1452         k = (v->source && v->source->max_column > 0) ?
1453                 DECIMAL_STR_WIDTH(v->source->max_column) :
1454                 DECIMAL_STR_MAX(unsigned) -1;
1455 
1456         if (whitespace) {
1457                 size_t n = 1 + (v->source ? strlen(v->source->name) : 0) +
1458                                ((v->source && (v->line > 0 || v->column > 0)) ? 1 : 0) +
1459                                (v->line > 0 ? w : 0) +
1460                                (((v->source || v->line > 0) && v->column > 0) ? 1 : 0) +
1461                                (v->column > 0 ? k : 0) +
1462                                2;
1463 
1464                 for (size_t i = 0; i < n; i++)
1465                         fputc(' ', f);
1466         } else {
1467                 fputc('[', f);
1468 
1469                 if (v->source)
1470                         fputs(v->source->name, f);
1471                 if (v->source && (v->line > 0 || v->column > 0))
1472                         fputc(':', f);
1473                 if (v->line > 0)
1474                         fprintf(f, "%*u", (int) w, v->line);
1475                 if ((v->source || v->line > 0) || v->column > 0)
1476                         fputc(':', f);
1477                 if (v->column > 0)
1478                         fprintf(f, "%*u", (int) k, v->column);
1479 
1480                 fputc(']', f);
1481                 fputc(' ', f);
1482         }
1483 
1484         return 0;
1485 }
1486 
json_format_string(FILE * f,const char * q,JsonFormatFlags flags)1487 static void json_format_string(FILE *f, const char *q, JsonFormatFlags flags) {
1488         assert(q);
1489 
1490         fputc('"', f);
1491 
1492         if (flags & JSON_FORMAT_COLOR)
1493                 fputs(ansi_green(), f);
1494 
1495         for (; *q; q++)
1496                 switch (*q) {
1497                 case '"':
1498                         fputs("\\\"", f);
1499                         break;
1500 
1501                 case '\\':
1502                         fputs("\\\\", f);
1503                         break;
1504 
1505                 case '\b':
1506                         fputs("\\b", f);
1507                         break;
1508 
1509                 case '\f':
1510                         fputs("\\f", f);
1511                         break;
1512 
1513                 case '\n':
1514                         fputs("\\n", f);
1515                         break;
1516 
1517                 case '\r':
1518                         fputs("\\r", f);
1519                         break;
1520 
1521                 case '\t':
1522                         fputs("\\t", f);
1523                         break;
1524 
1525                 default:
1526                         if ((signed char) *q >= 0 && *q < ' ')
1527                                 fprintf(f, "\\u%04x", *q);
1528                         else
1529                                 fputc(*q, f);
1530                         break;
1531                 }
1532 
1533         if (flags & JSON_FORMAT_COLOR)
1534                 fputs(ANSI_NORMAL, f);
1535 
1536         fputc('"', f);
1537 }
1538 
json_format(FILE * f,JsonVariant * v,JsonFormatFlags flags,const char * prefix)1539 static int json_format(FILE *f, JsonVariant *v, JsonFormatFlags flags, const char *prefix) {
1540         int r;
1541 
1542         assert(f);
1543         assert(v);
1544 
1545         switch (json_variant_type(v)) {
1546 
1547         case JSON_VARIANT_REAL: {
1548                 locale_t loc;
1549 
1550                 loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
1551                 if (loc == (locale_t) 0)
1552                         return -errno;
1553 
1554                 if (flags & JSON_FORMAT_COLOR)
1555                         fputs(ansi_highlight_blue(), f);
1556 
1557                 fprintf(f, "%.*e", DECIMAL_DIG, json_variant_real(v));
1558 
1559                 if (flags & JSON_FORMAT_COLOR)
1560                         fputs(ANSI_NORMAL, f);
1561 
1562                 freelocale(loc);
1563                 break;
1564         }
1565 
1566         case JSON_VARIANT_INTEGER:
1567                 if (flags & JSON_FORMAT_COLOR)
1568                         fputs(ansi_highlight_blue(), f);
1569 
1570                 fprintf(f, "%" PRIdMAX, json_variant_integer(v));
1571 
1572                 if (flags & JSON_FORMAT_COLOR)
1573                         fputs(ANSI_NORMAL, f);
1574                 break;
1575 
1576         case JSON_VARIANT_UNSIGNED:
1577                 if (flags & JSON_FORMAT_COLOR)
1578                         fputs(ansi_highlight_blue(), f);
1579 
1580                 fprintf(f, "%" PRIuMAX, json_variant_unsigned(v));
1581 
1582                 if (flags & JSON_FORMAT_COLOR)
1583                         fputs(ANSI_NORMAL, f);
1584                 break;
1585 
1586         case JSON_VARIANT_BOOLEAN:
1587 
1588                 if (flags & JSON_FORMAT_COLOR)
1589                         fputs(ANSI_HIGHLIGHT, f);
1590 
1591                 if (json_variant_boolean(v))
1592                         fputs("true", f);
1593                 else
1594                         fputs("false", f);
1595 
1596                 if (flags & JSON_FORMAT_COLOR)
1597                         fputs(ANSI_NORMAL, f);
1598 
1599                 break;
1600 
1601         case JSON_VARIANT_NULL:
1602                 if (flags & JSON_FORMAT_COLOR)
1603                         fputs(ANSI_HIGHLIGHT, f);
1604 
1605                 fputs("null", f);
1606 
1607                 if (flags & JSON_FORMAT_COLOR)
1608                         fputs(ANSI_NORMAL, f);
1609                 break;
1610 
1611         case JSON_VARIANT_STRING:
1612                 json_format_string(f, json_variant_string(v), flags);
1613                 break;
1614 
1615         case JSON_VARIANT_ARRAY: {
1616                 size_t n = json_variant_elements(v);
1617                 if (n == 0)
1618                         fputs("[]", f);
1619                 else {
1620                         _cleanup_free_ char *joined = NULL;
1621                         const char *prefix2;
1622 
1623                         if (flags & JSON_FORMAT_PRETTY) {
1624                                 joined = strjoin(strempty(prefix), "\t");
1625                                 if (!joined)
1626                                         return -ENOMEM;
1627 
1628                                 prefix2 = joined;
1629                                 fputs("[\n", f);
1630                         } else {
1631                                 prefix2 = strempty(prefix);
1632                                 fputc('[', f);
1633                         }
1634 
1635                         for (size_t i = 0; i < n; i++) {
1636                                 JsonVariant *e;
1637 
1638                                 assert_se(e = json_variant_by_index(v, i));
1639 
1640                                 if (i > 0) {
1641                                         if (flags & JSON_FORMAT_PRETTY)
1642                                                 fputs(",\n", f);
1643                                         else
1644                                                 fputc(',', f);
1645                                 }
1646 
1647                                 if (flags & JSON_FORMAT_PRETTY) {
1648                                         print_source(f, e, flags, false);
1649                                         fputs(prefix2, f);
1650                                 }
1651 
1652                                 r = json_format(f, e, flags, prefix2);
1653                                 if (r < 0)
1654                                         return r;
1655                         }
1656 
1657                         if (flags & JSON_FORMAT_PRETTY) {
1658                                 fputc('\n', f);
1659                                 print_source(f, v, flags, true);
1660                                 fputs(strempty(prefix), f);
1661                         }
1662 
1663                         fputc(']', f);
1664                 }
1665                 break;
1666         }
1667 
1668         case JSON_VARIANT_OBJECT: {
1669                 size_t n = json_variant_elements(v);
1670                 if (n == 0)
1671                         fputs("{}", f);
1672                 else {
1673                         _cleanup_free_ char *joined = NULL;
1674                         const char *prefix2;
1675 
1676                         if (flags & JSON_FORMAT_PRETTY) {
1677                                 joined = strjoin(strempty(prefix), "\t");
1678                                 if (!joined)
1679                                         return -ENOMEM;
1680 
1681                                 prefix2 = joined;
1682                                 fputs("{\n", f);
1683                         } else {
1684                                 prefix2 = strempty(prefix);
1685                                 fputc('{', f);
1686                         }
1687 
1688                         for (size_t i = 0; i < n; i += 2) {
1689                                 JsonVariant *e;
1690 
1691                                 e = json_variant_by_index(v, i);
1692 
1693                                 if (i > 0) {
1694                                         if (flags & JSON_FORMAT_PRETTY)
1695                                                 fputs(",\n", f);
1696                                         else
1697                                                 fputc(',', f);
1698                                 }
1699 
1700                                 if (flags & JSON_FORMAT_PRETTY) {
1701                                         print_source(f, e, flags, false);
1702                                         fputs(prefix2, f);
1703                                 }
1704 
1705                                 r = json_format(f, e, flags, prefix2);
1706                                 if (r < 0)
1707                                         return r;
1708 
1709                                 fputs(flags & JSON_FORMAT_PRETTY ? " : " : ":", f);
1710 
1711                                 r = json_format(f, json_variant_by_index(v, i+1), flags, prefix2);
1712                                 if (r < 0)
1713                                         return r;
1714                         }
1715 
1716                         if (flags & JSON_FORMAT_PRETTY) {
1717                                 fputc('\n', f);
1718                                 print_source(f, v, flags, true);
1719                                 fputs(strempty(prefix), f);
1720                         }
1721 
1722                         fputc('}', f);
1723                 }
1724                 break;
1725         }
1726 
1727         default:
1728                 assert_not_reached();
1729         }
1730 
1731         return 0;
1732 }
1733 
json_variant_format(JsonVariant * v,JsonFormatFlags flags,char ** ret)1734 int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret) {
1735         _cleanup_free_ char *s = NULL;
1736         size_t sz = 0;
1737         int r;
1738 
1739         /* Returns the length of the generated string (without the terminating NUL),
1740          * or negative on error. */
1741 
1742         assert_return(v, -EINVAL);
1743         assert_return(ret, -EINVAL);
1744 
1745         if (flags & JSON_FORMAT_OFF)
1746                 return -ENOEXEC;
1747 
1748         {
1749                 _cleanup_fclose_ FILE *f = NULL;
1750 
1751                 f = open_memstream_unlocked(&s, &sz);
1752                 if (!f)
1753                         return -ENOMEM;
1754 
1755                 json_variant_dump(v, flags, f, NULL);
1756 
1757                 /* Add terminating 0, so that the output buffer is a valid string. */
1758                 fputc('\0', f);
1759 
1760                 r = fflush_and_check(f);
1761         }
1762         if (r < 0)
1763                 return r;
1764 
1765         assert(s);
1766         *ret = TAKE_PTR(s);
1767         assert(sz > 0);
1768         return (int) sz - 1;
1769 }
1770 
json_variant_dump(JsonVariant * v,JsonFormatFlags flags,FILE * f,const char * prefix)1771 void json_variant_dump(JsonVariant *v, JsonFormatFlags flags, FILE *f, const char *prefix) {
1772         if (!v)
1773                 return;
1774 
1775         if (!f)
1776                 f = stdout;
1777 
1778         print_source(f, v, flags, false);
1779 
1780         if (((flags & (JSON_FORMAT_COLOR_AUTO|JSON_FORMAT_COLOR)) == JSON_FORMAT_COLOR_AUTO) && colors_enabled())
1781                 flags |= JSON_FORMAT_COLOR;
1782 
1783         if (((flags & (JSON_FORMAT_PRETTY_AUTO|JSON_FORMAT_PRETTY)) == JSON_FORMAT_PRETTY_AUTO))
1784                 flags |= on_tty() ? JSON_FORMAT_PRETTY : JSON_FORMAT_NEWLINE;
1785 
1786         if (flags & JSON_FORMAT_SSE)
1787                 fputs("data: ", f);
1788         if (flags & JSON_FORMAT_SEQ)
1789                 fputc('\x1e', f); /* ASCII Record Separator */
1790 
1791         json_format(f, v, flags, prefix);
1792 
1793         if (flags & (JSON_FORMAT_PRETTY|JSON_FORMAT_SEQ|JSON_FORMAT_SSE|JSON_FORMAT_NEWLINE))
1794                 fputc('\n', f);
1795         if (flags & JSON_FORMAT_SSE)
1796                 fputc('\n', f); /* In case of SSE add a second newline */
1797 
1798         if (flags & JSON_FORMAT_FLUSH)
1799                 fflush(f);
1800 }
1801 
json_variant_filter(JsonVariant ** v,char ** to_remove)1802 int json_variant_filter(JsonVariant **v, char **to_remove) {
1803         _cleanup_(json_variant_unrefp) JsonVariant *w = NULL;
1804         _cleanup_free_ JsonVariant **array = NULL;
1805         size_t n = 0, k = 0;
1806         int r;
1807 
1808         assert(v);
1809 
1810         if (json_variant_is_blank_object(*v))
1811                 return 0;
1812         if (!json_variant_is_object(*v))
1813                 return -EINVAL;
1814 
1815         if (strv_isempty(to_remove))
1816                 return 0;
1817 
1818         for (size_t i = 0; i < json_variant_elements(*v); i += 2) {
1819                 JsonVariant *p;
1820 
1821                 p = json_variant_by_index(*v, i);
1822                 if (!json_variant_has_type(p, JSON_VARIANT_STRING))
1823                         return -EINVAL;
1824 
1825                 if (strv_contains(to_remove, json_variant_string(p))) {
1826                         if (!array) {
1827                                 array = new(JsonVariant*, json_variant_elements(*v) - 2);
1828                                 if (!array)
1829                                         return -ENOMEM;
1830 
1831                                 for (k = 0; k < i; k++)
1832                                         array[k] = json_variant_by_index(*v, k);
1833                         }
1834 
1835                         n++;
1836                 } else if (array) {
1837                         array[k++] = p;
1838                         array[k++] = json_variant_by_index(*v, i + 1);
1839                 }
1840         }
1841 
1842         if (n == 0)
1843                 return 0;
1844 
1845         r = json_variant_new_object(&w, array, k);
1846         if (r < 0)
1847                 return r;
1848 
1849         json_variant_propagate_sensitive(*v, w);
1850         JSON_VARIANT_REPLACE(*v, TAKE_PTR(w));
1851 
1852         return (int) n;
1853 }
1854 
json_variant_set_field(JsonVariant ** v,const char * field,JsonVariant * value)1855 int json_variant_set_field(JsonVariant **v, const char *field, JsonVariant *value) {
1856         _cleanup_(json_variant_unrefp) JsonVariant *field_variant = NULL, *w = NULL;
1857         _cleanup_free_ JsonVariant **array = NULL;
1858         size_t k = 0;
1859         int r;
1860 
1861         assert(v);
1862         assert(field);
1863 
1864         if (json_variant_is_blank_object(*v)) {
1865                 array = new(JsonVariant*, 2);
1866                 if (!array)
1867                         return -ENOMEM;
1868 
1869         } else {
1870                 if (!json_variant_is_object(*v))
1871                         return -EINVAL;
1872 
1873                 for (size_t i = 0; i < json_variant_elements(*v); i += 2) {
1874                         JsonVariant *p;
1875 
1876                         p = json_variant_by_index(*v, i);
1877                         if (!json_variant_is_string(p))
1878                                 return -EINVAL;
1879 
1880                         if (streq(json_variant_string(p), field)) {
1881 
1882                                 if (!array) {
1883                                         array = new(JsonVariant*, json_variant_elements(*v));
1884                                         if (!array)
1885                                                 return -ENOMEM;
1886 
1887                                         for (k = 0; k < i; k++)
1888                                                 array[k] = json_variant_by_index(*v, k);
1889                                 }
1890 
1891                         } else if (array) {
1892                                 array[k++] = p;
1893                                 array[k++] = json_variant_by_index(*v, i + 1);
1894                         }
1895                 }
1896 
1897                 if (!array) {
1898                         array = new(JsonVariant*, json_variant_elements(*v) + 2);
1899                         if (!array)
1900                                 return -ENOMEM;
1901 
1902                         for (k = 0; k < json_variant_elements(*v); k++)
1903                                 array[k] = json_variant_by_index(*v, k);
1904                 }
1905         }
1906 
1907         r = json_variant_new_string(&field_variant, field);
1908         if (r < 0)
1909                 return r;
1910 
1911         array[k++] = field_variant;
1912         array[k++] = value;
1913 
1914         r = json_variant_new_object(&w, array, k);
1915         if (r < 0)
1916                 return r;
1917 
1918         json_variant_propagate_sensitive(*v, w);
1919         JSON_VARIANT_REPLACE(*v, TAKE_PTR(w));
1920 
1921         return 1;
1922 }
1923 
json_variant_set_field_string(JsonVariant ** v,const char * field,const char * value)1924 int json_variant_set_field_string(JsonVariant **v, const char *field, const char *value) {
1925         _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
1926         int r;
1927 
1928         r = json_variant_new_string(&m, value);
1929         if (r < 0)
1930                 return r;
1931 
1932         return json_variant_set_field(v, field, m);
1933 }
1934 
json_variant_set_field_integer(JsonVariant ** v,const char * field,int64_t i)1935 int json_variant_set_field_integer(JsonVariant **v, const char *field, int64_t i) {
1936         _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
1937         int r;
1938 
1939         r = json_variant_new_integer(&m, i);
1940         if (r < 0)
1941                 return r;
1942 
1943         return json_variant_set_field(v, field, m);
1944 }
1945 
json_variant_set_field_unsigned(JsonVariant ** v,const char * field,uint64_t u)1946 int json_variant_set_field_unsigned(JsonVariant **v, const char *field, uint64_t u) {
1947         _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
1948         int r;
1949 
1950         r = json_variant_new_unsigned(&m, u);
1951         if (r < 0)
1952                 return r;
1953 
1954         return json_variant_set_field(v, field, m);
1955 }
1956 
json_variant_set_field_boolean(JsonVariant ** v,const char * field,bool b)1957 int json_variant_set_field_boolean(JsonVariant **v, const char *field, bool b) {
1958         _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
1959         int r;
1960 
1961         r = json_variant_new_boolean(&m, b);
1962         if (r < 0)
1963                 return r;
1964 
1965         return json_variant_set_field(v, field, m);
1966 }
1967 
json_variant_set_field_strv(JsonVariant ** v,const char * field,char ** l)1968 int json_variant_set_field_strv(JsonVariant **v, const char *field, char **l) {
1969         _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
1970         int r;
1971 
1972         r = json_variant_new_array_strv(&m, l);
1973         if (r < 0)
1974                 return r;
1975 
1976         return json_variant_set_field(v, field, m);
1977 }
1978 
json_variant_merge(JsonVariant ** v,JsonVariant * m)1979 int json_variant_merge(JsonVariant **v, JsonVariant *m) {
1980         _cleanup_(json_variant_unrefp) JsonVariant *w = NULL;
1981         _cleanup_free_ JsonVariant **array = NULL;
1982         size_t v_elements, m_elements, k;
1983         bool v_blank, m_blank;
1984         int r;
1985 
1986         m = json_variant_dereference(m);
1987 
1988         v_blank = json_variant_is_blank_object(*v);
1989         m_blank = json_variant_is_blank_object(m);
1990 
1991         if (!v_blank && !json_variant_is_object(*v))
1992                 return -EINVAL;
1993         if (!m_blank && !json_variant_is_object(m))
1994                 return -EINVAL;
1995 
1996         if (m_blank)
1997                 return 0; /* nothing to do */
1998 
1999         if (v_blank) {
2000                 JSON_VARIANT_REPLACE(*v, json_variant_ref(m));
2001                 return 1;
2002         }
2003 
2004         v_elements = json_variant_elements(*v);
2005         m_elements = json_variant_elements(m);
2006         if (v_elements > SIZE_MAX - m_elements) /* overflow check */
2007                 return -ENOMEM;
2008 
2009         array = new(JsonVariant*, v_elements + m_elements);
2010         if (!array)
2011                 return -ENOMEM;
2012 
2013         k = 0;
2014         for (size_t i = 0; i < v_elements; i += 2) {
2015                 JsonVariant *u;
2016 
2017                 u = json_variant_by_index(*v, i);
2018                 if (!json_variant_is_string(u))
2019                         return -EINVAL;
2020 
2021                 if (json_variant_by_key(m, json_variant_string(u)))
2022                         continue; /* skip if exists in second variant */
2023 
2024                 array[k++] = u;
2025                 array[k++] = json_variant_by_index(*v, i + 1);
2026         }
2027 
2028         for (size_t i = 0; i < m_elements; i++)
2029                 array[k++] = json_variant_by_index(m, i);
2030 
2031         r = json_variant_new_object(&w, array, k);
2032         if (r < 0)
2033                 return r;
2034 
2035         json_variant_propagate_sensitive(*v, w);
2036         json_variant_propagate_sensitive(m, w);
2037         JSON_VARIANT_REPLACE(*v, TAKE_PTR(w));
2038 
2039         return 1;
2040 }
2041 
json_variant_append_array(JsonVariant ** v,JsonVariant * element)2042 int json_variant_append_array(JsonVariant **v, JsonVariant *element) {
2043         _cleanup_(json_variant_unrefp) JsonVariant *nv = NULL;
2044         bool blank;
2045         int r;
2046 
2047         assert(v);
2048         assert(element);
2049 
2050 
2051         if (!*v || json_variant_is_null(*v))
2052                 blank = true;
2053         else if (!json_variant_is_array(*v))
2054                 return -EINVAL;
2055         else
2056                 blank = json_variant_elements(*v) == 0;
2057 
2058         if (blank)
2059                 r = json_variant_new_array(&nv, (JsonVariant*[]) { element }, 1);
2060         else {
2061                 _cleanup_free_ JsonVariant **array = new(JsonVariant*, json_variant_elements(*v) + 1);
2062                 if (!array)
2063                         return -ENOMEM;
2064 
2065                 size_t size = json_variant_elements(*v);
2066                 for (size_t i = 0; i < size; i++)
2067                         array[i] = json_variant_by_index(*v, i);
2068 
2069                 array[size] = element;
2070 
2071                 r = json_variant_new_array(&nv, array, size + 1);
2072         }
2073         if (r < 0)
2074                 return r;
2075 
2076         json_variant_propagate_sensitive(*v, nv);
2077         JSON_VARIANT_REPLACE(*v, TAKE_PTR(nv));
2078 
2079         return 0;
2080 }
2081 
json_variant_strv(JsonVariant * v,char *** ret)2082 int json_variant_strv(JsonVariant *v, char ***ret) {
2083         char **l = NULL;
2084         bool sensitive;
2085         int r;
2086 
2087         assert(ret);
2088 
2089         if (!v || json_variant_is_null(v)) {
2090                 l = new0(char*, 1);
2091                 if (!l)
2092                         return -ENOMEM;
2093 
2094                 *ret = l;
2095                 return 0;
2096         }
2097 
2098         if (!json_variant_is_array(v))
2099                 return -EINVAL;
2100 
2101         sensitive = v->sensitive;
2102 
2103         size_t n = json_variant_elements(v);
2104         l = new(char*, n+1);
2105         if (!l)
2106                 return -ENOMEM;
2107 
2108         for (size_t i = 0; i < n; i++) {
2109                 JsonVariant *e;
2110 
2111                 assert_se(e = json_variant_by_index(v, i));
2112                 sensitive = sensitive || e->sensitive;
2113 
2114                 if (!json_variant_is_string(e)) {
2115                         l[i] = NULL;
2116                         r = -EINVAL;
2117                         goto fail;
2118                 }
2119 
2120                 l[i] = strdup(json_variant_string(e));
2121                 if (!l[i]) {
2122                         r = -ENOMEM;
2123                         goto fail;
2124                 }
2125         }
2126 
2127         l[n] = NULL;
2128         *ret = TAKE_PTR(l);
2129 
2130         return 0;
2131 
2132 fail:
2133         if (sensitive)
2134                 strv_free_erase(l);
2135         else
2136                 strv_free(l);
2137 
2138         return r;
2139 }
2140 
json_variant_copy(JsonVariant ** nv,JsonVariant * v)2141 static int json_variant_copy(JsonVariant **nv, JsonVariant *v) {
2142         JsonVariantType t;
2143         JsonVariant *c;
2144         JsonValue value;
2145         const void *source;
2146         size_t k;
2147 
2148         assert(nv);
2149         assert(v);
2150 
2151         /* Let's copy the simple types literally, and the larger types by references */
2152         t = json_variant_type(v);
2153         switch (t) {
2154         case JSON_VARIANT_INTEGER:
2155                 k = sizeof(int64_t);
2156                 value.integer = json_variant_integer(v);
2157                 source = &value;
2158                 break;
2159 
2160         case JSON_VARIANT_UNSIGNED:
2161                 k = sizeof(uint64_t);
2162                 value.unsig = json_variant_unsigned(v);
2163                 source = &value;
2164                 break;
2165 
2166         case JSON_VARIANT_REAL:
2167                 k = sizeof(double);
2168                 value.real = json_variant_real(v);
2169                 source = &value;
2170                 break;
2171 
2172         case JSON_VARIANT_BOOLEAN:
2173                 k = sizeof(bool);
2174                 value.boolean = json_variant_boolean(v);
2175                 source = &value;
2176                 break;
2177 
2178         case JSON_VARIANT_NULL:
2179                 k = 0;
2180                 source = NULL;
2181                 break;
2182 
2183         case JSON_VARIANT_STRING:
2184                 source = json_variant_string(v);
2185                 k = strnlen(source, INLINE_STRING_MAX + 1);
2186                 if (k <= INLINE_STRING_MAX) {
2187                         k ++;
2188                         break;
2189                 }
2190 
2191                 _fallthrough_;
2192 
2193         default:
2194                 /* Everything else copy by reference */
2195 
2196                 c = malloc0(MAX(sizeof(JsonVariant),
2197                                 offsetof(JsonVariant, reference) + sizeof(JsonVariant*)));
2198                 if (!c)
2199                         return -ENOMEM;
2200 
2201                 c->n_ref = 1;
2202                 c->type = t;
2203                 c->is_reference = true;
2204                 c->reference = json_variant_ref(json_variant_formalize(v));
2205 
2206                 *nv = c;
2207                 return 0;
2208         }
2209 
2210         c = malloc0(MAX(sizeof(JsonVariant),
2211                         offsetof(JsonVariant, value) + k));
2212         if (!c)
2213                 return -ENOMEM;
2214 
2215         c->n_ref = 1;
2216         c->type = t;
2217 
2218         memcpy_safe(&c->value, source, k);
2219 
2220         json_variant_propagate_sensitive(v, c);
2221 
2222         *nv = c;
2223         return 0;
2224 }
2225 
json_single_ref(JsonVariant * v)2226 static bool json_single_ref(JsonVariant *v) {
2227 
2228         /* Checks whether the caller is the single owner of the object, i.e. can get away with changing it */
2229 
2230         if (!json_variant_is_regular(v))
2231                 return false;
2232 
2233         if (v->is_embedded)
2234                 return json_single_ref(v->parent);
2235 
2236         assert(v->n_ref > 0);
2237         return v->n_ref == 1;
2238 }
2239 
json_variant_set_source(JsonVariant ** v,JsonSource * source,unsigned line,unsigned column)2240 static int json_variant_set_source(JsonVariant **v, JsonSource *source, unsigned line, unsigned column) {
2241         JsonVariant *w;
2242         int r;
2243 
2244         assert(v);
2245 
2246         /* Patch in source and line/column number. Tries to do this in-place if the caller is the sole
2247          * referencer of the object. If not, allocates a new object, possibly a surrogate for the original
2248          * one */
2249 
2250         if (!*v)
2251                 return 0;
2252 
2253         if (source && line > source->max_line)
2254                 source->max_line = line;
2255         if (source && column > source->max_column)
2256                 source->max_column = column;
2257 
2258         if (!json_variant_is_regular(*v)) {
2259 
2260                 if (!source && line == 0 && column == 0)
2261                         return 0;
2262 
2263         } else {
2264                 if (json_source_equal((*v)->source, source) &&
2265                     (*v)->line == line &&
2266                     (*v)->column == column)
2267                         return 0;
2268 
2269                 if (json_single_ref(*v)) { /* Sole reference? */
2270                         json_source_unref((*v)->source);
2271                         (*v)->source = json_source_ref(source);
2272                         (*v)->line = line;
2273                         (*v)->column = column;
2274                         return 1;
2275                 }
2276         }
2277 
2278         r = json_variant_copy(&w, *v);
2279         if (r < 0)
2280                 return r;
2281 
2282         assert(json_variant_is_regular(w));
2283         assert(!w->is_embedded);
2284         assert(w->n_ref == 1);
2285         assert(!w->source);
2286 
2287         w->source = json_source_ref(source);
2288         w->line = line;
2289         w->column = column;
2290 
2291         JSON_VARIANT_REPLACE(*v, w);
2292 
2293         return 1;
2294 }
2295 
inc_lines_columns(unsigned * line,unsigned * column,const char * s,size_t n)2296 static void inc_lines_columns(unsigned *line, unsigned *column, const char *s, size_t n) {
2297         assert(line);
2298         assert(column);
2299         assert(s || n == 0);
2300 
2301         while (n > 0) {
2302                 if (*s == '\n') {
2303                         (*line)++;
2304                         *column = 1;
2305                 } else if ((signed char) *s >= 0 && *s < 127) /* Process ASCII chars quickly */
2306                         (*column)++;
2307                 else {
2308                         int w;
2309 
2310                         w = utf8_encoded_valid_unichar(s, n);
2311                         if (w < 0) /* count invalid unichars as normal characters */
2312                                 w = 1;
2313                         else if ((size_t) w > n) /* never read more than the specified number of characters */
2314                                 w = (int) n;
2315 
2316                         (*column)++;
2317 
2318                         s += w;
2319                         n -= w;
2320                         continue;
2321                 }
2322 
2323                 s++;
2324                 n--;
2325         }
2326 }
2327 
unhex_ucs2(const char * c,uint16_t * ret)2328 static int unhex_ucs2(const char *c, uint16_t *ret) {
2329         int aa, bb, cc, dd;
2330         uint16_t x;
2331 
2332         assert(c);
2333         assert(ret);
2334 
2335         aa = unhexchar(c[0]);
2336         if (aa < 0)
2337                 return -EINVAL;
2338 
2339         bb = unhexchar(c[1]);
2340         if (bb < 0)
2341                 return -EINVAL;
2342 
2343         cc = unhexchar(c[2]);
2344         if (cc < 0)
2345                 return -EINVAL;
2346 
2347         dd = unhexchar(c[3]);
2348         if (dd < 0)
2349                 return -EINVAL;
2350 
2351         x =     ((uint16_t) aa << 12) |
2352                 ((uint16_t) bb << 8) |
2353                 ((uint16_t) cc << 4) |
2354                 ((uint16_t) dd);
2355 
2356         if (x <= 0)
2357                 return -EINVAL;
2358 
2359         *ret = x;
2360 
2361         return 0;
2362 }
2363 
json_parse_string(const char ** p,char ** ret)2364 static int json_parse_string(const char **p, char **ret) {
2365         _cleanup_free_ char *s = NULL;
2366         size_t n = 0;
2367         const char *c;
2368 
2369         assert(p);
2370         assert(*p);
2371         assert(ret);
2372 
2373         c = *p;
2374 
2375         if (*c != '"')
2376                 return -EINVAL;
2377 
2378         c++;
2379 
2380         for (;;) {
2381                 int len;
2382 
2383                 /* Check for EOF */
2384                 if (*c == 0)
2385                         return -EINVAL;
2386 
2387                 /* Check for control characters 0x00..0x1f */
2388                 if (*c > 0 && *c < ' ')
2389                         return -EINVAL;
2390 
2391                 /* Check for control character 0x7f */
2392                 if (*c == 0x7f)
2393                         return -EINVAL;
2394 
2395                 if (*c == '"') {
2396                         if (!s) {
2397                                 s = strdup("");
2398                                 if (!s)
2399                                         return -ENOMEM;
2400                         } else
2401                                 s[n] = 0;
2402 
2403                         *p = c + 1;
2404 
2405                         *ret = TAKE_PTR(s);
2406                         return JSON_TOKEN_STRING;
2407                 }
2408 
2409                 if (*c == '\\') {
2410                         char ch = 0;
2411                         c++;
2412 
2413                         if (*c == 0)
2414                                 return -EINVAL;
2415 
2416                         if (IN_SET(*c, '"', '\\', '/'))
2417                                 ch = *c;
2418                         else if (*c == 'b')
2419                                 ch = '\b';
2420                         else if (*c == 'f')
2421                                 ch = '\f';
2422                         else if (*c == 'n')
2423                                 ch = '\n';
2424                         else if (*c == 'r')
2425                                 ch = '\r';
2426                         else if (*c == 't')
2427                                 ch = '\t';
2428                         else if (*c == 'u') {
2429                                 char16_t x;
2430                                 int r;
2431 
2432                                 r = unhex_ucs2(c + 1, &x);
2433                                 if (r < 0)
2434                                         return r;
2435 
2436                                 c += 5;
2437 
2438                                 if (!GREEDY_REALLOC(s, n + 5))
2439                                         return -ENOMEM;
2440 
2441                                 if (!utf16_is_surrogate(x))
2442                                         n += utf8_encode_unichar(s + n, (char32_t) x);
2443                                 else if (utf16_is_trailing_surrogate(x))
2444                                         return -EINVAL;
2445                                 else {
2446                                         char16_t y;
2447 
2448                                         if (c[0] != '\\' || c[1] != 'u')
2449                                                 return -EINVAL;
2450 
2451                                         r = unhex_ucs2(c + 2, &y);
2452                                         if (r < 0)
2453                                                 return r;
2454 
2455                                         c += 6;
2456 
2457                                         if (!utf16_is_trailing_surrogate(y))
2458                                                 return -EINVAL;
2459 
2460                                         n += utf8_encode_unichar(s + n, utf16_surrogate_pair_to_unichar(x, y));
2461                                 }
2462 
2463                                 continue;
2464                         } else
2465                                 return -EINVAL;
2466 
2467                         if (!GREEDY_REALLOC(s, n + 2))
2468                                 return -ENOMEM;
2469 
2470                         s[n++] = ch;
2471                         c ++;
2472                         continue;
2473                 }
2474 
2475                 len = utf8_encoded_valid_unichar(c, SIZE_MAX);
2476                 if (len < 0)
2477                         return len;
2478 
2479                 if (!GREEDY_REALLOC(s, n + len + 1))
2480                         return -ENOMEM;
2481 
2482                 memcpy(s + n, c, len);
2483                 n += len;
2484                 c += len;
2485         }
2486 }
2487 
json_parse_number(const char ** p,JsonValue * ret)2488 static int json_parse_number(const char **p, JsonValue *ret) {
2489         bool negative = false, exponent_negative = false, is_real = false;
2490         double x = 0.0, y = 0.0, exponent = 0.0, shift = 1.0;
2491         int64_t i = 0;
2492         uint64_t u = 0;
2493         const char *c;
2494 
2495         assert(p);
2496         assert(*p);
2497         assert(ret);
2498 
2499         c = *p;
2500 
2501         if (*c == '-') {
2502                 negative = true;
2503                 c++;
2504         }
2505 
2506         if (*c == '0')
2507                 c++;
2508         else {
2509                 if (!strchr("123456789", *c) || *c == 0)
2510                         return -EINVAL;
2511 
2512                 do {
2513                         if (!is_real) {
2514                                 if (negative) {
2515 
2516                                         if (i < INT64_MIN / 10) /* overflow */
2517                                                 is_real = true;
2518                                         else {
2519                                                 int64_t t = 10 * i;
2520 
2521                                                 if (t < INT64_MIN + (*c - '0')) /* overflow */
2522                                                         is_real = true;
2523                                                 else
2524                                                         i = t - (*c - '0');
2525                                         }
2526                                 } else {
2527                                         if (u > UINT64_MAX / 10) /* overflow */
2528                                                 is_real = true;
2529                                         else {
2530                                                 uint64_t t = 10 * u;
2531 
2532                                                 if (t > UINT64_MAX - (*c - '0')) /* overflow */
2533                                                         is_real = true;
2534                                                 else
2535                                                         u = t + (*c - '0');
2536                                         }
2537                                 }
2538                         }
2539 
2540                         x = 10.0 * x + (*c - '0');
2541 
2542                         c++;
2543                 } while (strchr("0123456789", *c) && *c != 0);
2544         }
2545 
2546         if (*c == '.') {
2547                 is_real = true;
2548                 c++;
2549 
2550                 if (!strchr("0123456789", *c) || *c == 0)
2551                         return -EINVAL;
2552 
2553                 do {
2554                         y = 10.0 * y + (*c - '0');
2555                         shift = 10.0 * shift;
2556                         c++;
2557                 } while (strchr("0123456789", *c) && *c != 0);
2558         }
2559 
2560         if (IN_SET(*c, 'e', 'E')) {
2561                 is_real = true;
2562                 c++;
2563 
2564                 if (*c == '-') {
2565                         exponent_negative = true;
2566                         c++;
2567                 } else if (*c == '+')
2568                         c++;
2569 
2570                 if (!strchr("0123456789", *c) || *c == 0)
2571                         return -EINVAL;
2572 
2573                 do {
2574                         exponent = 10.0 * exponent + (*c - '0');
2575                         c++;
2576                 } while (strchr("0123456789", *c) && *c != 0);
2577         }
2578 
2579         *p = c;
2580 
2581         if (is_real) {
2582                 ret->real = ((negative ? -1.0 : 1.0) * (x + (y / shift))) * exp10((exponent_negative ? -1.0 : 1.0) * exponent);
2583                 return JSON_TOKEN_REAL;
2584         } else if (negative) {
2585                 ret->integer = i;
2586                 return JSON_TOKEN_INTEGER;
2587         } else  {
2588                 ret->unsig = u;
2589                 return JSON_TOKEN_UNSIGNED;
2590         }
2591 }
2592 
json_tokenize(const char ** p,char ** ret_string,JsonValue * ret_value,unsigned * ret_line,unsigned * ret_column,void ** state,unsigned * line,unsigned * column)2593 int json_tokenize(
2594                 const char **p,
2595                 char **ret_string,
2596                 JsonValue *ret_value,
2597                 unsigned *ret_line,   /* 'ret_line' returns the line at the beginning of this token */
2598                 unsigned *ret_column,
2599                 void **state,
2600                 unsigned *line,       /* 'line' is used as a line state, it always reflect the line we are at after the token was read */
2601                 unsigned *column) {
2602 
2603         unsigned start_line, start_column;
2604         const char *start, *c;
2605         size_t n;
2606         int t, r;
2607 
2608         enum {
2609                 STATE_NULL,
2610                 STATE_VALUE,
2611                 STATE_VALUE_POST,
2612         };
2613 
2614         assert(p);
2615         assert(*p);
2616         assert(ret_string);
2617         assert(ret_value);
2618         assert(ret_line);
2619         assert(ret_column);
2620         assert(line);
2621         assert(column);
2622         assert(state);
2623 
2624         t = PTR_TO_INT(*state);
2625         if (t == STATE_NULL) {
2626                 *line = 1;
2627                 *column = 1;
2628                 t = STATE_VALUE;
2629         }
2630 
2631         /* Skip over the whitespace */
2632         n = strspn(*p, WHITESPACE);
2633         inc_lines_columns(line, column, *p, n);
2634         c = *p + n;
2635 
2636         /* Remember where we started processing this token */
2637         start = c;
2638         start_line = *line;
2639         start_column = *column;
2640 
2641         if (*c == 0) {
2642                 *ret_string = NULL;
2643                 *ret_value = JSON_VALUE_NULL;
2644                 r = JSON_TOKEN_END;
2645                 goto finish;
2646         }
2647 
2648         switch (t) {
2649 
2650         case STATE_VALUE:
2651 
2652                 if (*c == '{') {
2653                         c++;
2654                         *state = INT_TO_PTR(STATE_VALUE);
2655                         r = JSON_TOKEN_OBJECT_OPEN;
2656                         goto null_return;
2657 
2658                 } else if (*c == '}') {
2659                         c++;
2660                         *state = INT_TO_PTR(STATE_VALUE_POST);
2661                         r = JSON_TOKEN_OBJECT_CLOSE;
2662                         goto null_return;
2663 
2664                 } else if (*c == '[') {
2665                         c++;
2666                         *state = INT_TO_PTR(STATE_VALUE);
2667                         r = JSON_TOKEN_ARRAY_OPEN;
2668                         goto null_return;
2669 
2670                 } else if (*c == ']') {
2671                         c++;
2672                         *state = INT_TO_PTR(STATE_VALUE_POST);
2673                         r = JSON_TOKEN_ARRAY_CLOSE;
2674                         goto null_return;
2675 
2676                 } else if (*c == '"') {
2677 
2678                         r = json_parse_string(&c, ret_string);
2679                         if (r < 0)
2680                                 return r;
2681 
2682                         *ret_value = JSON_VALUE_NULL;
2683                         *state = INT_TO_PTR(STATE_VALUE_POST);
2684                         goto finish;
2685 
2686                 } else if (strchr("-0123456789", *c)) {
2687 
2688                         r = json_parse_number(&c, ret_value);
2689                         if (r < 0)
2690                                 return r;
2691 
2692                         *ret_string = NULL;
2693                         *state = INT_TO_PTR(STATE_VALUE_POST);
2694                         goto finish;
2695 
2696                 } else if (startswith(c, "true")) {
2697                         *ret_string = NULL;
2698                         ret_value->boolean = true;
2699                         c += 4;
2700                         *state = INT_TO_PTR(STATE_VALUE_POST);
2701                         r = JSON_TOKEN_BOOLEAN;
2702                         goto finish;
2703 
2704                 } else if (startswith(c, "false")) {
2705                         *ret_string = NULL;
2706                         ret_value->boolean = false;
2707                         c += 5;
2708                         *state = INT_TO_PTR(STATE_VALUE_POST);
2709                         r = JSON_TOKEN_BOOLEAN;
2710                         goto finish;
2711 
2712                 } else if (startswith(c, "null")) {
2713                         *ret_string = NULL;
2714                         *ret_value = JSON_VALUE_NULL;
2715                         c += 4;
2716                         *state = INT_TO_PTR(STATE_VALUE_POST);
2717                         r = JSON_TOKEN_NULL;
2718                         goto finish;
2719 
2720                 }
2721 
2722                 return -EINVAL;
2723 
2724         case STATE_VALUE_POST:
2725 
2726                 if (*c == ':') {
2727                         c++;
2728                         *state = INT_TO_PTR(STATE_VALUE);
2729                         r = JSON_TOKEN_COLON;
2730                         goto null_return;
2731 
2732                 } else if (*c == ',') {
2733                         c++;
2734                         *state = INT_TO_PTR(STATE_VALUE);
2735                         r = JSON_TOKEN_COMMA;
2736                         goto null_return;
2737 
2738                 } else if (*c == '}') {
2739                         c++;
2740                         *state = INT_TO_PTR(STATE_VALUE_POST);
2741                         r = JSON_TOKEN_OBJECT_CLOSE;
2742                         goto null_return;
2743 
2744                 } else if (*c == ']') {
2745                         c++;
2746                         *state = INT_TO_PTR(STATE_VALUE_POST);
2747                         r = JSON_TOKEN_ARRAY_CLOSE;
2748                         goto null_return;
2749                 }
2750 
2751                 return -EINVAL;
2752 
2753         default:
2754                 assert_not_reached();
2755         }
2756 
2757 null_return:
2758         *ret_string = NULL;
2759         *ret_value = JSON_VALUE_NULL;
2760 
2761 finish:
2762         inc_lines_columns(line, column, start, c - start);
2763         *p = c;
2764 
2765         *ret_line = start_line;
2766         *ret_column = start_column;
2767 
2768         return r;
2769 }
2770 
2771 typedef enum JsonExpect {
2772         /* The following values are used by json_parse() */
2773         EXPECT_TOPLEVEL,
2774         EXPECT_END,
2775         EXPECT_OBJECT_FIRST_KEY,
2776         EXPECT_OBJECT_NEXT_KEY,
2777         EXPECT_OBJECT_COLON,
2778         EXPECT_OBJECT_VALUE,
2779         EXPECT_OBJECT_COMMA,
2780         EXPECT_ARRAY_FIRST_ELEMENT,
2781         EXPECT_ARRAY_NEXT_ELEMENT,
2782         EXPECT_ARRAY_COMMA,
2783 
2784         /* And these are used by json_build() */
2785         EXPECT_ARRAY_ELEMENT,
2786         EXPECT_OBJECT_KEY,
2787 } JsonExpect;
2788 
2789 typedef struct JsonStack {
2790         JsonExpect expect;
2791         JsonVariant **elements;
2792         size_t n_elements;
2793         unsigned line_before;
2794         unsigned column_before;
2795         size_t n_suppress; /* When building: if > 0, suppress this many subsequent elements. If == SIZE_MAX, suppress all subsequent elements */
2796 } JsonStack;
2797 
json_stack_release(JsonStack * s)2798 static void json_stack_release(JsonStack *s) {
2799         assert(s);
2800 
2801         json_variant_unref_many(s->elements, s->n_elements);
2802         s->elements = mfree(s->elements);
2803 }
2804 
json_parse_internal(const char ** input,JsonSource * source,JsonParseFlags flags,JsonVariant ** ret,unsigned * line,unsigned * column,bool continue_end)2805 static int json_parse_internal(
2806                 const char **input,
2807                 JsonSource *source,
2808                 JsonParseFlags flags,
2809                 JsonVariant **ret,
2810                 unsigned *line,
2811                 unsigned *column,
2812                 bool continue_end) {
2813 
2814         size_t n_stack = 1;
2815         unsigned line_buffer = 0, column_buffer = 0;
2816         void *tokenizer_state = NULL;
2817         JsonStack *stack = NULL;
2818         const char *p;
2819         int r;
2820 
2821         assert_return(input, -EINVAL);
2822         assert_return(ret, -EINVAL);
2823 
2824         p = *input;
2825 
2826         if (!GREEDY_REALLOC(stack, n_stack))
2827                 return -ENOMEM;
2828 
2829         stack[0] = (JsonStack) {
2830                 .expect = EXPECT_TOPLEVEL,
2831         };
2832 
2833         if (!line)
2834                 line = &line_buffer;
2835         if (!column)
2836                 column = &column_buffer;
2837 
2838         for (;;) {
2839                 _cleanup_(json_variant_unrefp) JsonVariant *add = NULL;
2840                 _cleanup_free_ char *string = NULL;
2841                 unsigned line_token, column_token;
2842                 JsonStack *current;
2843                 JsonValue value;
2844                 int token;
2845 
2846                 assert(n_stack > 0);
2847                 current = stack + n_stack - 1;
2848 
2849                 if (continue_end && current->expect == EXPECT_END)
2850                         goto done;
2851 
2852                 token = json_tokenize(&p, &string, &value, &line_token, &column_token, &tokenizer_state, line, column);
2853                 if (token < 0) {
2854                         r = token;
2855                         goto finish;
2856                 }
2857 
2858                 switch (token) {
2859 
2860                 case JSON_TOKEN_END:
2861                         if (current->expect != EXPECT_END) {
2862                                 r = -EINVAL;
2863                                 goto finish;
2864                         }
2865 
2866                         assert(current->n_elements == 1);
2867                         assert(n_stack == 1);
2868                         goto done;
2869 
2870                 case JSON_TOKEN_COLON:
2871 
2872                         if (current->expect != EXPECT_OBJECT_COLON) {
2873                                 r = -EINVAL;
2874                                 goto finish;
2875                         }
2876 
2877                         current->expect = EXPECT_OBJECT_VALUE;
2878                         break;
2879 
2880                 case JSON_TOKEN_COMMA:
2881 
2882                         if (current->expect == EXPECT_OBJECT_COMMA)
2883                                 current->expect = EXPECT_OBJECT_NEXT_KEY;
2884                         else if (current->expect == EXPECT_ARRAY_COMMA)
2885                                 current->expect = EXPECT_ARRAY_NEXT_ELEMENT;
2886                         else {
2887                                 r = -EINVAL;
2888                                 goto finish;
2889                         }
2890 
2891                         break;
2892 
2893                 case JSON_TOKEN_OBJECT_OPEN:
2894 
2895                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
2896                                 r = -EINVAL;
2897                                 goto finish;
2898                         }
2899 
2900                         if (!GREEDY_REALLOC(stack, n_stack+1)) {
2901                                 r = -ENOMEM;
2902                                 goto finish;
2903                         }
2904                         current = stack + n_stack - 1;
2905 
2906                         /* Prepare the expect for when we return from the child */
2907                         if (current->expect == EXPECT_TOPLEVEL)
2908                                 current->expect = EXPECT_END;
2909                         else if (current->expect == EXPECT_OBJECT_VALUE)
2910                                 current->expect = EXPECT_OBJECT_COMMA;
2911                         else {
2912                                 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
2913                                 current->expect = EXPECT_ARRAY_COMMA;
2914                         }
2915 
2916                         stack[n_stack++] = (JsonStack) {
2917                                 .expect = EXPECT_OBJECT_FIRST_KEY,
2918                                 .line_before = line_token,
2919                                 .column_before = column_token,
2920                         };
2921 
2922                         current = stack + n_stack - 1;
2923                         break;
2924 
2925                 case JSON_TOKEN_OBJECT_CLOSE:
2926                         if (!IN_SET(current->expect, EXPECT_OBJECT_FIRST_KEY, EXPECT_OBJECT_COMMA)) {
2927                                 r = -EINVAL;
2928                                 goto finish;
2929                         }
2930 
2931                         assert(n_stack > 1);
2932 
2933                         r = json_variant_new_object(&add, current->elements, current->n_elements);
2934                         if (r < 0)
2935                                 goto finish;
2936 
2937                         line_token = current->line_before;
2938                         column_token = current->column_before;
2939 
2940                         json_stack_release(current);
2941                         n_stack--, current--;
2942 
2943                         break;
2944 
2945                 case JSON_TOKEN_ARRAY_OPEN:
2946                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
2947                                 r = -EINVAL;
2948                                 goto finish;
2949                         }
2950 
2951                         if (!GREEDY_REALLOC(stack, n_stack+1)) {
2952                                 r = -ENOMEM;
2953                                 goto finish;
2954                         }
2955                         current = stack + n_stack - 1;
2956 
2957                         /* Prepare the expect for when we return from the child */
2958                         if (current->expect == EXPECT_TOPLEVEL)
2959                                 current->expect = EXPECT_END;
2960                         else if (current->expect == EXPECT_OBJECT_VALUE)
2961                                 current->expect = EXPECT_OBJECT_COMMA;
2962                         else {
2963                                 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
2964                                 current->expect = EXPECT_ARRAY_COMMA;
2965                         }
2966 
2967                         stack[n_stack++] = (JsonStack) {
2968                                 .expect = EXPECT_ARRAY_FIRST_ELEMENT,
2969                                 .line_before = line_token,
2970                                 .column_before = column_token,
2971                         };
2972 
2973                         break;
2974 
2975                 case JSON_TOKEN_ARRAY_CLOSE:
2976                         if (!IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_COMMA)) {
2977                                 r = -EINVAL;
2978                                 goto finish;
2979                         }
2980 
2981                         assert(n_stack > 1);
2982 
2983                         r = json_variant_new_array(&add, current->elements, current->n_elements);
2984                         if (r < 0)
2985                                 goto finish;
2986 
2987                         line_token = current->line_before;
2988                         column_token = current->column_before;
2989 
2990                         json_stack_release(current);
2991                         n_stack--, current--;
2992                         break;
2993 
2994                 case JSON_TOKEN_STRING:
2995                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_FIRST_KEY, EXPECT_OBJECT_NEXT_KEY, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
2996                                 r = -EINVAL;
2997                                 goto finish;
2998                         }
2999 
3000                         r = json_variant_new_string(&add, string);
3001                         if (r < 0)
3002                                 goto finish;
3003 
3004                         if (current->expect == EXPECT_TOPLEVEL)
3005                                 current->expect = EXPECT_END;
3006                         else if (IN_SET(current->expect, EXPECT_OBJECT_FIRST_KEY, EXPECT_OBJECT_NEXT_KEY))
3007                                 current->expect = EXPECT_OBJECT_COLON;
3008                         else if (current->expect == EXPECT_OBJECT_VALUE)
3009                                 current->expect = EXPECT_OBJECT_COMMA;
3010                         else {
3011                                 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
3012                                 current->expect = EXPECT_ARRAY_COMMA;
3013                         }
3014 
3015                         break;
3016 
3017                 case JSON_TOKEN_REAL:
3018                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
3019                                 r = -EINVAL;
3020                                 goto finish;
3021                         }
3022 
3023                         r = json_variant_new_real(&add, value.real);
3024                         if (r < 0)
3025                                 goto finish;
3026 
3027                         if (current->expect == EXPECT_TOPLEVEL)
3028                                 current->expect = EXPECT_END;
3029                         else if (current->expect == EXPECT_OBJECT_VALUE)
3030                                 current->expect = EXPECT_OBJECT_COMMA;
3031                         else {
3032                                 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
3033                                 current->expect = EXPECT_ARRAY_COMMA;
3034                         }
3035 
3036                         break;
3037 
3038                 case JSON_TOKEN_INTEGER:
3039                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
3040                                 r = -EINVAL;
3041                                 goto finish;
3042                         }
3043 
3044                         r = json_variant_new_integer(&add, value.integer);
3045                         if (r < 0)
3046                                 goto finish;
3047 
3048                         if (current->expect == EXPECT_TOPLEVEL)
3049                                 current->expect = EXPECT_END;
3050                         else if (current->expect == EXPECT_OBJECT_VALUE)
3051                                 current->expect = EXPECT_OBJECT_COMMA;
3052                         else {
3053                                 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
3054                                 current->expect = EXPECT_ARRAY_COMMA;
3055                         }
3056 
3057                         break;
3058 
3059                 case JSON_TOKEN_UNSIGNED:
3060                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
3061                                 r = -EINVAL;
3062                                 goto finish;
3063                         }
3064 
3065                         r = json_variant_new_unsigned(&add, value.unsig);
3066                         if (r < 0)
3067                                 goto finish;
3068 
3069                         if (current->expect == EXPECT_TOPLEVEL)
3070                                 current->expect = EXPECT_END;
3071                         else if (current->expect == EXPECT_OBJECT_VALUE)
3072                                 current->expect = EXPECT_OBJECT_COMMA;
3073                         else {
3074                                 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
3075                                 current->expect = EXPECT_ARRAY_COMMA;
3076                         }
3077 
3078                         break;
3079 
3080                 case JSON_TOKEN_BOOLEAN:
3081                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
3082                                 r = -EINVAL;
3083                                 goto finish;
3084                         }
3085 
3086                         r = json_variant_new_boolean(&add, value.boolean);
3087                         if (r < 0)
3088                                 goto finish;
3089 
3090                         if (current->expect == EXPECT_TOPLEVEL)
3091                                 current->expect = EXPECT_END;
3092                         else if (current->expect == EXPECT_OBJECT_VALUE)
3093                                 current->expect = EXPECT_OBJECT_COMMA;
3094                         else {
3095                                 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
3096                                 current->expect = EXPECT_ARRAY_COMMA;
3097                         }
3098 
3099                         break;
3100 
3101                 case JSON_TOKEN_NULL:
3102                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
3103                                 r = -EINVAL;
3104                                 goto finish;
3105                         }
3106 
3107                         r = json_variant_new_null(&add);
3108                         if (r < 0)
3109                                 goto finish;
3110 
3111                         if (current->expect == EXPECT_TOPLEVEL)
3112                                 current->expect = EXPECT_END;
3113                         else if (current->expect == EXPECT_OBJECT_VALUE)
3114                                 current->expect = EXPECT_OBJECT_COMMA;
3115                         else {
3116                                 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
3117                                 current->expect = EXPECT_ARRAY_COMMA;
3118                         }
3119 
3120                         break;
3121 
3122                 default:
3123                         assert_not_reached();
3124                 }
3125 
3126                 if (add) {
3127                         /* If we are asked to make this parsed object sensitive, then let's apply this
3128                          * immediately after allocating each variant, so that when we abort half-way
3129                          * everything we already allocated that is then freed is correctly marked. */
3130                         if (FLAGS_SET(flags, JSON_PARSE_SENSITIVE))
3131                                 json_variant_sensitive(add);
3132 
3133                         (void) json_variant_set_source(&add, source, line_token, column_token);
3134 
3135                         if (!GREEDY_REALLOC(current->elements, current->n_elements + 1)) {
3136                                 r = -ENOMEM;
3137                                 goto finish;
3138                         }
3139 
3140                         current->elements[current->n_elements++] = TAKE_PTR(add);
3141                 }
3142         }
3143 
3144 done:
3145         assert(n_stack == 1);
3146         assert(stack[0].n_elements == 1);
3147 
3148         *ret = json_variant_ref(stack[0].elements[0]);
3149         *input = p;
3150         r = 0;
3151 
3152 finish:
3153         for (size_t i = 0; i < n_stack; i++)
3154                 json_stack_release(stack + i);
3155 
3156         free(stack);
3157 
3158         return r;
3159 }
3160 
json_parse(const char * input,JsonParseFlags flags,JsonVariant ** ret,unsigned * ret_line,unsigned * ret_column)3161 int json_parse(const char *input, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
3162         return json_parse_internal(&input, NULL, flags, ret, ret_line, ret_column, false);
3163 }
3164 
json_parse_continue(const char ** p,JsonParseFlags flags,JsonVariant ** ret,unsigned * ret_line,unsigned * ret_column)3165 int json_parse_continue(const char **p, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
3166         return json_parse_internal(p, NULL, flags, ret, ret_line, ret_column, true);
3167 }
3168 
json_parse_file_at(FILE * f,int dir_fd,const char * path,JsonParseFlags flags,JsonVariant ** ret,unsigned * ret_line,unsigned * ret_column)3169 int json_parse_file_at(FILE *f, int dir_fd, const char *path, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
3170         _cleanup_(json_source_unrefp) JsonSource *source = NULL;
3171         _cleanup_free_ char *text = NULL;
3172         const char *p;
3173         int r;
3174 
3175         if (f)
3176                 r = read_full_stream(f, &text, NULL);
3177         else if (path)
3178                 r = read_full_file_full(dir_fd, path, UINT64_MAX, SIZE_MAX, 0, NULL, &text, NULL);
3179         else
3180                 return -EINVAL;
3181         if (r < 0)
3182                 return r;
3183 
3184         if (path) {
3185                 source = json_source_new(path);
3186                 if (!source)
3187                         return -ENOMEM;
3188         }
3189 
3190         p = text;
3191         return json_parse_internal(&p, source, flags, ret, ret_line, ret_column, false);
3192 }
3193 
json_buildv(JsonVariant ** ret,va_list ap)3194 int json_buildv(JsonVariant **ret, va_list ap) {
3195         JsonStack *stack = NULL;
3196         size_t n_stack = 1;
3197         int r;
3198 
3199         assert_return(ret, -EINVAL);
3200 
3201         if (!GREEDY_REALLOC(stack, n_stack))
3202                 return -ENOMEM;
3203 
3204         stack[0] = (JsonStack) {
3205                 .expect = EXPECT_TOPLEVEL,
3206         };
3207 
3208         for (;;) {
3209                 _cleanup_(json_variant_unrefp) JsonVariant *add = NULL, *add_more = NULL;
3210                 size_t n_subtract = 0; /* how much to subtract from current->n_suppress, i.e. how many elements would
3211                                         * have been added to the current variant */
3212                 JsonStack *current;
3213                 int command;
3214 
3215                 assert(n_stack > 0);
3216                 current = stack + n_stack - 1;
3217 
3218                 if (current->expect == EXPECT_END)
3219                         goto done;
3220 
3221                 command = va_arg(ap, int);
3222 
3223                 switch (command) {
3224 
3225                 case _JSON_BUILD_STRING: {
3226                         const char *p;
3227 
3228                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
3229                                 r = -EINVAL;
3230                                 goto finish;
3231                         }
3232 
3233                         p = va_arg(ap, const char *);
3234 
3235                         if (current->n_suppress == 0) {
3236                                 r = json_variant_new_string(&add, p);
3237                                 if (r < 0)
3238                                         goto finish;
3239                         }
3240 
3241                         n_subtract = 1;
3242 
3243                         if (current->expect == EXPECT_TOPLEVEL)
3244                                 current->expect = EXPECT_END;
3245                         else if (current->expect == EXPECT_OBJECT_VALUE)
3246                                 current->expect = EXPECT_OBJECT_KEY;
3247                         else
3248                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
3249 
3250                         break;
3251                 }
3252 
3253                 case _JSON_BUILD_INTEGER: {
3254                         int64_t j;
3255 
3256                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
3257                                 r = -EINVAL;
3258                                 goto finish;
3259                         }
3260 
3261                         j = va_arg(ap, int64_t);
3262 
3263                         if (current->n_suppress == 0) {
3264                                 r = json_variant_new_integer(&add, j);
3265                                 if (r < 0)
3266                                         goto finish;
3267                         }
3268 
3269                         n_subtract = 1;
3270 
3271                         if (current->expect == EXPECT_TOPLEVEL)
3272                                 current->expect = EXPECT_END;
3273                         else if (current->expect == EXPECT_OBJECT_VALUE)
3274                                 current->expect = EXPECT_OBJECT_KEY;
3275                         else
3276                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
3277 
3278                         break;
3279                 }
3280 
3281                 case _JSON_BUILD_UNSIGNED: {
3282                         uint64_t j;
3283 
3284                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
3285                                 r = -EINVAL;
3286                                 goto finish;
3287                         }
3288 
3289                         j = va_arg(ap, uint64_t);
3290 
3291                         if (current->n_suppress == 0) {
3292                                 r = json_variant_new_unsigned(&add, j);
3293                                 if (r < 0)
3294                                         goto finish;
3295                         }
3296 
3297                         n_subtract = 1;
3298 
3299                         if (current->expect == EXPECT_TOPLEVEL)
3300                                 current->expect = EXPECT_END;
3301                         else if (current->expect == EXPECT_OBJECT_VALUE)
3302                                 current->expect = EXPECT_OBJECT_KEY;
3303                         else
3304                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
3305 
3306                         break;
3307                 }
3308 
3309                 case _JSON_BUILD_REAL: {
3310                         double d;
3311 
3312                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
3313                                 r = -EINVAL;
3314                                 goto finish;
3315                         }
3316 
3317                         d = va_arg(ap, double);
3318 
3319                         if (current->n_suppress == 0) {
3320                                 r = json_variant_new_real(&add, d);
3321                                 if (r < 0)
3322                                         goto finish;
3323                         }
3324 
3325                         n_subtract = 1;
3326 
3327                         if (current->expect == EXPECT_TOPLEVEL)
3328                                 current->expect = EXPECT_END;
3329                         else if (current->expect == EXPECT_OBJECT_VALUE)
3330                                 current->expect = EXPECT_OBJECT_KEY;
3331                         else
3332                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
3333 
3334                         break;
3335                 }
3336 
3337                 case _JSON_BUILD_BOOLEAN: {
3338                         bool b;
3339 
3340                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
3341                                 r = -EINVAL;
3342                                 goto finish;
3343                         }
3344 
3345                         b = va_arg(ap, int);
3346 
3347                         if (current->n_suppress == 0) {
3348                                 r = json_variant_new_boolean(&add, b);
3349                                 if (r < 0)
3350                                         goto finish;
3351                         }
3352 
3353                         n_subtract = 1;
3354 
3355                         if (current->expect == EXPECT_TOPLEVEL)
3356                                 current->expect = EXPECT_END;
3357                         else if (current->expect == EXPECT_OBJECT_VALUE)
3358                                 current->expect = EXPECT_OBJECT_KEY;
3359                         else
3360                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
3361 
3362                         break;
3363                 }
3364 
3365                 case _JSON_BUILD_NULL:
3366 
3367                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
3368                                 r = -EINVAL;
3369                                 goto finish;
3370                         }
3371 
3372                         if (current->n_suppress == 0) {
3373                                 r = json_variant_new_null(&add);
3374                                 if (r < 0)
3375                                         goto finish;
3376                         }
3377 
3378                         n_subtract = 1;
3379 
3380                         if (current->expect == EXPECT_TOPLEVEL)
3381                                 current->expect = EXPECT_END;
3382                         else if (current->expect == EXPECT_OBJECT_VALUE)
3383                                 current->expect = EXPECT_OBJECT_KEY;
3384                         else
3385                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
3386 
3387                         break;
3388 
3389                 case _JSON_BUILD_VARIANT:
3390 
3391                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
3392                                 r = -EINVAL;
3393                                 goto finish;
3394                         }
3395 
3396                         /* Note that we don't care for current->n_suppress here, after all the variant is already
3397                          * allocated anyway... */
3398                         add = va_arg(ap, JsonVariant*);
3399                         if (!add)
3400                                 add = JSON_VARIANT_MAGIC_NULL;
3401                         else
3402                                 json_variant_ref(add);
3403 
3404                         n_subtract = 1;
3405 
3406                         if (current->expect == EXPECT_TOPLEVEL)
3407                                 current->expect = EXPECT_END;
3408                         else if (current->expect == EXPECT_OBJECT_VALUE)
3409                                 current->expect = EXPECT_OBJECT_KEY;
3410                         else
3411                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
3412 
3413                         break;
3414 
3415                 case _JSON_BUILD_VARIANT_ARRAY: {
3416                         JsonVariant **array;
3417                         size_t n;
3418 
3419                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
3420                                 r = -EINVAL;
3421                                 goto finish;
3422                         }
3423 
3424                         array = va_arg(ap, JsonVariant**);
3425                         n = va_arg(ap, size_t);
3426 
3427                         if (current->n_suppress == 0) {
3428                                 r = json_variant_new_array(&add, array, n);
3429                                 if (r < 0)
3430                                         goto finish;
3431                         }
3432 
3433                         n_subtract = 1;
3434 
3435                         if (current->expect == EXPECT_TOPLEVEL)
3436                                 current->expect = EXPECT_END;
3437                         else if (current->expect == EXPECT_OBJECT_VALUE)
3438                                 current->expect = EXPECT_OBJECT_KEY;
3439                         else
3440                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
3441 
3442                         break;
3443                 }
3444 
3445                 case _JSON_BUILD_LITERAL: {
3446                         const char *l;
3447 
3448                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
3449                                 r = -EINVAL;
3450                                 goto finish;
3451                         }
3452 
3453                         l = va_arg(ap, const char *);
3454 
3455                         if (l) {
3456                                 /* Note that we don't care for current->n_suppress here, we should generate parsing
3457                                  * errors even in suppressed object properties */
3458 
3459                                 r = json_parse(l, 0, &add, NULL, NULL);
3460                                 if (r < 0)
3461                                         goto finish;
3462                         } else
3463                                 add = JSON_VARIANT_MAGIC_NULL;
3464 
3465                         n_subtract = 1;
3466 
3467                         if (current->expect == EXPECT_TOPLEVEL)
3468                                 current->expect = EXPECT_END;
3469                         else if (current->expect == EXPECT_OBJECT_VALUE)
3470                                 current->expect = EXPECT_OBJECT_KEY;
3471                         else
3472                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
3473 
3474                         break;
3475                 }
3476 
3477                 case _JSON_BUILD_ARRAY_BEGIN:
3478 
3479                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
3480                                 r = -EINVAL;
3481                                 goto finish;
3482                         }
3483 
3484                         if (!GREEDY_REALLOC(stack, n_stack+1)) {
3485                                 r = -ENOMEM;
3486                                 goto finish;
3487                         }
3488                         current = stack + n_stack - 1;
3489 
3490                         if (current->expect == EXPECT_TOPLEVEL)
3491                                 current->expect = EXPECT_END;
3492                         else if (current->expect == EXPECT_OBJECT_VALUE)
3493                                 current->expect = EXPECT_OBJECT_KEY;
3494                         else
3495                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
3496 
3497                         stack[n_stack++] = (JsonStack) {
3498                                 .expect = EXPECT_ARRAY_ELEMENT,
3499                                 .n_suppress = current->n_suppress != 0 ? SIZE_MAX : 0, /* if we shall suppress the
3500                                                                                            * new array, then we should
3501                                                                                            * also suppress all array
3502                                                                                            * members */
3503                         };
3504 
3505                         break;
3506 
3507                 case _JSON_BUILD_ARRAY_END:
3508                         if (current->expect != EXPECT_ARRAY_ELEMENT) {
3509                                 r = -EINVAL;
3510                                 goto finish;
3511                         }
3512 
3513                         assert(n_stack > 1);
3514 
3515                         if (current->n_suppress == 0) {
3516                                 r = json_variant_new_array(&add, current->elements, current->n_elements);
3517                                 if (r < 0)
3518                                         goto finish;
3519                         }
3520 
3521                         n_subtract = 1;
3522 
3523                         json_stack_release(current);
3524                         n_stack--, current--;
3525 
3526                         break;
3527 
3528                 case _JSON_BUILD_STRV: {
3529                         char **l;
3530 
3531                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
3532                                 r = -EINVAL;
3533                                 goto finish;
3534                         }
3535 
3536                         l = va_arg(ap, char **);
3537 
3538                         if (current->n_suppress == 0) {
3539                                 r = json_variant_new_array_strv(&add, l);
3540                                 if (r < 0)
3541                                         goto finish;
3542                         }
3543 
3544                         n_subtract = 1;
3545 
3546                         if (current->expect == EXPECT_TOPLEVEL)
3547                                 current->expect = EXPECT_END;
3548                         else if (current->expect == EXPECT_OBJECT_VALUE)
3549                                 current->expect = EXPECT_OBJECT_KEY;
3550                         else
3551                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
3552 
3553                         break;
3554                 }
3555 
3556                 case _JSON_BUILD_BASE64: {
3557                         const void *p;
3558                         size_t n;
3559 
3560                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
3561                                 r = -EINVAL;
3562                                 goto finish;
3563                         }
3564 
3565                         p = va_arg(ap, const void *);
3566                         n = va_arg(ap, size_t);
3567 
3568                         if (current->n_suppress == 0) {
3569                                 r = json_variant_new_base64(&add, p, n);
3570                                 if (r < 0)
3571                                         goto finish;
3572                         }
3573 
3574                         n_subtract = 1;
3575 
3576                         if (current->expect == EXPECT_TOPLEVEL)
3577                                 current->expect = EXPECT_END;
3578                         else if (current->expect == EXPECT_OBJECT_VALUE)
3579                                 current->expect = EXPECT_OBJECT_KEY;
3580                         else
3581                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
3582 
3583                         break;
3584                 }
3585 
3586                 case _JSON_BUILD_HEX: {
3587                         const void *p;
3588                         size_t n;
3589 
3590                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
3591                                 r = -EINVAL;
3592                                 goto finish;
3593                         }
3594 
3595                         p = va_arg(ap, const void *);
3596                         n = va_arg(ap, size_t);
3597 
3598                         if (current->n_suppress == 0) {
3599                                 r = json_variant_new_hex(&add, p, n);
3600                                 if (r < 0)
3601                                         goto finish;
3602                         }
3603 
3604                         n_subtract = 1;
3605 
3606                         if (current->expect == EXPECT_TOPLEVEL)
3607                                 current->expect = EXPECT_END;
3608                         else if (current->expect == EXPECT_OBJECT_VALUE)
3609                                 current->expect = EXPECT_OBJECT_KEY;
3610                         else
3611                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
3612 
3613                         break;
3614                 }
3615 
3616                 case _JSON_BUILD_ID128: {
3617                         const sd_id128_t *id;
3618 
3619                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
3620                                 r = -EINVAL;
3621                                 goto finish;
3622                         }
3623 
3624                         assert_se(id = va_arg(ap, sd_id128_t*));
3625 
3626                         if (current->n_suppress == 0) {
3627                                 r = json_variant_new_id128(&add, *id);
3628                                 if (r < 0)
3629                                         goto finish;
3630                         }
3631 
3632                         n_subtract = 1;
3633 
3634                         if (current->expect == EXPECT_TOPLEVEL)
3635                                 current->expect = EXPECT_END;
3636                         else if (current->expect == EXPECT_OBJECT_VALUE)
3637                                 current->expect = EXPECT_OBJECT_KEY;
3638                         else
3639                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
3640 
3641                         break;
3642                 }
3643 
3644                 case _JSON_BUILD_BYTE_ARRAY: {
3645                         const void *array;
3646                         size_t n;
3647 
3648                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
3649                                 r = -EINVAL;
3650                                 goto finish;
3651                         }
3652 
3653                         array = va_arg(ap, const void*);
3654                         n = va_arg(ap, size_t);
3655 
3656                         if (current->n_suppress == 0) {
3657                                 r = json_variant_new_array_bytes(&add, array, n);
3658                                 if (r < 0)
3659                                         goto finish;
3660                         }
3661 
3662                         n_subtract = 1;
3663 
3664                         if (current->expect == EXPECT_TOPLEVEL)
3665                                 current->expect = EXPECT_END;
3666                         else if (current->expect == EXPECT_OBJECT_VALUE)
3667                                 current->expect = EXPECT_OBJECT_KEY;
3668                         else
3669                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
3670 
3671                         break;
3672                 }
3673 
3674                 case _JSON_BUILD_HW_ADDR: {
3675                         const struct hw_addr_data *hw_addr;
3676 
3677                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
3678                                 r = -EINVAL;
3679                                 goto finish;
3680                         }
3681 
3682                         assert_se(hw_addr = va_arg(ap, struct hw_addr_data*));
3683 
3684                         if (current->n_suppress == 0) {
3685                                 r = json_variant_new_array_bytes(&add, hw_addr->bytes, hw_addr->length);
3686                                 if (r < 0)
3687                                         goto finish;
3688                         }
3689 
3690                         n_subtract = 1;
3691 
3692                         if (current->expect == EXPECT_TOPLEVEL)
3693                                 current->expect = EXPECT_END;
3694                         else if (current->expect == EXPECT_OBJECT_VALUE)
3695                                 current->expect = EXPECT_OBJECT_KEY;
3696                         else
3697                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
3698 
3699                         break;
3700                 }
3701 
3702                 case _JSON_BUILD_OBJECT_BEGIN:
3703 
3704                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
3705                                 r = -EINVAL;
3706                                 goto finish;
3707                         }
3708 
3709                         if (!GREEDY_REALLOC(stack, n_stack+1)) {
3710                                 r = -ENOMEM;
3711                                 goto finish;
3712                         }
3713                         current = stack + n_stack - 1;
3714 
3715                         if (current->expect == EXPECT_TOPLEVEL)
3716                                 current->expect = EXPECT_END;
3717                         else if (current->expect == EXPECT_OBJECT_VALUE)
3718                                 current->expect = EXPECT_OBJECT_KEY;
3719                         else
3720                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
3721 
3722                         stack[n_stack++] = (JsonStack) {
3723                                 .expect = EXPECT_OBJECT_KEY,
3724                                 .n_suppress = current->n_suppress != 0 ? SIZE_MAX : 0, /* If we shall suppress the
3725                                                                                         * new object, then we should
3726                                                                                         * also suppress all object
3727                                                                                         * members. */
3728                         };
3729 
3730                         break;
3731 
3732                 case _JSON_BUILD_OBJECT_END:
3733 
3734                         if (current->expect != EXPECT_OBJECT_KEY) {
3735                                 r = -EINVAL;
3736                                 goto finish;
3737                         }
3738 
3739                         assert(n_stack > 1);
3740 
3741                         if (current->n_suppress == 0) {
3742                                 r = json_variant_new_object(&add, current->elements, current->n_elements);
3743                                 if (r < 0)
3744                                         goto finish;
3745                         }
3746 
3747                         n_subtract = 1;
3748 
3749                         json_stack_release(current);
3750                         n_stack--, current--;
3751 
3752                         break;
3753 
3754                 case _JSON_BUILD_PAIR: {
3755                         const char *n;
3756 
3757                         if (current->expect != EXPECT_OBJECT_KEY) {
3758                                 r = -EINVAL;
3759                                 goto finish;
3760                         }
3761 
3762                         n = va_arg(ap, const char *);
3763 
3764                         if (current->n_suppress == 0) {
3765                                 r = json_variant_new_string(&add, n);
3766                                 if (r < 0)
3767                                         goto finish;
3768                         }
3769 
3770                         n_subtract = 1;
3771 
3772                         current->expect = EXPECT_OBJECT_VALUE;
3773                         break;
3774                 }
3775 
3776                 case _JSON_BUILD_PAIR_CONDITION: {
3777                         const char *n;
3778                         bool b;
3779 
3780                         if (current->expect != EXPECT_OBJECT_KEY) {
3781                                 r = -EINVAL;
3782                                 goto finish;
3783                         }
3784 
3785                         b = va_arg(ap, int);
3786                         n = va_arg(ap, const char *);
3787 
3788                         if (b && current->n_suppress == 0) {
3789                                 r = json_variant_new_string(&add, n);
3790                                 if (r < 0)
3791                                         goto finish;
3792                         }
3793 
3794                         n_subtract = 1; /* we generated one item */
3795 
3796                         if (!b && current->n_suppress != SIZE_MAX)
3797                                 current->n_suppress += 2; /* Suppress this one and the next item */
3798 
3799                         current->expect = EXPECT_OBJECT_VALUE;
3800                         break;
3801                 }
3802 
3803                 case _JSON_BUILD_PAIR_UNSIGNED_NON_ZERO: {
3804                         const char *n;
3805                         uint64_t u;
3806 
3807                         if (current->expect != EXPECT_OBJECT_KEY) {
3808                                 r = -EINVAL;
3809                                 goto finish;
3810                         }
3811 
3812                         n = va_arg(ap, const char *);
3813                         u = va_arg(ap, uint64_t);
3814 
3815                         if (u != 0 && current->n_suppress == 0) {
3816                                 r = json_variant_new_string(&add, n);
3817                                 if (r < 0)
3818                                         goto finish;
3819 
3820                                 r = json_variant_new_unsigned(&add_more, u);
3821                                 if (r < 0)
3822                                         goto finish;
3823                         }
3824 
3825                         n_subtract = 2; /* we generated two item */
3826 
3827                         current->expect = EXPECT_OBJECT_KEY;
3828                         break;
3829                 }
3830 
3831                 case _JSON_BUILD_PAIR_FINITE_USEC: {
3832                         const char *n;
3833                         usec_t u;
3834 
3835                         if (current->expect != EXPECT_OBJECT_KEY) {
3836                                 r = -EINVAL;
3837                                 goto finish;
3838                         }
3839 
3840                         n = va_arg(ap, const char *);
3841                         u = va_arg(ap, usec_t);
3842 
3843                         if (u != USEC_INFINITY && current->n_suppress == 0) {
3844                                 r = json_variant_new_string(&add, n);
3845                                 if (r < 0)
3846                                         goto finish;
3847 
3848                                 r = json_variant_new_unsigned(&add_more, u);
3849                                 if (r < 0)
3850                                         goto finish;
3851                         }
3852 
3853                         n_subtract = 2; /* we generated two item */
3854 
3855                         current->expect = EXPECT_OBJECT_KEY;
3856                         break;
3857                 }
3858 
3859                 case _JSON_BUILD_PAIR_STRING_NON_EMPTY: {
3860                         const char *n, *s;
3861 
3862                         if (current->expect != EXPECT_OBJECT_KEY) {
3863                                 r = -EINVAL;
3864                                 goto finish;
3865                         }
3866 
3867                         n = va_arg(ap, const char *);
3868                         s = va_arg(ap, const char *);
3869 
3870                         if (!isempty(s) && current->n_suppress == 0) {
3871                                 r = json_variant_new_string(&add, n);
3872                                 if (r < 0)
3873                                         goto finish;
3874 
3875                                 r = json_variant_new_string(&add_more, s);
3876                                 if (r < 0)
3877                                         goto finish;
3878                         }
3879 
3880                         n_subtract = 2; /* we generated two item */
3881 
3882                         current->expect = EXPECT_OBJECT_KEY;
3883                         break;
3884                 }
3885 
3886                 case _JSON_BUILD_PAIR_STRV_NON_EMPTY: {
3887                         const char *n;
3888                         char **l;
3889 
3890                         if (current->expect != EXPECT_OBJECT_KEY) {
3891                                 r = -EINVAL;
3892                                 goto finish;
3893                         }
3894 
3895                         n = va_arg(ap, const char *);
3896                         l = va_arg(ap, char **);
3897 
3898                         if (!strv_isempty(l) && current->n_suppress == 0) {
3899                                 r = json_variant_new_string(&add, n);
3900                                 if (r < 0)
3901                                         goto finish;
3902 
3903                                 r = json_variant_new_array_strv(&add_more, l);
3904                                 if (r < 0)
3905                                         goto finish;
3906                         }
3907 
3908                         n_subtract = 2; /* we generated two item */
3909 
3910                         current->expect = EXPECT_OBJECT_KEY;
3911                         break;
3912                 }
3913 
3914                 case _JSON_BUILD_PAIR_VARIANT_NON_NULL: {
3915                         JsonVariant *v;
3916                         const char *n;
3917 
3918                         if (current->expect != EXPECT_OBJECT_KEY) {
3919                                 r = -EINVAL;
3920                                 goto finish;
3921                         }
3922 
3923                         n = va_arg(ap, const char *);
3924                         v = va_arg(ap, JsonVariant *);
3925 
3926                         if (v && !json_variant_is_null(v) && current->n_suppress == 0) {
3927                                 r = json_variant_new_string(&add, n);
3928                                 if (r < 0)
3929                                         goto finish;
3930 
3931                                 add_more = json_variant_ref(v);
3932                         }
3933 
3934                         n_subtract = 2; /* we generated two item */
3935 
3936                         current->expect = EXPECT_OBJECT_KEY;
3937                         break;
3938                 }
3939 
3940                 case _JSON_BUILD_PAIR_IN4_ADDR_NON_NULL: {
3941                         const struct in_addr *a;
3942                         const char *n;
3943 
3944                         if (current->expect != EXPECT_OBJECT_KEY) {
3945                                 r = -EINVAL;
3946                                 goto finish;
3947                         }
3948 
3949                         n = va_arg(ap, const char *);
3950                         a = va_arg(ap, const struct in_addr *);
3951 
3952                         if (a && in4_addr_is_set(a) && current->n_suppress == 0) {
3953                                 r = json_variant_new_string(&add, n);
3954                                 if (r < 0)
3955                                         goto finish;
3956 
3957                                 r = json_variant_new_array_bytes(&add_more, a, sizeof(struct in_addr));
3958                                 if (r < 0)
3959                                         goto finish;
3960                         }
3961 
3962                         n_subtract = 2; /* we generated two item */
3963 
3964                         current->expect = EXPECT_OBJECT_KEY;
3965                         break;
3966                 }
3967 
3968                 case _JSON_BUILD_PAIR_IN6_ADDR_NON_NULL: {
3969                         const struct in6_addr *a;
3970                         const char *n;
3971 
3972                         if (current->expect != EXPECT_OBJECT_KEY) {
3973                                 r = -EINVAL;
3974                                 goto finish;
3975                         }
3976 
3977                         n = va_arg(ap, const char *);
3978                         a = va_arg(ap, const struct in6_addr *);
3979 
3980                         if (a && in6_addr_is_set(a) && current->n_suppress == 0) {
3981                                 r = json_variant_new_string(&add, n);
3982                                 if (r < 0)
3983                                         goto finish;
3984 
3985                                 r = json_variant_new_array_bytes(&add_more, a, sizeof(struct in6_addr));
3986                                 if (r < 0)
3987                                         goto finish;
3988                         }
3989 
3990                         n_subtract = 2; /* we generated two item */
3991 
3992                         current->expect = EXPECT_OBJECT_KEY;
3993                         break;
3994                 }
3995 
3996                 case _JSON_BUILD_PAIR_IN_ADDR_NON_NULL: {
3997                         const union in_addr_union *a;
3998                         const char *n;
3999                         int f;
4000 
4001                         if (current->expect != EXPECT_OBJECT_KEY) {
4002                                 r = -EINVAL;
4003                                 goto finish;
4004                         }
4005 
4006                         n = va_arg(ap, const char *);
4007                         a = va_arg(ap, const union in_addr_union *);
4008                         f = va_arg(ap, int);
4009 
4010                         if (a && in_addr_is_set(f, a) && current->n_suppress == 0) {
4011                                 r = json_variant_new_string(&add, n);
4012                                 if (r < 0)
4013                                         goto finish;
4014 
4015                                 r = json_variant_new_array_bytes(&add_more, a->bytes, FAMILY_ADDRESS_SIZE(f));
4016                                 if (r < 0)
4017                                         goto finish;
4018                         }
4019 
4020                         n_subtract = 2; /* we generated two item */
4021 
4022                         current->expect = EXPECT_OBJECT_KEY;
4023                         break;
4024                 }
4025 
4026                 case _JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL: {
4027                         const struct ether_addr *a;
4028                         const char *n;
4029 
4030                         if (current->expect != EXPECT_OBJECT_KEY) {
4031                                 r = -EINVAL;
4032                                 goto finish;
4033                         }
4034 
4035                         n = va_arg(ap, const char *);
4036                         a = va_arg(ap, const struct ether_addr *);
4037 
4038                         if (a && !ether_addr_is_null(a) && current->n_suppress == 0) {
4039                                 r = json_variant_new_string(&add, n);
4040                                 if (r < 0)
4041                                         goto finish;
4042 
4043                                 r = json_variant_new_array_bytes(&add_more, a->ether_addr_octet, sizeof(struct ether_addr));
4044                                 if (r < 0)
4045                                         goto finish;
4046                         }
4047 
4048                         n_subtract = 2; /* we generated two item */
4049 
4050                         current->expect = EXPECT_OBJECT_KEY;
4051                         break;
4052                 }
4053 
4054                 case _JSON_BUILD_PAIR_HW_ADDR_NON_NULL: {
4055                         const struct hw_addr_data *a;
4056                         const char *n;
4057 
4058                         if (current->expect != EXPECT_OBJECT_KEY) {
4059                                 r = -EINVAL;
4060                                 goto finish;
4061                         }
4062 
4063                         n = va_arg(ap, const char *);
4064                         a = va_arg(ap, const struct hw_addr_data *);
4065 
4066                         if (a && !hw_addr_is_null(a) && current->n_suppress == 0) {
4067                                 r = json_variant_new_string(&add, n);
4068                                 if (r < 0)
4069                                         goto finish;
4070 
4071                                 r = json_variant_new_array_bytes(&add_more, a->bytes, a->length);
4072                                 if (r < 0)
4073                                         goto finish;
4074                         }
4075 
4076                         n_subtract = 2; /* we generated two item */
4077 
4078                         current->expect = EXPECT_OBJECT_KEY;
4079                         break;
4080                 }
4081                 }
4082 
4083                 /* If variants were generated, add them to our current variant, but only if we are not supposed to suppress additions */
4084                 if (add && current->n_suppress == 0) {
4085                         if (!GREEDY_REALLOC(current->elements, current->n_elements + 1 + !!add_more)) {
4086                                 r = -ENOMEM;
4087                                 goto finish;
4088                         }
4089 
4090                         current->elements[current->n_elements++] = TAKE_PTR(add);
4091                         if (add_more)
4092                                 current->elements[current->n_elements++] = TAKE_PTR(add_more);
4093                 }
4094 
4095                 /* If we are supposed to suppress items, let's subtract how many items where generated from
4096                  * that counter. Except if the counter is SIZE_MAX, i.e. we shall suppress an infinite number
4097                  * of elements on this stack level */
4098                 if (current->n_suppress != SIZE_MAX) {
4099                         if (current->n_suppress <= n_subtract) /* Saturated */
4100                                 current->n_suppress = 0;
4101                         else
4102                                 current->n_suppress -= n_subtract;
4103                 }
4104         }
4105 
4106 done:
4107         assert(n_stack == 1);
4108         assert(stack[0].n_elements == 1);
4109 
4110         *ret = json_variant_ref(stack[0].elements[0]);
4111         r = 0;
4112 
4113 finish:
4114         for (size_t i = 0; i < n_stack; i++)
4115                 json_stack_release(stack + i);
4116 
4117         free(stack);
4118 
4119         return r;
4120 }
4121 
json_build(JsonVariant ** ret,...)4122 int json_build(JsonVariant **ret, ...) {
4123         va_list ap;
4124         int r;
4125 
4126         va_start(ap, ret);
4127         r = json_buildv(ret, ap);
4128         va_end(ap);
4129 
4130         return r;
4131 }
4132 
json_log_internal(JsonVariant * variant,int level,int error,const char * file,int line,const char * func,const char * format,...)4133 int json_log_internal(
4134                 JsonVariant *variant,
4135                 int level,
4136                 int error,
4137                 const char *file,
4138                 int line,
4139                 const char *func,
4140                 const char *format, ...) {
4141 
4142         PROTECT_ERRNO;
4143 
4144         unsigned source_line, source_column;
4145         char buffer[LINE_MAX];
4146         const char *source;
4147         va_list ap;
4148         int r;
4149 
4150         errno = ERRNO_VALUE(error);
4151 
4152         va_start(ap, format);
4153         (void) vsnprintf(buffer, sizeof buffer, format, ap);
4154         va_end(ap);
4155 
4156         if (variant) {
4157                 r = json_variant_get_source(variant, &source, &source_line, &source_column);
4158                 if (r < 0)
4159                         return r;
4160         } else {
4161                 source = NULL;
4162                 source_line = 0;
4163                 source_column = 0;
4164         }
4165 
4166         if (source && source_line > 0 && source_column > 0)
4167                 return log_struct_internal(
4168                                 level,
4169                                 error,
4170                                 file, line, func,
4171                                 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
4172                                 "CONFIG_FILE=%s", source,
4173                                 "CONFIG_LINE=%u", source_line,
4174                                 "CONFIG_COLUMN=%u", source_column,
4175                                 LOG_MESSAGE("%s:%u:%u: %s", source, source_line, source_column, buffer),
4176                                 NULL);
4177         else if (source_line > 0 && source_column > 0)
4178                 return log_struct_internal(
4179                                 level,
4180                                 error,
4181                                 file, line, func,
4182                                 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
4183                                 "CONFIG_LINE=%u", source_line,
4184                                 "CONFIG_COLUMN=%u", source_column,
4185                                 LOG_MESSAGE("(string):%u:%u: %s", source_line, source_column, buffer),
4186                                 NULL);
4187         else
4188                 return log_struct_internal(
4189                                 level,
4190                                 error,
4191                                 file, line, func,
4192                                 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
4193                                 LOG_MESSAGE("%s", buffer),
4194                                 NULL);
4195 }
4196 
json_dispatch(JsonVariant * v,const JsonDispatch table[],JsonDispatchCallback bad,JsonDispatchFlags flags,void * userdata)4197 int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallback bad, JsonDispatchFlags flags, void *userdata) {
4198         size_t m;
4199         int r, done = 0;
4200         bool *found;
4201 
4202         if (!json_variant_is_object(v)) {
4203                 json_log(v, flags, 0, "JSON variant is not an object.");
4204 
4205                 if (flags & JSON_PERMISSIVE)
4206                         return 0;
4207 
4208                 return -EINVAL;
4209         }
4210 
4211         m = 0;
4212         for (const JsonDispatch *p = table; p->name; p++)
4213                 m++;
4214 
4215         found = newa0(bool, m);
4216 
4217         size_t n = json_variant_elements(v);
4218         for (size_t i = 0; i < n; i += 2) {
4219                 JsonVariant *key, *value;
4220                 const JsonDispatch *p;
4221 
4222                 assert_se(key = json_variant_by_index(v, i));
4223                 assert_se(value = json_variant_by_index(v, i+1));
4224 
4225                 for (p = table; p->name; p++)
4226                         if (p->name == POINTER_MAX ||
4227                             streq_ptr(json_variant_string(key), p->name))
4228                                 break;
4229 
4230                 if (p->name) { /* Found a matching entry! :-) */
4231                         JsonDispatchFlags merged_flags;
4232 
4233                         merged_flags = flags | p->flags;
4234 
4235                         if (p->type != _JSON_VARIANT_TYPE_INVALID &&
4236                             !json_variant_has_type(value, p->type)) {
4237 
4238                                 json_log(value, merged_flags, 0,
4239                                          "Object field '%s' has wrong type %s, expected %s.", json_variant_string(key),
4240                                          json_variant_type_to_string(json_variant_type(value)), json_variant_type_to_string(p->type));
4241 
4242                                 if (merged_flags & JSON_PERMISSIVE)
4243                                         continue;
4244 
4245                                 return -EINVAL;
4246                         }
4247 
4248                         if (found[p-table]) {
4249                                 json_log(value, merged_flags, 0, "Duplicate object field '%s'.", json_variant_string(key));
4250 
4251                                 if (merged_flags & JSON_PERMISSIVE)
4252                                         continue;
4253 
4254                                 return -ENOTUNIQ;
4255                         }
4256 
4257                         found[p-table] = true;
4258 
4259                         if (p->callback) {
4260                                 r = p->callback(json_variant_string(key), value, merged_flags, (uint8_t*) userdata + p->offset);
4261                                 if (r < 0) {
4262                                         if (merged_flags & JSON_PERMISSIVE)
4263                                                 continue;
4264 
4265                                         return r;
4266                                 }
4267                         }
4268 
4269                         done ++;
4270 
4271                 } else { /* Didn't find a matching entry! :-( */
4272 
4273                         if (bad) {
4274                                 r = bad(json_variant_string(key), value, flags, userdata);
4275                                 if (r < 0) {
4276                                         if (flags & JSON_PERMISSIVE)
4277                                                 continue;
4278 
4279                                         return r;
4280                                 } else
4281                                         done ++;
4282 
4283                         } else  {
4284                                 json_log(value, flags, 0, "Unexpected object field '%s'.", json_variant_string(key));
4285 
4286                                 if (flags & JSON_PERMISSIVE)
4287                                         continue;
4288 
4289                                 return -EADDRNOTAVAIL;
4290                         }
4291                 }
4292         }
4293 
4294         for (const JsonDispatch *p = table; p->name; p++) {
4295                 JsonDispatchFlags merged_flags = p->flags | flags;
4296 
4297                 if ((merged_flags & JSON_MANDATORY) && !found[p-table]) {
4298                         json_log(v, merged_flags, 0, "Missing object field '%s'.", p->name);
4299 
4300                         if ((merged_flags & JSON_PERMISSIVE))
4301                                 continue;
4302 
4303                         return -ENXIO;
4304                 }
4305         }
4306 
4307         return done;
4308 }
4309 
json_dispatch_boolean(const char * name,JsonVariant * variant,JsonDispatchFlags flags,void * userdata)4310 int json_dispatch_boolean(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
4311         bool *b = userdata;
4312 
4313         assert(variant);
4314         assert(b);
4315 
4316         if (!json_variant_is_boolean(variant))
4317                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a boolean.", strna(name));
4318 
4319         *b = json_variant_boolean(variant);
4320         return 0;
4321 }
4322 
json_dispatch_tristate(const char * name,JsonVariant * variant,JsonDispatchFlags flags,void * userdata)4323 int json_dispatch_tristate(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
4324         int *b = userdata;
4325 
4326         assert(variant);
4327         assert(b);
4328 
4329         if (json_variant_is_null(variant)) {
4330                 *b = -1;
4331                 return 0;
4332         }
4333 
4334         if (!json_variant_is_boolean(variant))
4335                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a boolean.", strna(name));
4336 
4337         *b = json_variant_boolean(variant);
4338         return 0;
4339 }
4340 
json_dispatch_int64(const char * name,JsonVariant * variant,JsonDispatchFlags flags,void * userdata)4341 int json_dispatch_int64(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
4342         int64_t *i = userdata;
4343 
4344         assert(variant);
4345         assert(i);
4346 
4347         if (!json_variant_is_integer(variant))
4348                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an integer.", strna(name));
4349 
4350         *i = json_variant_integer(variant);
4351         return 0;
4352 }
4353 
json_dispatch_uint64(const char * name,JsonVariant * variant,JsonDispatchFlags flags,void * userdata)4354 int json_dispatch_uint64(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
4355         uint64_t *u = userdata;
4356 
4357         assert(variant);
4358         assert(u);
4359 
4360         if (!json_variant_is_unsigned(variant))
4361                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an unsigned integer.", strna(name));
4362 
4363         *u = json_variant_unsigned(variant);
4364         return 0;
4365 }
4366 
json_dispatch_uint32(const char * name,JsonVariant * variant,JsonDispatchFlags flags,void * userdata)4367 int json_dispatch_uint32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
4368         uint32_t *u = userdata;
4369 
4370         assert(variant);
4371         assert(u);
4372 
4373         if (!json_variant_is_unsigned(variant))
4374                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an unsigned integer.", strna(name));
4375 
4376         if (json_variant_unsigned(variant) > UINT32_MAX)
4377                 return json_log(variant, flags, SYNTHETIC_ERRNO(ERANGE), "JSON field '%s' out of bounds.", strna(name));
4378 
4379         *u = (uint32_t) json_variant_unsigned(variant);
4380         return 0;
4381 }
4382 
json_dispatch_int32(const char * name,JsonVariant * variant,JsonDispatchFlags flags,void * userdata)4383 int json_dispatch_int32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
4384         int32_t *i = userdata;
4385 
4386         assert(variant);
4387         assert(i);
4388 
4389         if (!json_variant_is_integer(variant))
4390                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an integer.", strna(name));
4391 
4392         if (json_variant_integer(variant) < INT32_MIN || json_variant_integer(variant) > INT32_MAX)
4393                 return json_log(variant, flags, SYNTHETIC_ERRNO(ERANGE), "JSON field '%s' out of bounds.", strna(name));
4394 
4395         *i = (int32_t) json_variant_integer(variant);
4396         return 0;
4397 }
4398 
json_dispatch_string(const char * name,JsonVariant * variant,JsonDispatchFlags flags,void * userdata)4399 int json_dispatch_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
4400         char **s = userdata;
4401         int r;
4402 
4403         assert(variant);
4404         assert(s);
4405 
4406         if (json_variant_is_null(variant)) {
4407                 *s = mfree(*s);
4408                 return 0;
4409         }
4410 
4411         if (!json_variant_is_string(variant))
4412                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(name));
4413 
4414         if ((flags & JSON_SAFE) && !string_is_safe(json_variant_string(variant)))
4415                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' contains unsafe characters, refusing.", strna(name));
4416 
4417         r = free_and_strdup(s, json_variant_string(variant));
4418         if (r < 0)
4419                 return json_log(variant, flags, r, "Failed to allocate string: %m");
4420 
4421         return 0;
4422 }
4423 
json_dispatch_const_string(const char * name,JsonVariant * variant,JsonDispatchFlags flags,void * userdata)4424 int json_dispatch_const_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
4425         const char **s = userdata;
4426 
4427         assert(variant);
4428         assert(s);
4429 
4430         if (json_variant_is_null(variant)) {
4431                 *s = NULL;
4432                 return 0;
4433         }
4434 
4435         if (!json_variant_is_string(variant))
4436                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(name));
4437 
4438         if ((flags & JSON_SAFE) && !string_is_safe(json_variant_string(variant)))
4439                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' contains unsafe characters, refusing.", strna(name));
4440 
4441         *s = json_variant_string(variant);
4442         return 0;
4443 }
4444 
json_dispatch_strv(const char * name,JsonVariant * variant,JsonDispatchFlags flags,void * userdata)4445 int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
4446         _cleanup_strv_free_ char **l = NULL;
4447         char ***s = userdata;
4448         JsonVariant *e;
4449         int r;
4450 
4451         assert(variant);
4452         assert(s);
4453 
4454         if (json_variant_is_null(variant)) {
4455                 *s = strv_free(*s);
4456                 return 0;
4457         }
4458 
4459         /* Let's be flexible here: accept a single string in place of a single-item array */
4460         if (json_variant_is_string(variant)) {
4461                 if ((flags & JSON_SAFE) && !string_is_safe(json_variant_string(variant)))
4462                         return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' contains unsafe characters, refusing.", strna(name));
4463 
4464                 l = strv_new(json_variant_string(variant));
4465                 if (!l)
4466                         return log_oom();
4467 
4468                 strv_free_and_replace(*s, l);
4469                 return 0;
4470         }
4471 
4472         if (!json_variant_is_array(variant))
4473                 return json_log(variant, SYNTHETIC_ERRNO(EINVAL), flags, "JSON field '%s' is not an array.", strna(name));
4474 
4475         JSON_VARIANT_ARRAY_FOREACH(e, variant) {
4476                 if (!json_variant_is_string(e))
4477                         return json_log(e, flags, SYNTHETIC_ERRNO(EINVAL), "JSON array element is not a string.");
4478 
4479                 if ((flags & JSON_SAFE) && !string_is_safe(json_variant_string(e)))
4480                         return json_log(e, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' contains unsafe characters, refusing.", strna(name));
4481 
4482                 r = strv_extend(&l, json_variant_string(e));
4483                 if (r < 0)
4484                         return json_log(e, flags, r, "Failed to append array element: %m");
4485         }
4486 
4487         strv_free_and_replace(*s, l);
4488         return 0;
4489 }
4490 
json_dispatch_variant(const char * name,JsonVariant * variant,JsonDispatchFlags flags,void * userdata)4491 int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
4492         JsonVariant **p = ASSERT_PTR(userdata);
4493         assert(variant);
4494 
4495         JSON_VARIANT_REPLACE(*p, json_variant_ref(variant));
4496         return 0;
4497 }
4498 
json_dispatch_uid_gid(const char * name,JsonVariant * variant,JsonDispatchFlags flags,void * userdata)4499 int json_dispatch_uid_gid(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
4500         uid_t *uid = userdata;
4501         uint64_t k;
4502 
4503         assert_cc(sizeof(uid_t) == sizeof(uint32_t));
4504         assert_cc(sizeof(gid_t) == sizeof(uint32_t));
4505 
4506         DISABLE_WARNING_TYPE_LIMITS;
4507         assert_cc((UID_INVALID < (uid_t) 0) == (GID_INVALID < (gid_t) 0));
4508         REENABLE_WARNING;
4509 
4510         if (json_variant_is_null(variant)) {
4511                 *uid = UID_INVALID;
4512                 return 0;
4513         }
4514 
4515         if (!json_variant_is_unsigned(variant))
4516                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an integer.", strna(name));
4517 
4518         k = json_variant_unsigned(variant);
4519         if (k > UINT32_MAX || !uid_is_valid(k))
4520                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid UID/GID.", strna(name));
4521 
4522         *uid = k;
4523         return 0;
4524 }
4525 
json_dispatch_user_group_name(const char * name,JsonVariant * variant,JsonDispatchFlags flags,void * userdata)4526 int json_dispatch_user_group_name(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
4527         char **s = userdata;
4528         const char *n;
4529         int r;
4530 
4531         if (json_variant_is_null(variant)) {
4532                 *s = mfree(*s);
4533                 return 0;
4534         }
4535 
4536         if (!json_variant_is_string(variant))
4537                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(name));
4538 
4539         n = json_variant_string(variant);
4540         if (!valid_user_group_name(n, FLAGS_SET(flags, JSON_RELAX) ? VALID_USER_RELAX : 0))
4541                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid user/group name.", strna(name));
4542 
4543         r = free_and_strdup(s, n);
4544         if (r < 0)
4545                 return json_log(variant, flags, r, "Failed to allocate string: %m");
4546 
4547         return 0;
4548 }
4549 
json_dispatch_id128(const char * name,JsonVariant * variant,JsonDispatchFlags flags,void * userdata)4550 int json_dispatch_id128(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
4551         sd_id128_t *uuid = userdata;
4552         int r;
4553 
4554         if (json_variant_is_null(variant)) {
4555                 *uuid = SD_ID128_NULL;
4556                 return 0;
4557         }
4558 
4559         if (!json_variant_is_string(variant))
4560                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(name));
4561 
4562         r = sd_id128_from_string(json_variant_string(variant), uuid);
4563         if (r < 0)
4564                 return json_log(variant, flags, r, "JSON field '%s' is not a valid UID.", strna(name));
4565 
4566         return 0;
4567 }
4568 
json_dispatch_unsupported(const char * name,JsonVariant * variant,JsonDispatchFlags flags,void * userdata)4569 int json_dispatch_unsupported(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
4570         return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not allowed in this object.", strna(name));
4571 }
4572 
json_cmp_strings(const void * x,const void * y)4573 static int json_cmp_strings(const void *x, const void *y) {
4574         JsonVariant *const *a = x, *const *b = y;
4575 
4576         if (!json_variant_is_string(*a) || !json_variant_is_string(*b))
4577                 return CMP(*a, *b);
4578 
4579         return strcmp(json_variant_string(*a), json_variant_string(*b));
4580 }
4581 
json_variant_sort(JsonVariant ** v)4582 int json_variant_sort(JsonVariant **v) {
4583         _cleanup_free_ JsonVariant **a = NULL;
4584         _cleanup_(json_variant_unrefp) JsonVariant *n = NULL;
4585         size_t m;
4586         int r;
4587 
4588         assert(v);
4589 
4590         if (json_variant_is_sorted(*v))
4591                 return 0;
4592 
4593         if (!json_variant_is_object(*v))
4594                 return -EMEDIUMTYPE;
4595 
4596         /* Sorts they key/value pairs in an object variant */
4597 
4598         m = json_variant_elements(*v);
4599         a = new(JsonVariant*, m);
4600         if (!a)
4601                 return -ENOMEM;
4602 
4603         for (size_t i = 0; i < m; i++)
4604                 a[i] = json_variant_by_index(*v, i);
4605 
4606         qsort(a, m/2, sizeof(JsonVariant*)*2, json_cmp_strings);
4607 
4608         r = json_variant_new_object(&n, a, m);
4609         if (r < 0)
4610                 return r;
4611 
4612         json_variant_propagate_sensitive(*v, n);
4613 
4614         if (!n->sorted) /* Check if this worked. This will fail if there are multiple identical keys used. */
4615                 return -ENOTUNIQ;
4616 
4617         JSON_VARIANT_REPLACE(*v, TAKE_PTR(n));
4618 
4619         return 1;
4620 }
4621 
json_variant_normalize(JsonVariant ** v)4622 int json_variant_normalize(JsonVariant **v) {
4623         _cleanup_free_ JsonVariant **a = NULL;
4624         _cleanup_(json_variant_unrefp) JsonVariant *n = NULL;
4625         size_t i, m;
4626         int r;
4627 
4628         assert(v);
4629 
4630         if (json_variant_is_normalized(*v))
4631                 return 0;
4632 
4633         if (!json_variant_is_object(*v) && !json_variant_is_array(*v))
4634                 return -EMEDIUMTYPE;
4635 
4636         /* Sorts the key/value pairs in an object variant anywhere down the tree in the specified variant */
4637 
4638         m = json_variant_elements(*v);
4639         a = new(JsonVariant*, m);
4640         if (!a)
4641                 return -ENOMEM;
4642 
4643         for (i = 0; i < m; ) {
4644                 a[i] = json_variant_ref(json_variant_by_index(*v, i));
4645                 i++;
4646 
4647                 r = json_variant_normalize(&a[i-1]);
4648                 if (r < 0)
4649                         goto finish;
4650         }
4651 
4652         qsort(a, m/2, sizeof(JsonVariant*)*2, json_cmp_strings);
4653 
4654         if (json_variant_is_object(*v))
4655                 r = json_variant_new_object(&n, a, m);
4656         else {
4657                 assert(json_variant_is_array(*v));
4658                 r = json_variant_new_array(&n, a, m);
4659         }
4660         if (r < 0)
4661                 goto finish;
4662 
4663         json_variant_propagate_sensitive(*v, n);
4664 
4665         if (!n->normalized) { /* Let's see if normalization worked. It will fail if there are multiple
4666                                * identical keys used in the same object anywhere, or if there are floating
4667                                * point numbers used (see below) */
4668                 r = -ENOTUNIQ;
4669                 goto finish;
4670         }
4671 
4672         JSON_VARIANT_REPLACE(*v, TAKE_PTR(n));
4673 
4674         r = 1;
4675 
4676 finish:
4677         for (size_t j = 0; j < i; j++)
4678                 json_variant_unref(a[j]);
4679 
4680         return r;
4681 }
4682 
json_variant_is_normalized(JsonVariant * v)4683 bool json_variant_is_normalized(JsonVariant *v) {
4684         /* For now, let's consider anything containing numbers not expressible as integers as non-normalized.
4685          * That's because we cannot sensibly compare them due to accuracy issues, nor even store them if they
4686          * are too large. */
4687         if (json_variant_is_real(v) && !json_variant_is_integer(v) && !json_variant_is_unsigned(v))
4688                 return false;
4689 
4690         /* The concept only applies to variants that include other variants, i.e. objects and arrays. All
4691          * others are normalized anyway. */
4692         if (!json_variant_is_object(v) && !json_variant_is_array(v))
4693                 return true;
4694 
4695         /* Empty objects/arrays don't include any other variant, hence are always normalized too */
4696         if (json_variant_elements(v) == 0)
4697                 return true;
4698 
4699         return v->normalized; /* For everything else there's an explicit boolean we maintain */
4700 }
4701 
json_variant_is_sorted(JsonVariant * v)4702 bool json_variant_is_sorted(JsonVariant *v) {
4703 
4704         /* Returns true if all key/value pairs of an object are properly sorted. Note that this only applies
4705          * to objects, not arrays. */
4706 
4707         if (!json_variant_is_object(v))
4708                 return true;
4709         if (json_variant_elements(v) <= 1)
4710                 return true;
4711 
4712         return v->sorted;
4713 }
4714 
json_variant_unbase64(JsonVariant * v,void ** ret,size_t * ret_size)4715 int json_variant_unbase64(JsonVariant *v, void **ret, size_t *ret_size) {
4716         if (!json_variant_is_string(v))
4717                 return -EINVAL;
4718 
4719         return unbase64mem(json_variant_string(v), SIZE_MAX, ret, ret_size);
4720 }
4721 
json_variant_unhex(JsonVariant * v,void ** ret,size_t * ret_size)4722 int json_variant_unhex(JsonVariant *v, void **ret, size_t *ret_size) {
4723         if (!json_variant_is_string(v))
4724                 return -EINVAL;
4725 
4726         return unhexmem(json_variant_string(v), SIZE_MAX, ret, ret_size);
4727 }
4728 
4729 static const char* const json_variant_type_table[_JSON_VARIANT_TYPE_MAX] = {
4730         [JSON_VARIANT_STRING]   = "string",
4731         [JSON_VARIANT_INTEGER]  = "integer",
4732         [JSON_VARIANT_UNSIGNED] = "unsigned",
4733         [JSON_VARIANT_REAL]     = "real",
4734         [JSON_VARIANT_NUMBER]   = "number",
4735         [JSON_VARIANT_BOOLEAN]  = "boolean",
4736         [JSON_VARIANT_ARRAY]    = "array",
4737         [JSON_VARIANT_OBJECT]   = "object",
4738         [JSON_VARIANT_NULL]     = "null",
4739 };
4740 
4741 DEFINE_STRING_TABLE_LOOKUP(json_variant_type, JsonVariantType);
4742