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