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