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