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