]> git.zerfleddert.de Git - proxmark3-svn/blame - client/jansson/pack_unpack.c
Merge branch 'master' of https://github.com/Proxmark/proxmark3
[proxmark3-svn] / client / jansson / pack_unpack.c
CommitLineData
556826b5
OM
1/*
2 * Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
3 * Copyright (c) 2011-2012 Graeme Smecher <graeme.smecher@mail.mcgill.ca>
4 *
5 * Jansson is free software; you can redistribute it and/or modify
6 * it under the terms of the MIT license. See LICENSE for details.
7 */
8
9#include <string.h>
10#include "jansson.h"
11#include "jansson_private.h"
12#include "utf.h"
13
14typedef struct {
15 int line;
16 int column;
17 size_t pos;
18 char token;
19} token_t;
20
21typedef struct {
22 const char *start;
23 const char *fmt;
24 token_t prev_token;
25 token_t token;
26 token_t next_token;
27 json_error_t *error;
28 size_t flags;
29 int line;
30 int column;
31 size_t pos;
32 int has_error;
33} scanner_t;
34
35#define token(scanner) ((scanner)->token.token)
36
37static const char * const type_names[] = {
38 "object",
39 "array",
40 "string",
41 "integer",
42 "real",
43 "true",
44 "false",
45 "null"
46};
47
48#define type_name(x) type_names[json_typeof(x)]
49
50static const char unpack_value_starters[] = "{[siIbfFOon";
51
52static void scanner_init(scanner_t *s, json_error_t *error,
53 size_t flags, const char *fmt)
54{
55 s->error = error;
56 s->flags = flags;
57 s->fmt = s->start = fmt;
58 memset(&s->prev_token, 0, sizeof(token_t));
59 memset(&s->token, 0, sizeof(token_t));
60 memset(&s->next_token, 0, sizeof(token_t));
61 s->line = 1;
62 s->column = 0;
63 s->pos = 0;
64 s->has_error = 0;
65}
66
67static void next_token(scanner_t *s)
68{
69 const char *t;
70 s->prev_token = s->token;
71
72 if(s->next_token.line) {
73 s->token = s->next_token;
74 s->next_token.line = 0;
75 return;
76 }
77
78 t = s->fmt;
79 s->column++;
80 s->pos++;
81
82 /* skip space and ignored chars */
83 while(*t == ' ' || *t == '\t' || *t == '\n' || *t == ',' || *t == ':') {
84 if(*t == '\n') {
85 s->line++;
86 s->column = 1;
87 }
88 else
89 s->column++;
90
91 s->pos++;
92 t++;
93 }
94
95 s->token.token = *t;
96 s->token.line = s->line;
97 s->token.column = s->column;
98 s->token.pos = s->pos;
99
100 t++;
101 s->fmt = t;
102}
103
104static void prev_token(scanner_t *s)
105{
106 s->next_token = s->token;
107 s->token = s->prev_token;
108}
109
110static void set_error(scanner_t *s, const char *source, enum json_error_code code,
111 const char *fmt, ...)
112{
113 va_list ap;
114 va_start(ap, fmt);
115
116 jsonp_error_vset(s->error, s->token.line, s->token.column, s->token.pos,
117 code, fmt, ap);
118
119 jsonp_error_set_source(s->error, source);
120
121 va_end(ap);
122}
123
124static json_t *pack(scanner_t *s, va_list *ap);
125
126
127/* ours will be set to 1 if jsonp_free() must be called for the result
128 afterwards */
129static char *read_string(scanner_t *s, va_list *ap,
130 const char *purpose, size_t *out_len, int *ours)
131{
132 char t;
133 strbuffer_t strbuff;
134 const char *str;
135 size_t length;
136
137 next_token(s);
138 t = token(s);
139 prev_token(s);
140
141 *ours = 0;
142 if(t != '#' && t != '%' && t != '+') {
143 /* Optimize the simple case */
144 str = va_arg(*ap, const char *);
145
146 if(!str) {
147 set_error(s, "<args>", json_error_null_value, "NULL string argument");
148 return NULL;
149 }
150
151 length = strlen(str);
152
153 if(!utf8_check_string(str, length)) {
154 set_error(s, "<args>", json_error_invalid_utf8, "Invalid UTF-8 %s", purpose);
155 return NULL;
156 }
157
158 *out_len = length;
159 return (char *)str;
160 }
161
162 strbuffer_init(&strbuff);
163
164 while(1) {
165 str = va_arg(*ap, const char *);
166 if(!str) {
167 set_error(s, "<args>", json_error_null_value, "NULL string argument");
168 s->has_error = 1;
169 }
170
171 next_token(s);
172
173 if(token(s) == '#') {
174 length = va_arg(*ap, int);
175 }
176 else if(token(s) == '%') {
177 length = va_arg(*ap, size_t);
178 }
179 else {
180 prev_token(s);
181 length = s->has_error ? 0 : strlen(str);
182 }
183
184 if(!s->has_error && strbuffer_append_bytes(&strbuff, str, length) == -1) {
185 set_error(s, "<internal>", json_error_out_of_memory, "Out of memory");
186 s->has_error = 1;
187 }
188
189 next_token(s);
190 if(token(s) != '+') {
191 prev_token(s);
192 break;
193 }
194 }
195
196 if(s->has_error) {
197 strbuffer_close(&strbuff);
198 return NULL;
199 }
200
201 if(!utf8_check_string(strbuff.value, strbuff.length)) {
202 set_error(s, "<args>", json_error_invalid_utf8, "Invalid UTF-8 %s", purpose);
203 strbuffer_close(&strbuff);
204 s->has_error = 1;
205 return NULL;
206 }
207
208 *out_len = strbuff.length;
209 *ours = 1;
210 return strbuffer_steal_value(&strbuff);
211}
212
213static json_t *pack_object(scanner_t *s, va_list *ap)
214{
215 json_t *object = json_object();
216 next_token(s);
217
218 while(token(s) != '}') {
219 char *key;
220 size_t len;
221 int ours;
222 json_t *value;
223
224 if(!token(s)) {
225 set_error(s, "<format>", json_error_invalid_format, "Unexpected end of format string");
226 goto error;
227 }
228
229 if(token(s) != 's') {
230 set_error(s, "<format>", json_error_invalid_format, "Expected format 's', got '%c'", token(s));
231 goto error;
232 }
233
234 key = read_string(s, ap, "object key", &len, &ours);
235 if (!key)
236 s->has_error = 1;
237
238 next_token(s);
239
240 value = pack(s, ap);
241 if(!value) {
242 if(ours)
243 jsonp_free(key);
244
245 if(strchr("soO", token(s)) && s->next_token.token == '*') {
246 next_token(s);
247 } else {
248 s->has_error = 1;
249 }
250
251 next_token(s);
252 continue;
253 }
254
255 if(s->has_error)
256 json_decref(value);
257
258 if(!s->has_error && json_object_set_new_nocheck(object, key, value)) {
259 set_error(s, "<internal>", json_error_out_of_memory, "Unable to add key \"%s\"", key);
260 s->has_error = 1;
261 }
262
263 if(ours)
264 jsonp_free(key);
265
266 if(strchr("soO", token(s)) && s->next_token.token == '*')
267 next_token(s);
268 next_token(s);
269 }
270
271 if(!s->has_error)
272 return object;
273
274error:
275 json_decref(object);
276 return NULL;
277}
278
279static json_t *pack_array(scanner_t *s, va_list *ap)
280{
281 json_t *array = json_array();
282 next_token(s);
283
284 while(token(s) != ']') {
285 json_t *value;
286
287 if(!token(s)) {
288 set_error(s, "<format>", json_error_invalid_format, "Unexpected end of format string");
289 /* Format string errors are unrecoverable. */
290 goto error;
291 }
292
293 value = pack(s, ap);
294 if(!value) {
295 if(strchr("soO", token(s)) && s->next_token.token == '*') {
296 next_token(s);
297 } else {
298 s->has_error = 1;
299 }
300
301 next_token(s);
302 continue;
303 }
304
305 if(s->has_error)
306 json_decref(value);
307
308 if(!s->has_error && json_array_append_new(array, value)) {
309 set_error(s, "<internal>", json_error_out_of_memory, "Unable to append to array");
310 s->has_error = 1;
311 }
312
313 if(strchr("soO", token(s)) && s->next_token.token == '*')
314 next_token(s);
315 next_token(s);
316 }
317
318 if(!s->has_error)
319 return array;
320
321error:
322 json_decref(array);
323 return NULL;
324}
325
326static json_t *pack_string(scanner_t *s, va_list *ap)
327{
328 char *str;
329 size_t len;
330 int ours;
331 int nullable;
332
333 next_token(s);
334 nullable = token(s) == '?';
335 if (!nullable)
336 prev_token(s);
337
338 str = read_string(s, ap, "string", &len, &ours);
339 if (!str) {
340 return nullable ? json_null() : NULL;
341 } else if (ours) {
342 return jsonp_stringn_nocheck_own(str, len);
343 } else {
344 return json_stringn_nocheck(str, len);
345 }
346}
347
348static json_t *pack(scanner_t *s, va_list *ap)
349{
350 switch(token(s)) {
351 case '{':
352 return pack_object(s, ap);
353
354 case '[':
355 return pack_array(s, ap);
356
357 case 's': /* string */
358 return pack_string(s, ap);
359
360 case 'n': /* null */
361 return json_null();
362
363 case 'b': /* boolean */
364 return va_arg(*ap, int) ? json_true() : json_false();
365
366 case 'i': /* integer from int */
367 return json_integer(va_arg(*ap, int));
368
369 case 'I': /* integer from json_int_t */
370 return json_integer(va_arg(*ap, json_int_t));
371
372 case 'f': /* real */
373 return json_real(va_arg(*ap, double));
374
375 case 'O': /* a json_t object; increments refcount */
376 {
377 int nullable;
378 json_t *json;
379
380 next_token(s);
381 nullable = token(s) == '?';
382 if (!nullable)
383 prev_token(s);
384
385 json = va_arg(*ap, json_t *);
386 if (!json && nullable) {
387 return json_null();
388 } else {
389 return json_incref(json);
390 }
391 }
392
393 case 'o': /* a json_t object; doesn't increment refcount */
394 {
395 int nullable;
396 json_t *json;
397
398 next_token(s);
399 nullable = token(s) == '?';
400 if (!nullable)
401 prev_token(s);
402
403 json = va_arg(*ap, json_t *);
404 if (!json && nullable) {
405 return json_null();
406 } else {
407 return json;
408 }
409 }
410
411 default:
412 set_error(s, "<format>", json_error_invalid_format, "Unexpected format character '%c'",
413 token(s));
414 s->has_error = 1;
415 return NULL;
416 }
417}
418
419static int unpack(scanner_t *s, json_t *root, va_list *ap);
420
421static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
422{
423 int ret = -1;
424 int strict = 0;
425 int gotopt = 0;
426
427 /* Use a set (emulated by a hashtable) to check that all object
428 keys are accessed. Checking that the correct number of keys
429 were accessed is not enough, as the same key can be unpacked
430 multiple times.
431 */
432 hashtable_t key_set;
433
434 if(hashtable_init(&key_set)) {
435 set_error(s, "<internal>", json_error_out_of_memory, "Out of memory");
436 return -1;
437 }
438
439 if(root && !json_is_object(root)) {
440 set_error(s, "<validation>", json_error_wrong_type, "Expected object, got %s",
441 type_name(root));
442 goto out;
443 }
444 next_token(s);
445
446 while(token(s) != '}') {
447 const char *key;
448 json_t *value;
449 int opt = 0;
450
451 if(strict != 0) {
452 set_error(s, "<format>", json_error_invalid_format, "Expected '}' after '%c', got '%c'",
453 (strict == 1 ? '!' : '*'), token(s));
454 goto out;
455 }
456
457 if(!token(s)) {
458 set_error(s, "<format>", json_error_invalid_format, "Unexpected end of format string");
459 goto out;
460 }
461
462 if(token(s) == '!' || token(s) == '*') {
463 strict = (token(s) == '!' ? 1 : -1);
464 next_token(s);
465 continue;
466 }
467
468 if(token(s) != 's') {
469 set_error(s, "<format>", json_error_invalid_format, "Expected format 's', got '%c'", token(s));
470 goto out;
471 }
472
473 key = va_arg(*ap, const char *);
474 if(!key) {
475 set_error(s, "<args>", json_error_null_value, "NULL object key");
476 goto out;
477 }
478
479 next_token(s);
480
481 if(token(s) == '?') {
482 opt = gotopt = 1;
483 next_token(s);
484 }
485
486 if(!root) {
487 /* skipping */
488 value = NULL;
489 }
490 else {
491 value = json_object_get(root, key);
492 if(!value && !opt) {
493 set_error(s, "<validation>", json_error_item_not_found, "Object item not found: %s", key);
494 goto out;
495 }
496 }
497
498 if(unpack(s, value, ap))
499 goto out;
500
501 hashtable_set(&key_set, key, json_null());
502 next_token(s);
503 }
504
505 if(strict == 0 && (s->flags & JSON_STRICT))
506 strict = 1;
507
508 if(root && strict == 1) {
509 /* We need to check that all non optional items have been parsed */
510 const char *key;
511 int have_unrecognized_keys = 0;
512 strbuffer_t unrecognized_keys;
513 json_t *value;
514 long unpacked = 0;
515 if (gotopt) {
516 /* We have optional keys, we need to iter on each key */
517 json_object_foreach(root, key, value) {
518 if(!hashtable_get(&key_set, key)) {
519 unpacked++;
520
521 /* Save unrecognized keys for the error message */
522 if (!have_unrecognized_keys) {
523 strbuffer_init(&unrecognized_keys);
524 have_unrecognized_keys = 1;
525 } else {
526 strbuffer_append_bytes(&unrecognized_keys, ", ", 2);
527 }
528 strbuffer_append_bytes(&unrecognized_keys, key, strlen(key));
529 }
530 }
531 } else {
532 /* No optional keys, we can just compare the number of items */
533 unpacked = (long)json_object_size(root) - (long)key_set.size;
534 }
535 if (unpacked) {
536 if (!gotopt) {
537 /* Save unrecognized keys for the error message */
538 json_object_foreach(root, key, value) {
539 if(!hashtable_get(&key_set, key)) {
540 if (!have_unrecognized_keys) {
541 strbuffer_init(&unrecognized_keys);
542 have_unrecognized_keys = 1;
543 } else {
544 strbuffer_append_bytes(&unrecognized_keys, ", ", 2);
545 }
546 strbuffer_append_bytes(&unrecognized_keys, key, strlen(key));
547 }
548 }
549 }
550 set_error(s, "<validation>", json_error_end_of_input_expected,
551 "%li object item(s) left unpacked: %s",
552 unpacked, strbuffer_value(&unrecognized_keys));
553 strbuffer_close(&unrecognized_keys);
554 goto out;
555 }
556 }
557
558 ret = 0;
559
560out:
561 hashtable_close(&key_set);
562 return ret;
563}
564
565static int unpack_array(scanner_t *s, json_t *root, va_list *ap)
566{
567 size_t i = 0;
568 int strict = 0;
569
570 if(root && !json_is_array(root)) {
571 set_error(s, "<validation>", json_error_wrong_type, "Expected array, got %s", type_name(root));
572 return -1;
573 }
574 next_token(s);
575
576 while(token(s) != ']') {
577 json_t *value;
578
579 if(strict != 0) {
580 set_error(s, "<format>", json_error_invalid_format, "Expected ']' after '%c', got '%c'",
581 (strict == 1 ? '!' : '*'),
582 token(s));
583 return -1;
584 }
585
586 if(!token(s)) {
587 set_error(s, "<format>", json_error_invalid_format, "Unexpected end of format string");
588 return -1;
589 }
590
591 if(token(s) == '!' || token(s) == '*') {
592 strict = (token(s) == '!' ? 1 : -1);
593 next_token(s);
594 continue;
595 }
596
597 if(!strchr(unpack_value_starters, token(s))) {
598 set_error(s, "<format>", json_error_invalid_format, "Unexpected format character '%c'",
599 token(s));
600 return -1;
601 }
602
603 if(!root) {
604 /* skipping */
605 value = NULL;
606 }
607 else {
608 value = json_array_get(root, i);
609 if(!value) {
610 set_error(s, "<validation>", json_error_index_out_of_range, "Array index %lu out of range",
611 (unsigned long)i);
612 return -1;
613 }
614 }
615
616 if(unpack(s, value, ap))
617 return -1;
618
619 next_token(s);
620 i++;
621 }
622
623 if(strict == 0 && (s->flags & JSON_STRICT))
624 strict = 1;
625
626 if(root && strict == 1 && i != json_array_size(root)) {
627 long diff = (long)json_array_size(root) - (long)i;
628 set_error(s, "<validation>", json_error_end_of_input_expected, "%li array item(s) left unpacked", diff);
629 return -1;
630 }
631
632 return 0;
633}
634
635static int unpack(scanner_t *s, json_t *root, va_list *ap)
636{
637 switch(token(s))
638 {
639 case '{':
640 return unpack_object(s, root, ap);
641
642 case '[':
643 return unpack_array(s, root, ap);
644
645 case 's':
646 if(root && !json_is_string(root)) {
647 set_error(s, "<validation>", json_error_wrong_type, "Expected string, got %s",
648 type_name(root));
649 return -1;
650 }
651
652 if(!(s->flags & JSON_VALIDATE_ONLY)) {
653 const char **str_target;
654 size_t *len_target = NULL;
655
656 str_target = va_arg(*ap, const char **);
657 if(!str_target) {
658 set_error(s, "<args>", json_error_null_value, "NULL string argument");
659 return -1;
660 }
661
662 next_token(s);
663
664 if(token(s) == '%') {
665 len_target = va_arg(*ap, size_t *);
666 if(!len_target) {
667 set_error(s, "<args>", json_error_null_value, "NULL string length argument");
668 return -1;
669 }
670 }
671 else
672 prev_token(s);
673
674 if(root) {
675 *str_target = json_string_value(root);
676 if(len_target)
677 *len_target = json_string_length(root);
678 }
679 }
680 return 0;
681
682 case 'i':
683 if(root && !json_is_integer(root)) {
684 set_error(s, "<validation>", json_error_wrong_type, "Expected integer, got %s",
685 type_name(root));
686 return -1;
687 }
688
689 if(!(s->flags & JSON_VALIDATE_ONLY)) {
690 int *target = va_arg(*ap, int*);
691 if(root)
692 *target = (int)json_integer_value(root);
693 }
694
695 return 0;
696
697 case 'I':
698 if(root && !json_is_integer(root)) {
699 set_error(s, "<validation>", json_error_wrong_type, "Expected integer, got %s",
700 type_name(root));
701 return -1;
702 }
703
704 if(!(s->flags & JSON_VALIDATE_ONLY)) {
705 json_int_t *target = va_arg(*ap, json_int_t*);
706 if(root)
707 *target = json_integer_value(root);
708 }
709
710 return 0;
711
712 case 'b':
713 if(root && !json_is_boolean(root)) {
714 set_error(s, "<validation>", json_error_wrong_type, "Expected true or false, got %s",
715 type_name(root));
716 return -1;
717 }
718
719 if(!(s->flags & JSON_VALIDATE_ONLY)) {
720 int *target = va_arg(*ap, int*);
721 if(root)
722 *target = json_is_true(root);
723 }
724
725 return 0;
726
727 case 'f':
728 if(root && !json_is_real(root)) {
729 set_error(s, "<validation>", json_error_wrong_type, "Expected real, got %s",
730 type_name(root));
731 return -1;
732 }
733
734 if(!(s->flags & JSON_VALIDATE_ONLY)) {
735 double *target = va_arg(*ap, double*);
736 if(root)
737 *target = json_real_value(root);
738 }
739
740 return 0;
741
742 case 'F':
743 if(root && !json_is_number(root)) {
744 set_error(s, "<validation>", json_error_wrong_type, "Expected real or integer, got %s",
745 type_name(root));
746 return -1;
747 }
748
749 if(!(s->flags & JSON_VALIDATE_ONLY)) {
750 double *target = va_arg(*ap, double*);
751 if(root)
752 *target = json_number_value(root);
753 }
754
755 return 0;
756
757 case 'O':
758 if(root && !(s->flags & JSON_VALIDATE_ONLY))
759 json_incref(root);
760 /* Fall through */
761
762 case 'o':
763 if(!(s->flags & JSON_VALIDATE_ONLY)) {
764 json_t **target = va_arg(*ap, json_t**);
765 if(root)
766 *target = root;
767 }
768
769 return 0;
770
771 case 'n':
772 /* Never assign, just validate */
773 if(root && !json_is_null(root)) {
774 set_error(s, "<validation>", json_error_wrong_type, "Expected null, got %s",
775 type_name(root));
776 return -1;
777 }
778 return 0;
779
780 default:
781 set_error(s, "<format>", json_error_invalid_format, "Unexpected format character '%c'",
782 token(s));
783 return -1;
784 }
785}
786
787json_t *json_vpack_ex(json_error_t *error, size_t flags,
788 const char *fmt, va_list ap)
789{
790 scanner_t s;
791 va_list ap_copy;
792 json_t *value;
793
794 if(!fmt || !*fmt) {
795 jsonp_error_init(error, "<format>");
796 jsonp_error_set(error, -1, -1, 0, json_error_invalid_argument, "NULL or empty format string");
797 return NULL;
798 }
799 jsonp_error_init(error, NULL);
800
801 scanner_init(&s, error, flags, fmt);
802 next_token(&s);
803
804 va_copy(ap_copy, ap);
805 value = pack(&s, &ap_copy);
806 va_end(ap_copy);
807
808 if(!value)
809 return NULL;
810
811 next_token(&s);
812 if(token(&s)) {
813 json_decref(value);
814 set_error(&s, "<format>", json_error_invalid_format, "Garbage after format string");
815 return NULL;
816 }
817 if(s.has_error) {
818 json_decref(value);
819 return NULL;
820 }
821
822 return value;
823}
824
825json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...)
826{
827 json_t *value;
828 va_list ap;
829
830 va_start(ap, fmt);
831 value = json_vpack_ex(error, flags, fmt, ap);
832 va_end(ap);
833
834 return value;
835}
836
837json_t *json_pack(const char *fmt, ...)
838{
839 json_t *value;
840 va_list ap;
841
842 va_start(ap, fmt);
843 value = json_vpack_ex(NULL, 0, fmt, ap);
844 va_end(ap);
845
846 return value;
847}
848
849int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags,
850 const char *fmt, va_list ap)
851{
852 scanner_t s;
853 va_list ap_copy;
854
855 if(!root) {
856 jsonp_error_init(error, "<root>");
857 jsonp_error_set(error, -1, -1, 0, json_error_null_value, "NULL root value");
858 return -1;
859 }
860
861 if(!fmt || !*fmt) {
862 jsonp_error_init(error, "<format>");
863 jsonp_error_set(error, -1, -1, 0, json_error_invalid_argument, "NULL or empty format string");
864 return -1;
865 }
866 jsonp_error_init(error, NULL);
867
868 scanner_init(&s, error, flags, fmt);
869 next_token(&s);
870
871 va_copy(ap_copy, ap);
872 if(unpack(&s, root, &ap_copy)) {
873 va_end(ap_copy);
874 return -1;
875 }
876 va_end(ap_copy);
877
878 next_token(&s);
879 if(token(&s)) {
880 set_error(&s, "<format>", json_error_invalid_format, "Garbage after format string");
881 return -1;
882 }
883
884 return 0;
885}
886
887int json_unpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, ...)
888{
889 int ret;
890 va_list ap;
891
892 va_start(ap, fmt);
893 ret = json_vunpack_ex(root, error, flags, fmt, ap);
894 va_end(ap);
895
896 return ret;
897}
898
899int json_unpack(json_t *root, const char *fmt, ...)
900{
901 int ret;
902 va_list ap;
903
904 va_start(ap, fmt);
905 ret = json_vunpack_ex(root, NULL, 0, fmt, ap);
906 va_end(ap);
907
908 return ret;
909}
Impressum, Datenschutz