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