xref: /freebsd/crypto/krb5/src/util/support/json.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
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