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