1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* util/support/json.c - JSON parser and unparser */
3 /*
4 * Copyright (c) 2010 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
7 *
8 * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 *
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * 3. Neither the name of the Institute nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37 /*
38 * Copyright (C) 2012 by the Massachusetts Institute of Technology.
39 * All rights reserved.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 *
45 * * Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 *
48 * * Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in
50 * the documentation and/or other materials provided with the
51 * distribution.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
54 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
55 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
56 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
57 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
58 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
59 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
60 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
62 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
64 * OF THE POSSIBILITY OF SUCH DAMAGE.
65 */
66
67 /*
68 * This file implements a minimal dynamic type system for JSON values and a
69 * JSON encoder and decoder. It is loosely based on the heimbase code from
70 * Heimdal.
71 */
72
73 #include <k5-platform.h>
74 #include <k5-base64.h>
75 #include <k5-json.h>
76 #include <k5-buf.h>
77
78 #define MAX_DECODE_DEPTH 64
79 #define MIN_ALLOC_SLOT 16
80
81 typedef void (*type_dealloc_fn)(void *val);
82
83 typedef struct json_type_st {
84 k5_json_tid tid;
85 const char *name;
86 type_dealloc_fn dealloc;
87 } *json_type;
88
89 struct value_base {
90 json_type isa;
91 unsigned int ref_cnt;
92 };
93
94 #define PTR2BASE(ptr) (((struct value_base *)ptr) - 1)
95 #define BASE2PTR(ptr) ((void *)(((struct value_base *)ptr) + 1))
96
97 k5_json_value
k5_json_retain(k5_json_value val)98 k5_json_retain(k5_json_value val)
99 {
100 struct value_base *p;
101
102 if (val == NULL)
103 return val;
104 p = PTR2BASE(val);
105 assert(p->ref_cnt != 0);
106 p->ref_cnt++;
107 return val;
108 }
109
110 void
k5_json_release(k5_json_value val)111 k5_json_release(k5_json_value val)
112 {
113 struct value_base *p;
114
115 if (val == NULL)
116 return;
117 p = PTR2BASE(val);
118 assert(p->ref_cnt != 0);
119 p->ref_cnt--;
120 if (p->ref_cnt == 0) {
121 if (p->isa->dealloc != NULL)
122 p->isa->dealloc(val);
123 free(p);
124 }
125 }
126
127 /* Get the type description of a k5_json_value. */
128 static json_type
get_isa(k5_json_value val)129 get_isa(k5_json_value val)
130 {
131 struct value_base *p = PTR2BASE(val);
132
133 return p->isa;
134 }
135
136 k5_json_tid
k5_json_get_tid(k5_json_value val)137 k5_json_get_tid(k5_json_value val)
138 {
139 json_type isa = get_isa(val);
140
141 return isa->tid;
142 }
143
144 static k5_json_value
alloc_value(json_type type,size_t size)145 alloc_value(json_type type, size_t size)
146 {
147 struct value_base *p = calloc(1, size + sizeof(*p));
148
149 if (p == NULL)
150 return NULL;
151 p->isa = type;
152 p->ref_cnt = 1;
153
154 return BASE2PTR(p);
155 }
156
157 /*** Null type ***/
158
159 static struct json_type_st null_type = { K5_JSON_TID_NULL, "null", NULL };
160
161 int
k5_json_null_create(k5_json_null * val_out)162 k5_json_null_create(k5_json_null *val_out)
163 {
164 *val_out = alloc_value(&null_type, 0);
165 return (*val_out == NULL) ? ENOMEM : 0;
166 }
167
168 int
k5_json_null_create_val(k5_json_value * val_out)169 k5_json_null_create_val(k5_json_value *val_out)
170 {
171 *val_out = alloc_value(&null_type, 0);
172 return (*val_out == NULL) ? ENOMEM : 0;
173 }
174
175 /*** Boolean type ***/
176
177 static struct json_type_st bool_type = { K5_JSON_TID_BOOL, "bool", NULL };
178
179 int
k5_json_bool_create(int truth,k5_json_bool * val_out)180 k5_json_bool_create(int truth, k5_json_bool *val_out)
181 {
182 k5_json_bool b;
183
184 *val_out = NULL;
185 b = alloc_value(&bool_type, 1);
186 if (b == NULL)
187 return ENOMEM;
188 *(unsigned char *)b = !!truth;
189 *val_out = b;
190 return 0;
191 }
192
193 int
k5_json_bool_value(k5_json_bool bval)194 k5_json_bool_value(k5_json_bool bval)
195 {
196 return *(unsigned char *)bval;
197 }
198
199 /*** Array type ***/
200
201 struct k5_json_array_st {
202 k5_json_value *values;
203 size_t len;
204 size_t allocated;
205 };
206
207 static void
array_dealloc(void * ptr)208 array_dealloc(void *ptr)
209 {
210 k5_json_array array = ptr;
211 size_t i;
212
213 for (i = 0; i < array->len; i++)
214 k5_json_release(array->values[i]);
215 free(array->values);
216 }
217
218 static struct json_type_st array_type = {
219 K5_JSON_TID_ARRAY, "array", array_dealloc
220 };
221
222 int
k5_json_array_create(k5_json_array * val_out)223 k5_json_array_create(k5_json_array *val_out)
224 {
225 *val_out = alloc_value(&array_type, sizeof(struct k5_json_array_st));
226 return (*val_out == NULL) ? ENOMEM : 0;
227 }
228
229 int
k5_json_array_add(k5_json_array array,k5_json_value val)230 k5_json_array_add(k5_json_array array, k5_json_value val)
231 {
232 k5_json_value *ptr;
233 size_t new_alloc;
234
235 if (array->len >= array->allocated) {
236 /* Increase the number of slots by 50% (MIN_ALLOC_SLOT minimum). */
237 new_alloc = array->len + 1 + (array->len >> 1);
238 if (new_alloc < MIN_ALLOC_SLOT)
239 new_alloc = MIN_ALLOC_SLOT;
240 ptr = realloc(array->values, new_alloc * sizeof(*array->values));
241 if (ptr == NULL)
242 return ENOMEM;
243 array->values = ptr;
244 array->allocated = new_alloc;
245 }
246 array->values[array->len++] = k5_json_retain(val);
247 return 0;
248 }
249
250 size_t
k5_json_array_length(k5_json_array array)251 k5_json_array_length(k5_json_array array)
252 {
253 return array->len;
254 }
255
256 k5_json_value
k5_json_array_get(k5_json_array array,size_t idx)257 k5_json_array_get(k5_json_array array, size_t idx)
258 {
259 if (idx >= array->len)
260 abort();
261 return array->values[idx];
262 }
263
264 void
k5_json_array_set(k5_json_array array,size_t idx,k5_json_value val)265 k5_json_array_set(k5_json_array array, size_t idx, k5_json_value val)
266 {
267 if (idx >= array->len)
268 abort();
269 k5_json_release(array->values[idx]);
270 array->values[idx] = k5_json_retain(val);
271 }
272
273 int
k5_json_array_fmt(k5_json_array * array_out,const char * template,...)274 k5_json_array_fmt(k5_json_array *array_out, const char *template, ...)
275 {
276 const char *p;
277 va_list ap;
278 const char *cstring;
279 unsigned char *data;
280 size_t len;
281 long long nval;
282 k5_json_array array;
283 k5_json_value val;
284 k5_json_number num;
285 k5_json_string str;
286 k5_json_bool b;
287 k5_json_null null;
288 int truth, ret;
289
290 *array_out = NULL;
291 if (k5_json_array_create(&array))
292 return ENOMEM;
293 va_start(ap, template);
294 for (p = template; *p != '\0'; p++) {
295 switch (*p) {
296 case 'v':
297 val = k5_json_retain(va_arg(ap, k5_json_value));
298 break;
299 case 'n':
300 if (k5_json_null_create(&null))
301 goto err;
302 val = null;
303 break;
304 case 'b':
305 truth = va_arg(ap, int);
306 if (k5_json_bool_create(truth, &b))
307 goto err;
308 val = b;
309 break;
310 case 'i':
311 nval = va_arg(ap, int);
312 if (k5_json_number_create(nval, &num))
313 goto err;
314 val = num;
315 break;
316 case 'L':
317 nval = va_arg(ap, long long);
318 if (k5_json_number_create(nval, &num))
319 goto err;
320 val = num;
321 break;
322 case 's':
323 cstring = va_arg(ap, const char *);
324 if (cstring == NULL) {
325 if (k5_json_null_create(&null))
326 goto err;
327 val = null;
328 } else {
329 if (k5_json_string_create(cstring, &str))
330 goto err;
331 val = str;
332 }
333 break;
334 case 'B':
335 data = va_arg(ap, unsigned char *);
336 len = va_arg(ap, size_t);
337 if (k5_json_string_create_base64(data, len, &str))
338 goto err;
339 val = str;
340 break;
341 default:
342 goto err;
343 }
344 ret = k5_json_array_add(array, val);
345 k5_json_release(val);
346 if (ret)
347 goto err;
348 }
349 va_end(ap);
350 *array_out = array;
351 return 0;
352
353 err:
354 va_end(ap);
355 k5_json_release(array);
356 return ENOMEM;
357 }
358
359 /*** Object type (string:value mapping) ***/
360
361 struct entry {
362 char *key;
363 k5_json_value value;
364 };
365
366 struct k5_json_object_st {
367 struct entry *entries;
368 size_t len;
369 size_t allocated;
370 };
371
372 static void
object_dealloc(void * ptr)373 object_dealloc(void *ptr)
374 {
375 k5_json_object obj = ptr;
376 size_t i;
377
378 for (i = 0; i < obj->len; i++) {
379 free(obj->entries[i].key);
380 k5_json_release(obj->entries[i].value);
381 }
382 free(obj->entries);
383 }
384
385 static struct json_type_st object_type = {
386 K5_JSON_TID_OBJECT, "object", object_dealloc
387 };
388
389 int
k5_json_object_create(k5_json_object * val_out)390 k5_json_object_create(k5_json_object *val_out)
391 {
392 *val_out = alloc_value(&object_type, sizeof(struct k5_json_object_st));
393 return (*val_out == NULL) ? ENOMEM : 0;
394 }
395
396 size_t
k5_json_object_count(k5_json_object obj)397 k5_json_object_count(k5_json_object obj)
398 {
399 return obj->len;
400 }
401
402 /* Return the entry for key within obj, or NULL if none exists. */
403 static struct entry *
object_search(k5_json_object obj,const char * key)404 object_search(k5_json_object obj, const char *key)
405 {
406 size_t i;
407
408 for (i = 0; i < obj->len; i++) {
409 if (strcmp(key, obj->entries[i].key) == 0)
410 return &obj->entries[i];
411 }
412 return NULL;
413 }
414
415 k5_json_value
k5_json_object_get(k5_json_object obj,const char * key)416 k5_json_object_get(k5_json_object obj, const char *key)
417 {
418 struct entry *ent;
419
420 ent = object_search(obj, key);
421 if (ent == NULL)
422 return NULL;
423 return ent->value;
424 }
425
426 int
k5_json_object_set(k5_json_object obj,const char * key,k5_json_value val)427 k5_json_object_set(k5_json_object obj, const char *key, k5_json_value val)
428 {
429 struct entry *ent, *ptr;
430 size_t new_alloc, i;
431
432 ent = object_search(obj, key);
433 if (ent != NULL) {
434 k5_json_release(ent->value);
435 if (val == NULL) {
436 /* Remove this key. */
437 free(ent->key);
438 for (i = ent - obj->entries; i < obj->len - 1; i++)
439 obj->entries[i] = obj->entries[i + 1];
440 obj->len--;
441 } else {
442 /* Overwrite this key's value with the new one. */
443 ent->value = k5_json_retain(val);
444 }
445 return 0;
446 }
447
448 /* If didn't find a key the caller asked to remove, do nothing. */
449 if (val == NULL)
450 return 0;
451
452 if (obj->len >= obj->allocated) {
453 /* Increase the number of slots by 50% (MIN_ALLOC_SLOT minimum). */
454 new_alloc = obj->len + 1 + (obj->len >> 1);
455 if (new_alloc < MIN_ALLOC_SLOT)
456 new_alloc = MIN_ALLOC_SLOT;
457 ptr = realloc(obj->entries, new_alloc * sizeof(*obj->entries));
458 if (ptr == NULL)
459 return ENOMEM;
460 obj->entries = ptr;
461 obj->allocated = new_alloc;
462 }
463 obj->entries[obj->len].key = strdup(key);
464 if (obj->entries[obj->len].key == NULL)
465 return ENOMEM;
466 obj->entries[obj->len].value = k5_json_retain(val);
467 obj->len++;
468 return 0;
469 }
470
471 void
k5_json_object_iterate(k5_json_object obj,k5_json_object_iterator_fn func,void * arg)472 k5_json_object_iterate(k5_json_object obj, k5_json_object_iterator_fn func,
473 void *arg)
474 {
475 size_t i;
476
477 for (i = 0; i < obj->len; i++)
478 func(arg, obj->entries[i].key, obj->entries[i].value);
479 }
480
481 /*** String type ***/
482
483 static struct json_type_st string_type = {
484 K5_JSON_TID_STRING, "string", NULL
485 };
486
487 int
k5_json_string_create(const char * cstring,k5_json_string * val_out)488 k5_json_string_create(const char *cstring, k5_json_string *val_out)
489 {
490 return k5_json_string_create_len(cstring, strlen(cstring), val_out);
491 }
492
493 int
k5_json_string_create_len(const void * data,size_t len,k5_json_string * val_out)494 k5_json_string_create_len(const void *data, size_t len,
495 k5_json_string *val_out)
496 {
497 char *s;
498
499 *val_out = NULL;
500 s = alloc_value(&string_type, len + 1);
501 if (s == NULL)
502 return ENOMEM;
503 if (len > 0)
504 memcpy(s, data, len);
505 s[len] = '\0';
506 *val_out = (k5_json_string)s;
507 return 0;
508 }
509
510 int
k5_json_string_create_base64(const void * data,size_t len,k5_json_string * val_out)511 k5_json_string_create_base64(const void *data, size_t len,
512 k5_json_string *val_out)
513 {
514 char *base64;
515 int ret;
516
517 *val_out = NULL;
518 base64 = k5_base64_encode(data, len);
519 if (base64 == NULL)
520 return ENOMEM;
521 ret = k5_json_string_create(base64, val_out);
522 free(base64);
523 return ret;
524 }
525
526 const char *
k5_json_string_utf8(k5_json_string string)527 k5_json_string_utf8(k5_json_string string)
528 {
529 return (const char *)string;
530 }
531
532 int
k5_json_string_unbase64(k5_json_string string,unsigned char ** data_out,size_t * len_out)533 k5_json_string_unbase64(k5_json_string string, unsigned char **data_out,
534 size_t *len_out)
535 {
536 unsigned char *data;
537 size_t len;
538
539 *data_out = NULL;
540 *len_out = 0;
541 data = k5_base64_decode((const char *)string, &len);
542 if (data == NULL)
543 return (len == 0) ? ENOMEM : EINVAL;
544 *data_out = data;
545 *len_out = len;
546 return 0;
547 }
548
549 /*** Number type ***/
550
551 static struct json_type_st number_type = {
552 K5_JSON_TID_NUMBER, "number", NULL
553 };
554
555 int
k5_json_number_create(long long number,k5_json_number * val_out)556 k5_json_number_create(long long number, k5_json_number *val_out)
557 {
558 k5_json_number n;
559
560 *val_out = NULL;
561 n = alloc_value(&number_type, sizeof(long long));
562 if (n == NULL)
563 return ENOMEM;
564 *((long long *)n) = number;
565 *val_out = n;
566 return 0;
567 }
568
569 long long
k5_json_number_value(k5_json_number number)570 k5_json_number_value(k5_json_number number)
571 {
572 return *(long long *)number;
573 }
574
575 /*** JSON encoding ***/
576
577 static const char quotemap_json[] = "\"\\/bfnrt";
578 static const char quotemap_c[] = "\"\\/\b\f\n\r\t";
579 static const char needs_quote[] = "\\\"\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17"
580 "\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37";
581
582 static int encode_value(struct k5buf *buf, k5_json_value val);
583
584 static void
encode_string(struct k5buf * buf,const char * str)585 encode_string(struct k5buf *buf, const char *str)
586 {
587 size_t n;
588 const char *p;
589
590 k5_buf_add(buf, "\"");
591 while (*str != '\0') {
592 n = strcspn(str, needs_quote);
593 k5_buf_add_len(buf, str, n);
594 str += n;
595 if (*str == '\0')
596 break;
597 k5_buf_add(buf, "\\");
598 p = strchr(quotemap_c, *str);
599 if (p != NULL)
600 k5_buf_add_len(buf, quotemap_json + (p - quotemap_c), 1);
601 else
602 k5_buf_add_fmt(buf, "u00%02X", (unsigned int)*str);
603 str++;
604 }
605 k5_buf_add(buf, "\"");
606 }
607
608 struct obj_ctx {
609 struct k5buf *buf;
610 int ret;
611 int first;
612 };
613
614 static void
encode_obj_entry(void * ctx,const char * key,k5_json_value value)615 encode_obj_entry(void *ctx, const char *key, k5_json_value value)
616 {
617 struct obj_ctx *j = ctx;
618
619 if (j->ret)
620 return;
621 if (j->first)
622 j->first = 0;
623 else
624 k5_buf_add(j->buf, ",");
625 encode_string(j->buf, key);
626 k5_buf_add(j->buf, ":");
627 j->ret = encode_value(j->buf, value);
628 }
629
630 static int
encode_value(struct k5buf * buf,k5_json_value val)631 encode_value(struct k5buf *buf, k5_json_value val)
632 {
633 k5_json_tid type;
634 int ret;
635 size_t i, len;
636 struct obj_ctx ctx;
637
638 if (val == NULL)
639 return EINVAL;
640
641 type = k5_json_get_tid(val);
642 switch (type) {
643 case K5_JSON_TID_ARRAY:
644 k5_buf_add(buf, "[");
645 len = k5_json_array_length(val);
646 for (i = 0; i < len; i++) {
647 if (i != 0)
648 k5_buf_add(buf, ",");
649 ret = encode_value(buf, k5_json_array_get(val, i));
650 if (ret)
651 return ret;
652 }
653 k5_buf_add(buf, "]");
654 return 0;
655
656 case K5_JSON_TID_OBJECT:
657 k5_buf_add(buf, "{");
658 ctx.buf = buf;
659 ctx.ret = 0;
660 ctx.first = 1;
661 k5_json_object_iterate(val, encode_obj_entry, &ctx);
662 k5_buf_add(buf, "}");
663 return ctx.ret;
664
665 case K5_JSON_TID_STRING:
666 encode_string(buf, k5_json_string_utf8(val));
667 return 0;
668
669 case K5_JSON_TID_NUMBER:
670 k5_buf_add_fmt(buf, "%lld", k5_json_number_value(val));
671 return 0;
672
673 case K5_JSON_TID_NULL:
674 k5_buf_add(buf, "null");
675 return 0;
676
677 case K5_JSON_TID_BOOL:
678 k5_buf_add(buf, k5_json_bool_value(val) ? "true" : "false");
679 return 0;
680
681 default:
682 return EINVAL;
683 }
684 }
685
686 int
k5_json_encode(k5_json_value val,char ** json_out)687 k5_json_encode(k5_json_value val, char **json_out)
688 {
689 struct k5buf buf;
690 int ret;
691
692 *json_out = NULL;
693 k5_buf_init_dynamic(&buf);
694 ret = encode_value(&buf, val);
695 if (ret) {
696 k5_buf_free(&buf);
697 return ret;
698 }
699 *json_out = k5_buf_cstring(&buf);
700 return (*json_out == NULL) ? ENOMEM : 0;
701 }
702
703 /*** JSON decoding ***/
704
705 struct decode_ctx {
706 const unsigned char *p;
707 size_t depth;
708 };
709
710 static int parse_value(struct decode_ctx *ctx, k5_json_value *val_out);
711
712 /* Consume whitespace. Return 0 if there is anything left to parse after the
713 * whitespace, -1 if not. */
714 static int
white_spaces(struct decode_ctx * ctx)715 white_spaces(struct decode_ctx *ctx)
716 {
717 unsigned char c;
718
719 for (; *ctx->p != '\0'; ctx->p++) {
720 c = *ctx->p;
721 if (c != ' ' && c != '\t' && c != '\r' && c != '\n')
722 return 0;
723 }
724 return -1;
725 }
726
727 /* Return true if c is a decimal digit. */
728 static inline int
is_digit(unsigned char c)729 is_digit(unsigned char c)
730 {
731 return ('0' <= c && c <= '9');
732 }
733
734 /* Return true if c is a hexadecimal digit (per RFC 5234 HEXDIG). */
735 static inline int
is_hex_digit(unsigned char c)736 is_hex_digit(unsigned char c)
737 {
738 return is_digit(c) || ('A' <= c && c <= 'F');
739 }
740
741 /* Return the numeric value of a hex digit; aborts if c is not a hex digit. */
742 static inline unsigned int
hexval(unsigned char c)743 hexval(unsigned char c)
744 {
745 if (is_digit(c))
746 return c - '0';
747 else if ('A' <= c && c <= 'F')
748 return c - 'A' + 10;
749 abort();
750 }
751
752 /* Parse a JSON number (which must be an integer in the signed 64-bit range; we
753 * do not allow floating-point numbers). */
754 static int
parse_number(struct decode_ctx * ctx,k5_json_number * val_out)755 parse_number(struct decode_ctx *ctx, k5_json_number *val_out)
756 {
757 const unsigned long long umax = ~0ULL, smax = (1ULL << 63) - 1;
758 unsigned long long number = 0;
759 int neg = 1;
760
761 *val_out = NULL;
762
763 if (*ctx->p == '-') {
764 neg = -1;
765 ctx->p++;
766 }
767
768 if (!is_digit(*ctx->p))
769 return EINVAL;
770
771 /* Read the number into an unsigned 64-bit container, ensuring that we
772 * don't overflow it. */
773 while (is_digit(*ctx->p)) {
774 if (number + 1 > umax / 10)
775 return EOVERFLOW;
776 number = (number * 10) + (*ctx->p - '0');
777 ctx->p++;
778 }
779
780 /* Make sure the unsigned 64-bit value fits in the signed 64-bit range. */
781 if (number > smax + 1 || (number > smax && neg == 1))
782 return EOVERFLOW;
783
784 return k5_json_number_create(number * neg, val_out);
785 }
786
787 /* Parse a JSON string (which must not quote Unicode code points above 256). */
788 static int
parse_string(struct decode_ctx * ctx,char ** str_out)789 parse_string(struct decode_ctx *ctx, char **str_out)
790 {
791 const unsigned char *p, *start, *end = NULL;
792 const char *q;
793 char *buf, *pos;
794 unsigned int code;
795
796 *str_out = NULL;
797
798 /* Find the start and end of the string. */
799 if (*ctx->p != '"')
800 return EINVAL;
801 start = ++ctx->p;
802 for (; *ctx->p != '\0'; ctx->p++) {
803 if (*ctx->p == '\\') {
804 ctx->p++;
805 if (*ctx->p == '\0')
806 return EINVAL;
807 } else if (*ctx->p == '"') {
808 end = ctx->p++;
809 break;
810 }
811 }
812 if (end == NULL)
813 return EINVAL;
814
815 pos = buf = malloc(end - start + 1);
816 if (buf == NULL)
817 return ENOMEM;
818 for (p = start; p < end;) {
819 if (*p == '\\') {
820 p++;
821 if (*p == 'u' && is_hex_digit(p[1]) && is_hex_digit(p[2]) &&
822 is_hex_digit(p[3]) && is_hex_digit(p[4])) {
823 code = (hexval(p[1]) << 12) | (hexval(p[2]) << 8) |
824 (hexval(p[3]) << 4) | hexval(p[4]);
825 if (code <= 0xff) {
826 *pos++ = code;
827 } else {
828 /* Code points above 0xff don't need to be quoted, so we
829 * don't implement translating those into UTF-8. */
830 free(buf);
831 return EINVAL;
832 }
833 p += 5;
834 } else {
835 q = strchr(quotemap_json, *p);
836 if (q != NULL) {
837 *pos++ = quotemap_c[q - quotemap_json];
838 } else {
839 free(buf);
840 return EINVAL;
841 }
842 p++;
843 }
844 } else {
845 *pos++ = *p++;
846 }
847 }
848 *pos = '\0';
849 *str_out = buf;
850 return 0;
851 }
852
853 /* Parse an object association and place it into obj. */
854 static int
parse_object_association(k5_json_object obj,struct decode_ctx * ctx)855 parse_object_association(k5_json_object obj, struct decode_ctx *ctx)
856 {
857 char *key = NULL;
858 k5_json_value val;
859 int ret;
860
861 /* Parse the key and value. */
862 ret = parse_string(ctx, &key);
863 if (ret)
864 return ret;
865 if (white_spaces(ctx))
866 goto invalid;
867 if (*ctx->p != ':')
868 goto invalid;
869 ctx->p++;
870 if (white_spaces(ctx))
871 goto invalid;
872 ret = parse_value(ctx, &val);
873 if (ret) {
874 free(key);
875 return ret;
876 }
877
878 /* Add the key and value to obj. */
879 ret = k5_json_object_set(obj, key, val);
880 free(key);
881 k5_json_release(val);
882 return ret;
883
884 invalid:
885 free(key);
886 return EINVAL;
887 }
888
889 /* Parse a JSON object. */
890 static int
parse_object(struct decode_ctx * ctx,k5_json_object * val_out)891 parse_object(struct decode_ctx *ctx, k5_json_object *val_out)
892 {
893 k5_json_object obj = NULL;
894 int ret;
895
896 *val_out = NULL;
897
898 /* Parse past the opening brace. */
899 if (*ctx->p != '{')
900 return EINVAL;
901 ctx->p++;
902 if (white_spaces(ctx))
903 return EINVAL;
904
905 ret = k5_json_object_create(&obj);
906 if (ret)
907 return ret;
908
909 /* Pairs associations until we reach the terminating brace. */
910 if (*ctx->p != '}') {
911 while (1) {
912 ret = parse_object_association(obj, ctx);
913 if (ret) {
914 k5_json_release(obj);
915 return ret;
916 }
917 if (white_spaces(ctx))
918 goto invalid;
919 if (*ctx->p == '}')
920 break;
921 if (*ctx->p != ',')
922 goto invalid;
923 ctx->p++;
924 if (white_spaces(ctx))
925 goto invalid;
926 }
927 }
928 ctx->p++;
929 *val_out = obj;
930 return 0;
931
932 invalid:
933 k5_json_release(obj);
934 return EINVAL;
935 }
936
937 /* Parse an value and place it into array. */
938 static int
parse_array_item(k5_json_array array,struct decode_ctx * ctx)939 parse_array_item(k5_json_array array, struct decode_ctx *ctx)
940 {
941 k5_json_value val;
942 int ret;
943
944 ret = parse_value(ctx, &val);
945 if (ret)
946 return ret;
947 ret = k5_json_array_add(array, val);
948 k5_json_release(val);
949 return ret;
950 }
951
952 /* Parse a JSON array. */
953 static int
parse_array(struct decode_ctx * ctx,k5_json_array * val_out)954 parse_array(struct decode_ctx *ctx, k5_json_array *val_out)
955 {
956 k5_json_array array = NULL;
957 int ret;
958
959 *val_out = NULL;
960
961 /* Parse past the opening bracket. */
962 if (*ctx->p != '[')
963 return EINVAL;
964 ctx->p++;
965 if (white_spaces(ctx))
966 return EINVAL;
967
968 ret = k5_json_array_create(&array);
969 if (ret)
970 return ret;
971
972 /* Pairs values until we reach the terminating bracket. */
973 if (*ctx->p != ']') {
974 while (1) {
975 ret = parse_array_item(array, ctx);
976 if (ret) {
977 k5_json_release(array);
978 return ret;
979 }
980 if (white_spaces(ctx))
981 goto invalid;
982 if (*ctx->p == ']')
983 break;
984 if (*ctx->p != ',')
985 goto invalid;
986 ctx->p++;
987 if (white_spaces(ctx))
988 goto invalid;
989 }
990 }
991 ctx->p++;
992 *val_out = array;
993 return 0;
994
995 invalid:
996 k5_json_release(array);
997 return EINVAL;
998 }
999
1000 /* Parse a JSON value of any type. */
1001 static int
parse_value(struct decode_ctx * ctx,k5_json_value * val_out)1002 parse_value(struct decode_ctx *ctx, k5_json_value *val_out)
1003 {
1004 k5_json_null null;
1005 k5_json_bool bval;
1006 k5_json_number num;
1007 k5_json_string str;
1008 k5_json_object obj;
1009 k5_json_array array;
1010 char *cstring;
1011 int ret;
1012
1013 *val_out = NULL;
1014
1015 if (white_spaces(ctx))
1016 return EINVAL;
1017
1018 if (*ctx->p == '"') {
1019 ret = parse_string(ctx, &cstring);
1020 if (ret)
1021 return ret;
1022 ret = k5_json_string_create(cstring, &str);
1023 free(cstring);
1024 if (ret)
1025 return ret;
1026 *val_out = str;
1027 } else if (*ctx->p == '{') {
1028 if (ctx->depth-- == 1)
1029 return EINVAL;
1030 ret = parse_object(ctx, &obj);
1031 if (ret)
1032 return ret;
1033 ctx->depth++;
1034 *val_out = obj;
1035 } else if (*ctx->p == '[') {
1036 if (ctx->depth-- == 1)
1037 return EINVAL;
1038 ret = parse_array(ctx, &array);
1039 ctx->depth++;
1040 *val_out = array;
1041 } else if (is_digit(*ctx->p) || *ctx->p == '-') {
1042 ret = parse_number(ctx, &num);
1043 if (ret)
1044 return ret;
1045 *val_out = num;
1046 } else if (strncmp((char *)ctx->p, "null", 4) == 0) {
1047 ctx->p += 4;
1048 ret = k5_json_null_create(&null);
1049 if (ret)
1050 return ret;
1051 *val_out = null;
1052 } else if (strncmp((char *)ctx->p, "true", 4) == 0) {
1053 ctx->p += 4;
1054 ret = k5_json_bool_create(1, &bval);
1055 if (ret)
1056 return ret;
1057 *val_out = bval;
1058 } else if (strncmp((char *)ctx->p, "false", 5) == 0) {
1059 ctx->p += 5;
1060 ret = k5_json_bool_create(0, &bval);
1061 if (ret)
1062 return ret;
1063 *val_out = bval;
1064 } else {
1065 return EINVAL;
1066 }
1067
1068 return 0;
1069 }
1070
1071 int
k5_json_decode(const char * string,k5_json_value * val_out)1072 k5_json_decode(const char *string, k5_json_value *val_out)
1073 {
1074 struct decode_ctx ctx;
1075 k5_json_value val;
1076 int ret;
1077
1078 *val_out = NULL;
1079 ctx.p = (unsigned char *)string;
1080 ctx.depth = MAX_DECODE_DEPTH;
1081 ret = parse_value(&ctx, &val);
1082 if (ret)
1083 return ret;
1084 if (white_spaces(&ctx) == 0) {
1085 k5_json_release(val);
1086 return EINVAL;
1087 }
1088 *val_out = val;
1089 return 0;
1090 }
1091