]> git.proxmox.com Git - systemd.git/blob - src/basic/json.c
Merge tag 'upstream/229'
[systemd.git] / src / basic / json.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2014 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <errno.h>
21 #include <math.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/types.h>
25
26 #include "alloc-util.h"
27 #include "hexdecoct.h"
28 #include "json.h"
29 #include "macro.h"
30 #include "string-util.h"
31 #include "utf8.h"
32
33 int json_variant_new(JsonVariant **ret, JsonVariantType type) {
34 JsonVariant *v;
35
36 v = new0(JsonVariant, 1);
37 if (!v)
38 return -ENOMEM;
39 v->type = type;
40 *ret = v;
41 return 0;
42 }
43
44 static int json_variant_deep_copy(JsonVariant *ret, JsonVariant *variant) {
45 int r;
46
47 assert(ret);
48 assert(variant);
49
50 ret->type = variant->type;
51 ret->size = variant->size;
52
53 if (variant->type == JSON_VARIANT_STRING) {
54 ret->string = memdup(variant->string, variant->size+1);
55 if (!ret->string)
56 return -ENOMEM;
57 } else if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT) {
58 size_t i;
59
60 ret->objects = new0(JsonVariant, variant->size);
61 if (!ret->objects)
62 return -ENOMEM;
63
64 for (i = 0; i < variant->size; ++i) {
65 r = json_variant_deep_copy(&ret->objects[i], &variant->objects[i]);
66 if (r < 0)
67 return r;
68 }
69 } else
70 ret->value = variant->value;
71
72 return 0;
73 }
74
75 static JsonVariant *json_object_unref(JsonVariant *variant);
76
77 static JsonVariant *json_variant_unref_inner(JsonVariant *variant) {
78 if (!variant)
79 return NULL;
80
81 if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT)
82 return json_object_unref(variant);
83 else if (variant->type == JSON_VARIANT_STRING)
84 free(variant->string);
85
86 return NULL;
87 }
88
89 static JsonVariant *json_raw_unref(JsonVariant *variant, size_t size) {
90 if (!variant)
91 return NULL;
92
93 for (size_t i = 0; i < size; ++i)
94 json_variant_unref_inner(&variant[i]);
95
96 free(variant);
97 return NULL;
98 }
99
100 static JsonVariant *json_object_unref(JsonVariant *variant) {
101 size_t i;
102
103 assert(variant);
104
105 if (!variant->objects)
106 return NULL;
107
108 for (i = 0; i < variant->size; ++i)
109 json_variant_unref_inner(&variant->objects[i]);
110
111 free(variant->objects);
112 return NULL;
113 }
114
115 static JsonVariant **json_variant_array_unref(JsonVariant **variant) {
116 size_t i = 0;
117 JsonVariant *p = NULL;
118
119 if (!variant)
120 return NULL;
121
122 while((p = (variant[i++])) != NULL) {
123 if (p->type == JSON_VARIANT_STRING)
124 free(p->string);
125 free(p);
126 }
127
128 free(variant);
129
130 return NULL;
131 }
132
133 DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant **, json_variant_array_unref);
134
135 JsonVariant *json_variant_unref(JsonVariant *variant) {
136 if (!variant)
137 return NULL;
138
139 if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT)
140 json_object_unref(variant);
141 else if (variant->type == JSON_VARIANT_STRING)
142 free(variant->string);
143
144 free(variant);
145
146 return NULL;
147 }
148
149 char *json_variant_string(JsonVariant *variant){
150 assert(variant);
151 assert(variant->type == JSON_VARIANT_STRING);
152
153 return variant->string;
154 }
155
156 bool json_variant_bool(JsonVariant *variant) {
157 assert(variant);
158 assert(variant->type == JSON_VARIANT_BOOLEAN);
159
160 return variant->value.boolean;
161 }
162
163 intmax_t json_variant_integer(JsonVariant *variant) {
164 assert(variant);
165 assert(variant->type == JSON_VARIANT_INTEGER);
166
167 return variant->value.integer;
168 }
169
170 double json_variant_real(JsonVariant *variant) {
171 assert(variant);
172 assert(variant->type == JSON_VARIANT_REAL);
173
174 return variant->value.real;
175 }
176
177 JsonVariant *json_variant_element(JsonVariant *variant, unsigned index) {
178 assert(variant);
179 assert(variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT);
180 assert(index < variant->size);
181 assert(variant->objects);
182
183 return &variant->objects[index];
184 }
185
186 JsonVariant *json_variant_value(JsonVariant *variant, const char *key) {
187 size_t i;
188
189 assert(variant);
190 assert(variant->type == JSON_VARIANT_OBJECT);
191 assert(variant->objects);
192
193 for (i = 0; i < variant->size; i += 2) {
194 JsonVariant *p = &variant->objects[i];
195 if (p->type == JSON_VARIANT_STRING && streq(key, p->string))
196 return &variant->objects[i + 1];
197 }
198
199 return NULL;
200 }
201
202 static void inc_lines(unsigned *line, const char *s, size_t n) {
203 const char *p = s;
204
205 if (!line)
206 return;
207
208 for (;;) {
209 const char *f;
210
211 f = memchr(p, '\n', n);
212 if (!f)
213 return;
214
215 n -= (f - p) + 1;
216 p = f + 1;
217 (*line)++;
218 }
219 }
220
221 static int unhex_ucs2(const char *c, uint16_t *ret) {
222 int aa, bb, cc, dd;
223 uint16_t x;
224
225 assert(c);
226 assert(ret);
227
228 aa = unhexchar(c[0]);
229 if (aa < 0)
230 return -EINVAL;
231
232 bb = unhexchar(c[1]);
233 if (bb < 0)
234 return -EINVAL;
235
236 cc = unhexchar(c[2]);
237 if (cc < 0)
238 return -EINVAL;
239
240 dd = unhexchar(c[3]);
241 if (dd < 0)
242 return -EINVAL;
243
244 x = ((uint16_t) aa << 12) |
245 ((uint16_t) bb << 8) |
246 ((uint16_t) cc << 4) |
247 ((uint16_t) dd);
248
249 if (x <= 0)
250 return -EINVAL;
251
252 *ret = x;
253
254 return 0;
255 }
256
257 static int json_parse_string(const char **p, char **ret) {
258 _cleanup_free_ char *s = NULL;
259 size_t n = 0, allocated = 0;
260 const char *c;
261
262 assert(p);
263 assert(*p);
264 assert(ret);
265
266 c = *p;
267
268 if (*c != '"')
269 return -EINVAL;
270
271 c++;
272
273 for (;;) {
274 int len;
275
276 /* Check for EOF */
277 if (*c == 0)
278 return -EINVAL;
279
280 /* Check for control characters 0x00..0x1f */
281 if (*c > 0 && *c < ' ')
282 return -EINVAL;
283
284 /* Check for control character 0x7f */
285 if (*c == 0x7f)
286 return -EINVAL;
287
288 if (*c == '"') {
289 if (!s) {
290 s = strdup("");
291 if (!s)
292 return -ENOMEM;
293 } else
294 s[n] = 0;
295
296 *p = c + 1;
297
298 *ret = s;
299 s = NULL;
300 return JSON_STRING;
301 }
302
303 if (*c == '\\') {
304 char ch = 0;
305 c++;
306
307 if (*c == 0)
308 return -EINVAL;
309
310 if (IN_SET(*c, '"', '\\', '/'))
311 ch = *c;
312 else if (*c == 'b')
313 ch = '\b';
314 else if (*c == 'f')
315 ch = '\f';
316 else if (*c == 'n')
317 ch = '\n';
318 else if (*c == 'r')
319 ch = '\r';
320 else if (*c == 't')
321 ch = '\t';
322 else if (*c == 'u') {
323 char16_t x;
324 int r;
325
326 r = unhex_ucs2(c + 1, &x);
327 if (r < 0)
328 return r;
329
330 c += 5;
331
332 if (!GREEDY_REALLOC(s, allocated, n + 4))
333 return -ENOMEM;
334
335 if (!utf16_is_surrogate(x))
336 n += utf8_encode_unichar(s + n, (char32_t) x);
337 else if (utf16_is_trailing_surrogate(x))
338 return -EINVAL;
339 else {
340 char16_t y;
341
342 if (c[0] != '\\' || c[1] != 'u')
343 return -EINVAL;
344
345 r = unhex_ucs2(c + 2, &y);
346 if (r < 0)
347 return r;
348
349 c += 6;
350
351 if (!utf16_is_trailing_surrogate(y))
352 return -EINVAL;
353
354 n += utf8_encode_unichar(s + n, utf16_surrogate_pair_to_unichar(x, y));
355 }
356
357 continue;
358 } else
359 return -EINVAL;
360
361 if (!GREEDY_REALLOC(s, allocated, n + 2))
362 return -ENOMEM;
363
364 s[n++] = ch;
365 c ++;
366 continue;
367 }
368
369 len = utf8_encoded_valid_unichar(c);
370 if (len < 0)
371 return len;
372
373 if (!GREEDY_REALLOC(s, allocated, n + len + 1))
374 return -ENOMEM;
375
376 memcpy(s + n, c, len);
377 n += len;
378 c += len;
379 }
380 }
381
382 static int json_parse_number(const char **p, union json_value *ret) {
383 bool negative = false, exponent_negative = false, is_double = false;
384 double x = 0.0, y = 0.0, exponent = 0.0, shift = 1.0;
385 intmax_t i = 0;
386 const char *c;
387
388 assert(p);
389 assert(*p);
390 assert(ret);
391
392 c = *p;
393
394 if (*c == '-') {
395 negative = true;
396 c++;
397 }
398
399 if (*c == '0')
400 c++;
401 else {
402 if (!strchr("123456789", *c) || *c == 0)
403 return -EINVAL;
404
405 do {
406 if (!is_double) {
407 int64_t t;
408
409 t = 10 * i + (*c - '0');
410 if (t < i) /* overflow */
411 is_double = false;
412 else
413 i = t;
414 }
415
416 x = 10.0 * x + (*c - '0');
417 c++;
418 } while (strchr("0123456789", *c) && *c != 0);
419 }
420
421 if (*c == '.') {
422 is_double = true;
423 c++;
424
425 if (!strchr("0123456789", *c) || *c == 0)
426 return -EINVAL;
427
428 do {
429 y = 10.0 * y + (*c - '0');
430 shift = 10.0 * shift;
431 c++;
432 } while (strchr("0123456789", *c) && *c != 0);
433 }
434
435 if (*c == 'e' || *c == 'E') {
436 is_double = true;
437 c++;
438
439 if (*c == '-') {
440 exponent_negative = true;
441 c++;
442 } else if (*c == '+')
443 c++;
444
445 if (!strchr("0123456789", *c) || *c == 0)
446 return -EINVAL;
447
448 do {
449 exponent = 10.0 * exponent + (*c - '0');
450 c++;
451 } while (strchr("0123456789", *c) && *c != 0);
452 }
453
454 *p = c;
455
456 if (is_double) {
457 ret->real = ((negative ? -1.0 : 1.0) * (x + (y / shift))) * exp10((exponent_negative ? -1.0 : 1.0) * exponent);
458 return JSON_REAL;
459 } else {
460 ret->integer = negative ? -i : i;
461 return JSON_INTEGER;
462 }
463 }
464
465 int json_tokenize(
466 const char **p,
467 char **ret_string,
468 union json_value *ret_value,
469 void **state,
470 unsigned *line) {
471
472 const char *c;
473 int t;
474 int r;
475
476 enum {
477 STATE_NULL,
478 STATE_VALUE,
479 STATE_VALUE_POST,
480 };
481
482 assert(p);
483 assert(*p);
484 assert(ret_string);
485 assert(ret_value);
486 assert(state);
487
488 t = PTR_TO_INT(*state);
489 c = *p;
490
491 if (t == STATE_NULL) {
492 if (line)
493 *line = 1;
494 t = STATE_VALUE;
495 }
496
497 for (;;) {
498 const char *b;
499
500 b = c + strspn(c, WHITESPACE);
501 if (*b == 0)
502 return JSON_END;
503
504 inc_lines(line, c, b - c);
505 c = b;
506
507 switch (t) {
508
509 case STATE_VALUE:
510
511 if (*c == '{') {
512 *ret_string = NULL;
513 *ret_value = JSON_VALUE_NULL;
514 *p = c + 1;
515 *state = INT_TO_PTR(STATE_VALUE);
516 return JSON_OBJECT_OPEN;
517
518 } else if (*c == '}') {
519 *ret_string = NULL;
520 *ret_value = JSON_VALUE_NULL;
521 *p = c + 1;
522 *state = INT_TO_PTR(STATE_VALUE_POST);
523 return JSON_OBJECT_CLOSE;
524
525 } else if (*c == '[') {
526 *ret_string = NULL;
527 *ret_value = JSON_VALUE_NULL;
528 *p = c + 1;
529 *state = INT_TO_PTR(STATE_VALUE);
530 return JSON_ARRAY_OPEN;
531
532 } else if (*c == ']') {
533 *ret_string = NULL;
534 *ret_value = JSON_VALUE_NULL;
535 *p = c + 1;
536 *state = INT_TO_PTR(STATE_VALUE_POST);
537 return JSON_ARRAY_CLOSE;
538
539 } else if (*c == '"') {
540 r = json_parse_string(&c, ret_string);
541 if (r < 0)
542 return r;
543
544 *ret_value = JSON_VALUE_NULL;
545 *p = c;
546 *state = INT_TO_PTR(STATE_VALUE_POST);
547 return r;
548
549 } else if (strchr("-0123456789", *c)) {
550 r = json_parse_number(&c, ret_value);
551 if (r < 0)
552 return r;
553
554 *ret_string = NULL;
555 *p = c;
556 *state = INT_TO_PTR(STATE_VALUE_POST);
557 return r;
558
559 } else if (startswith(c, "true")) {
560 *ret_string = NULL;
561 ret_value->boolean = true;
562 *p = c + 4;
563 *state = INT_TO_PTR(STATE_VALUE_POST);
564 return JSON_BOOLEAN;
565
566 } else if (startswith(c, "false")) {
567 *ret_string = NULL;
568 ret_value->boolean = false;
569 *p = c + 5;
570 *state = INT_TO_PTR(STATE_VALUE_POST);
571 return JSON_BOOLEAN;
572
573 } else if (startswith(c, "null")) {
574 *ret_string = NULL;
575 *ret_value = JSON_VALUE_NULL;
576 *p = c + 4;
577 *state = INT_TO_PTR(STATE_VALUE_POST);
578 return JSON_NULL;
579
580 } else
581 return -EINVAL;
582
583 case STATE_VALUE_POST:
584
585 if (*c == ':') {
586 *ret_string = NULL;
587 *ret_value = JSON_VALUE_NULL;
588 *p = c + 1;
589 *state = INT_TO_PTR(STATE_VALUE);
590 return JSON_COLON;
591 } else if (*c == ',') {
592 *ret_string = NULL;
593 *ret_value = JSON_VALUE_NULL;
594 *p = c + 1;
595 *state = INT_TO_PTR(STATE_VALUE);
596 return JSON_COMMA;
597 } else if (*c == '}') {
598 *ret_string = NULL;
599 *ret_value = JSON_VALUE_NULL;
600 *p = c + 1;
601 *state = INT_TO_PTR(STATE_VALUE_POST);
602 return JSON_OBJECT_CLOSE;
603 } else if (*c == ']') {
604 *ret_string = NULL;
605 *ret_value = JSON_VALUE_NULL;
606 *p = c + 1;
607 *state = INT_TO_PTR(STATE_VALUE_POST);
608 return JSON_ARRAY_CLOSE;
609 } else
610 return -EINVAL;
611 }
612
613 }
614 }
615
616 static bool json_is_value(JsonVariant *var) {
617 assert(var);
618
619 return var->type != JSON_VARIANT_CONTROL;
620 }
621
622 static int json_scoped_parse(JsonVariant **tokens, size_t *i, size_t n, JsonVariant *scope) {
623 bool arr = scope->type == JSON_VARIANT_ARRAY;
624 int terminator = arr ? JSON_ARRAY_CLOSE : JSON_OBJECT_CLOSE;
625 size_t allocated = 0, size = 0;
626 JsonVariant *key = NULL, *value = NULL, *var = NULL, *items = NULL;
627 enum {
628 STATE_KEY,
629 STATE_COLON,
630 STATE_COMMA,
631 STATE_VALUE
632 } state = arr ? STATE_VALUE : STATE_KEY;
633
634 assert(tokens);
635 assert(i);
636 assert(scope);
637
638 while((var = *i < n ? tokens[(*i)++] : NULL) != NULL) {
639 bool stopper;
640 int r;
641
642 stopper = !json_is_value(var) && var->value.integer == terminator;
643
644 if (stopper) {
645 if (state != STATE_COMMA && size > 0)
646 goto error;
647
648 goto out;
649 }
650
651 if (state == STATE_KEY) {
652 if (var->type != JSON_VARIANT_STRING)
653 goto error;
654 else {
655 key = var;
656 state = STATE_COLON;
657 }
658 }
659 else if (state == STATE_COLON) {
660 if (key == NULL)
661 goto error;
662
663 if (json_is_value(var))
664 goto error;
665
666 if (var->value.integer != JSON_COLON)
667 goto error;
668
669 state = STATE_VALUE;
670 }
671 else if (state == STATE_VALUE) {
672 _cleanup_json_variant_unref_ JsonVariant *v = NULL;
673 size_t toadd = arr ? 1 : 2;
674
675 if (!json_is_value(var)) {
676 int type = (var->value.integer == JSON_ARRAY_OPEN) ? JSON_VARIANT_ARRAY : JSON_VARIANT_OBJECT;
677
678 r = json_variant_new(&v, type);
679 if (r < 0)
680 goto error;
681
682 r = json_scoped_parse(tokens, i, n, v);
683 if (r < 0)
684 goto error;
685
686 value = v;
687 }
688 else
689 value = var;
690
691 if(!GREEDY_REALLOC(items, allocated, size + toadd))
692 goto error;
693
694 if (arr) {
695 r = json_variant_deep_copy(&items[size], value);
696 if (r < 0)
697 goto error;
698 } else {
699 r = json_variant_deep_copy(&items[size], key);
700 if (r < 0)
701 goto error;
702
703 r = json_variant_deep_copy(&items[size+1], value);
704 if (r < 0)
705 goto error;
706 }
707
708 size += toadd;
709 state = STATE_COMMA;
710 }
711 else if (state == STATE_COMMA) {
712 if (json_is_value(var))
713 goto error;
714
715 if (var->value.integer != JSON_COMMA)
716 goto error;
717
718 key = NULL;
719 value = NULL;
720
721 state = arr ? STATE_VALUE : STATE_KEY;
722 }
723 }
724
725 error:
726 json_raw_unref(items, size);
727 return -EBADMSG;
728
729 out:
730 scope->size = size;
731 scope->objects = items;
732
733 return scope->type;
734 }
735
736 static int json_parse_tokens(JsonVariant **tokens, size_t ntokens, JsonVariant **rv) {
737 size_t it = 0;
738 int r;
739 JsonVariant *e;
740 _cleanup_json_variant_unref_ JsonVariant *p = NULL;
741
742 assert(tokens);
743 assert(ntokens);
744
745 e = tokens[it++];
746 r = json_variant_new(&p, JSON_VARIANT_OBJECT);
747 if (r < 0)
748 return r;
749
750 if (e->type != JSON_VARIANT_CONTROL && e->value.integer != JSON_OBJECT_OPEN)
751 return -EBADMSG;
752
753 r = json_scoped_parse(tokens, &it, ntokens, p);
754 if (r < 0)
755 return r;
756
757 *rv = p;
758 p = NULL;
759
760 return 0;
761 }
762
763 static int json_tokens(const char *string, size_t size, JsonVariant ***tokens, size_t *n) {
764 _cleanup_free_ char *buf = NULL;
765 _cleanup_(json_variant_array_unrefp) JsonVariant **items = NULL;
766 union json_value v = {};
767 void *json_state = NULL;
768 const char *p;
769 int t, r;
770 size_t allocated = 0, s = 0;
771
772 assert(string);
773 assert(n);
774
775 if (size <= 0)
776 return -EBADMSG;
777
778 buf = strndup(string, size);
779 if (!buf)
780 return -ENOMEM;
781
782 p = buf;
783 for (;;) {
784 _cleanup_json_variant_unref_ JsonVariant *var = NULL;
785 _cleanup_free_ char *rstr = NULL;
786
787 t = json_tokenize(&p, &rstr, &v, &json_state, NULL);
788
789 if (t < 0)
790 return t;
791 else if (t == JSON_END)
792 break;
793
794 if (t <= JSON_ARRAY_CLOSE) {
795 r = json_variant_new(&var, JSON_VARIANT_CONTROL);
796 if (r < 0)
797 return r;
798 var->value.integer = t;
799 } else {
800 switch (t) {
801 case JSON_STRING:
802 r = json_variant_new(&var, JSON_VARIANT_STRING);
803 if (r < 0)
804 return r;
805 var->size = strlen(rstr);
806 var->string = strdup(rstr);
807 if (!var->string) {
808 return -ENOMEM;
809 }
810 break;
811 case JSON_INTEGER:
812 r = json_variant_new(&var, JSON_VARIANT_INTEGER);
813 if (r < 0)
814 return r;
815 var->value = v;
816 break;
817 case JSON_REAL:
818 r = json_variant_new(&var, JSON_VARIANT_REAL);
819 if (r < 0)
820 return r;
821 var->value = v;
822 break;
823 case JSON_BOOLEAN:
824 r = json_variant_new(&var, JSON_VARIANT_BOOLEAN);
825 if (r < 0)
826 return r;
827 var->value = v;
828 break;
829 case JSON_NULL:
830 r = json_variant_new(&var, JSON_VARIANT_NULL);
831 if (r < 0)
832 return r;
833 break;
834 }
835 }
836
837 if (!GREEDY_REALLOC(items, allocated, s+2))
838 return -ENOMEM;
839
840 items[s++] = var;
841 items[s] = NULL;
842 var = NULL;
843 }
844
845 *n = s;
846 *tokens = items;
847 items = NULL;
848
849 return 0;
850 }
851
852 int json_parse(const char *string, JsonVariant **rv) {
853 _cleanup_(json_variant_array_unrefp) JsonVariant **s = NULL;
854 JsonVariant *v = NULL;
855 size_t n = 0;
856 int r;
857
858 assert(string);
859 assert(rv);
860
861 r = json_tokens(string, strlen(string), &s, &n);
862 if (r < 0)
863 return r;
864
865 r = json_parse_tokens(s, n, &v);
866 if (r < 0)
867 return r;
868
869 *rv = v;
870 return 0;
871 }