Coverage Report

Created: 2026-09-13 06:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tmux/json.c
Line
Count
Source
1
/* $OpenBSD: json.c,v 1.1 2026/09/08 08:33:10 nicm Exp $ */
2
3
/*
4
 * Copyright (c) 2026 Dane Jensen <dhcjensen@gmail.com>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
21
#include <ctype.h>
22
#include <errno.h>
23
#include <stdint.h>
24
#include <stdlib.h>
25
#include <string.h>
26
27
#include "tmux.h"
28
29
/*
30
 * Parse a subset of JSON. The subset accepted is:
31
 *
32
 * - Arrays may only hold objects.
33
 * - The top-level value must be an object.
34
 * - Numbers are 64-bit signed integers in base 10; there are no fractions and
35
 *   no exponents.
36
 * - There is no null, and a string may not be empty.
37
 * - Escapes are validated but not decoded.
38
 * - A key may not appear twice in the same object. Note that because escapes
39
 *   are not decoded, duplicate keys may go undetected.
40
 * - Objects may only be parsed to a fixed maximum depth.
41
 */
42
43
0
#define ERROR_CTX_LEN 8
44
0
#define PARSE_DEPTH_MAX 200
45
46
/* JSON token types. */
47
enum json_token_type {
48
  TOK_OPENOBJECT,
49
  TOK_CLOSEOBJECT,
50
  TOK_OPENARRAY,
51
  TOK_CLOSEARRAY,
52
  TOK_COMMA,
53
  TOK_COLON,
54
  TOK_QUOTE,
55
  TOK_VALUE,
56
  TOK_EOF
57
};
58
59
/* JSON token. */
60
struct json_token {
61
  enum json_token_type  type;
62
  int     offset;
63
  int     len;
64
};
65
66
/* JSON tokens. */
67
struct json_tokens {
68
  int      size;
69
  int      capacity;
70
  struct json_token *toks;
71
};
72
73
/* JSON node type. */
74
enum json_node_type {
75
  NODE_STRING,
76
  NODE_NUMBER,
77
  NODE_BOOLEAN,
78
  NODE_OBJECT,
79
  NODE_ARRAY
80
};
81
82
/* JSON field tree. */
83
RB_HEAD(json_fields, json_node);
84
85
/* JSON array queue. */
86
TAILQ_HEAD(json_members, json_node);
87
88
/* JSON parse context. */
89
struct json_parse_ctx {
90
  const char   *input;
91
  char    **cause;
92
  int     depth;
93
};
94
95
/* JSON node. */
96
struct json_node {
97
  enum json_node_type    type;
98
  char        *key;
99
  struct json_node    *parent;
100
  union {
101
    char      *str;
102
    int64_t      num;
103
    int      boolean;
104
    struct json_fields   fields;
105
    struct json_members  members;
106
  };
107
  RB_ENTRY(json_node)    oentry;
108
  TAILQ_ENTRY(json_node)     aentry;
109
};
110
111
static int
112
json_node_cmp(struct json_node *a, struct json_node *b)
113
0
{
114
0
  return (strcmp(a->key, b->key));
115
0
}
116
0
RB_GENERATE_STATIC(json_fields, json_node, oentry, json_node_cmp);
Unexecuted instantiation: json.c:json_fields_RB_FIND
Unexecuted instantiation: json.c:json_fields_RB_MINMAX
Unexecuted instantiation: json.c:json_fields_RB_REMOVE
Unexecuted instantiation: json.c:json_fields_RB_REMOVE_COLOR
Unexecuted instantiation: json.c:json_fields_RB_INSERT
117
0
118
0
static struct json_tokens *json_tokenize_input(const char *, char **);
119
0
static struct json_tokens *json_create_tokens(void);
120
0
static void    json_destroy_tokens(struct json_tokens *);
121
0
static void    json_add_token(struct json_tokens *,
122
0
           enum json_token_type, const char *, const char *,
123
0
           int);
124
0
static int     json_tokenize_value(struct json_tokens *,
125
0
           const char *);
126
0
static void    json_error(char **, const char *, const char *);
127
0
static struct json_node *json_create_node(struct json_node *,
128
0
           enum json_node_type, const char *, void *);
129
0
static void    json_assign_value(struct json_node *, void *);
130
0
static struct json_node *json_parse_tokens(struct json_tokens **,
131
0
           struct json_parse_ctx *);
132
0
static char   *json_parse_key(struct json_token **,
133
0
           struct json_parse_ctx *);
134
0
static struct json_node *json_parse_object(struct json_token **,
135
0
           struct json_parse_ctx *, const char *,
136
0
           struct json_node *);
137
0
static struct json_node *json_parse_array(struct json_token **,
138
0
           struct json_parse_ctx *, const char *,
139
0
           struct json_node *);
140
0
static struct json_node *json_parse_string(struct json_token **,
141
0
           struct json_parse_ctx *, const char *,
142
0
           struct json_node *);
143
0
static struct json_node *json_parse_number(struct json_token **,
144
0
           struct json_parse_ctx *, const char *,
145
0
           struct json_node *);
146
0
static struct json_node *json_parse_boolean(struct json_token **,
147
0
           struct json_parse_ctx *, const char *,
148
0
           struct json_node *);
149
0
150
0
/* Parse an input string into JSON. */
151
0
struct json_node *
152
0
json_parse(const char *input, char **cause)
153
0
{
154
0
  struct json_tokens  *tokens;
155
0
  struct json_parse_ctx  pctx;
156
157
0
  if (*input == '\0') {
158
0
    json_error(cause, "empty input", NULL);
159
0
    return (NULL);
160
0
  }
161
162
0
  if ((tokens = json_tokenize_input(input, cause)) == NULL)
163
0
    return (NULL);
164
165
0
  pctx.input = input;
166
0
  pctx.cause = cause;
167
0
  pctx.depth = 0;
168
169
0
  return (json_parse_tokens(&tokens, &pctx));
170
0
}
171
172
/* Returns a field node from an object node. */
173
struct json_node *
174
json_find(struct json_node *jn, const char *key)
175
0
{
176
0
  struct json_node  *node = (struct json_node *)jn, tmp = { 0 };
177
178
0
  if (jn->type != NODE_OBJECT)
179
0
    return (NULL);
180
181
0
  tmp.key = (char *)key;
182
0
  return (RB_FIND(json_fields, &node->fields, &tmp));
183
0
}
184
185
/* Returns the first member of an array node. */
186
struct json_node *
187
json_array_first(struct json_node *jn)
188
0
{
189
0
  if (jn->type != NODE_ARRAY)
190
0
    return (NULL);
191
192
0
  return (TAILQ_FIRST(&jn->members));
193
0
}
194
195
/* Returns the next member of an array's member node. */
196
struct json_node *
197
json_array_next(struct json_node *member)
198
0
{
199
0
  if (member == NULL ||
200
0
      member->parent == NULL ||
201
0
      member->parent->type != NODE_ARRAY)
202
0
    return (NULL);
203
0
  return (TAILQ_NEXT(member, aentry));
204
0
}
205
206
/* Returns the string value from a node. */
207
int
208
json_get_string(struct json_node *jn, const char **s)
209
0
{
210
0
  if (jn->type != NODE_STRING)
211
0
    return (-1);
212
213
0
  *s = jn->str;
214
0
  return (0);
215
0
}
216
217
/* Returns the number value from a node. */
218
int
219
json_get_number(struct json_node *jn, int64_t *i)
220
0
{
221
0
  if (jn->type != NODE_NUMBER)
222
0
    return (-1);
223
224
0
  *i = jn->num;
225
0
  return (0);
226
0
}
227
228
/* Returns the boolean value from a node. */
229
int
230
json_get_boolean(struct json_node *jn, int *b)
231
0
{
232
0
  if (jn->type != NODE_BOOLEAN)
233
0
    return (-1);
234
235
0
  *b = jn->boolean;
236
0
  return (0);
237
0
}
238
239
/* Returns the object value from a node. */
240
int
241
json_get_object(struct json_node *jn, struct json_node **o)
242
0
{
243
0
  if (jn->type != NODE_OBJECT)
244
0
    return (-1);
245
246
0
  *o = jn;
247
0
  return (0);
248
0
}
249
250
/* Returns the array value from a node. */
251
int
252
json_get_array(struct json_node *jn, struct json_node **a)
253
0
{
254
0
  if (jn->type != NODE_ARRAY)
255
0
    return (-1);
256
257
0
  *a = jn;
258
0
  return (0);
259
0
}
260
261
/* Returns the string value from a given key in an object node. */
262
int
263
json_find_string(struct json_node *jn, const char *key, const char **out,
264
    char **cause)
265
0
{
266
0
  struct json_node  *field;
267
268
0
  if ((field = json_find(jn, key)) == NULL) {
269
0
    if (cause != NULL)
270
0
      xasprintf(cause, "key \"%s\" not found", key);
271
0
    return (-1);
272
0
  }
273
0
  if (field->type != NODE_STRING) {
274
0
    if (cause != NULL)
275
0
      xasprintf(cause, "key \"%s\" expected a string", key);
276
0
    return (-1);
277
0
  }
278
0
  *out = field->str;
279
280
0
  return (0);
281
0
}
282
283
/* Returns the number value from a given key in an object node. */
284
int
285
json_find_number(struct json_node *jn, const char *key, int64_t *out,
286
    char **cause)
287
0
{
288
0
  struct json_node  *field;
289
290
0
  if ((field = json_find(jn, key)) == NULL) {
291
0
    if (cause != NULL)
292
0
      xasprintf(cause, "key \"%s\" not found", key);
293
0
    return (-1);
294
0
  }
295
0
  if (field->type != NODE_NUMBER) {
296
0
    if (cause != NULL)
297
0
      xasprintf(cause, "key \"%s\" expected a number", key);
298
0
    return (-1);
299
0
  }
300
0
  *out = field->num;
301
302
0
  return (0);
303
0
}
304
305
/* Returns the boolean value from a given key in an object node. */
306
int
307
json_find_boolean(struct json_node *jn, const char *key, int *out, char **cause)
308
0
{
309
0
  struct json_node  *field;
310
311
0
  if ((field = json_find(jn, key)) == NULL) {
312
0
    if (cause != NULL)
313
0
      xasprintf(cause, "key \"%s\" not found", key);
314
0
    return (-1);
315
0
  }
316
0
  if (field->type != NODE_BOOLEAN) {
317
0
    if (cause != NULL)
318
0
      xasprintf(cause, "key \"%s\" expected a boolean", key);
319
0
    return (-1);
320
0
  }
321
0
  *out = field->boolean;
322
323
0
  return (0);
324
0
}
325
326
/* Returns the object value from a given key in an object node. */
327
int
328
json_find_object(struct json_node *jn, const char *key, struct json_node **out,
329
    char **cause)
330
0
{
331
0
  struct json_node  *field;
332
333
0
  if ((field = json_find(jn, key)) == NULL) {
334
0
    if (cause != NULL)
335
0
      xasprintf(cause, "key \"%s\" not found", key);
336
0
    return (-1);
337
0
  }
338
0
  if (field->type != NODE_OBJECT) {
339
0
    if (cause != NULL)
340
0
      xasprintf(cause, "key \"%s\" expected an object", key);
341
0
    return (-1);
342
0
  }
343
0
  *out = field;
344
345
0
  return (0);
346
0
}
347
348
/* Returns the array value from a given key in an object node. */
349
int
350
json_find_array(struct json_node *jn, const char *key, struct json_node **out,
351
    char **cause)
352
0
{
353
0
  struct json_node  *field;
354
355
0
  if ((field = json_find(jn, key)) == NULL) {
356
0
    if (cause != NULL)
357
0
      xasprintf(cause, "key \"%s\" not found", key);
358
0
    return (-1);
359
0
  }
360
0
  if (field->type != NODE_ARRAY) {
361
0
    if (cause != NULL)
362
0
      xasprintf(cause, "key \"%s\" expected an array", key);
363
0
    return (-1);
364
0
  }
365
0
  *out = field;
366
367
0
  return (0);
368
0
}
369
370
/* Fill an error cause. */
371
static void
372
json_error(char **cause, const char *reason, const char *loc)
373
0
{
374
0
  const char  *ellipsis = "...";
375
0
  int    i;
376
377
0
  if (cause == NULL)
378
0
    return;
379
0
  if (loc == NULL || *loc == '\0') {
380
0
    xasprintf(cause, "%s", reason);
381
0
    return;
382
0
  }
383
384
0
  for (i = 0; i < ERROR_CTX_LEN + 1; i++) {
385
0
    if (loc[i] == '\0') {
386
0
      ellipsis = "";
387
0
      break;
388
0
    }
389
0
  }
390
391
0
  xasprintf(cause, "%s: %.*s%s", reason, ERROR_CTX_LEN, loc, ellipsis);
392
0
}
393
394
/* Tokenize the json string. */
395
static struct json_tokens *
396
json_tokenize_input(const char *input, char **cause)
397
0
{
398
0
  struct json_tokens  *tokens;
399
0
  enum json_token_type   type;
400
0
  const char    *loc, *start = input;
401
0
  int      in_string = 0, scan;
402
403
0
  tokens = json_create_tokens();
404
0
  while (*input != '\0') {
405
0
    loc = input;
406
0
    scan = 1;
407
408
0
    if (in_string && *input != '"') {
409
0
      type = TOK_VALUE;
410
0
    } else {
411
0
      switch (*input) {
412
0
      case ' ':
413
0
      case '\t':
414
0
      case '\n':
415
0
      case '\r':
416
0
        input++;
417
0
        continue;
418
0
      case '{':
419
0
        type = TOK_OPENOBJECT;
420
0
        break;
421
0
      case '}':
422
0
        type = TOK_CLOSEOBJECT;
423
0
        break;
424
0
      case '[':
425
0
        type = TOK_OPENARRAY;
426
0
        break;
427
0
      case ']':
428
0
        type = TOK_CLOSEARRAY;
429
0
        break;
430
0
      case '"':
431
0
        type = TOK_QUOTE;
432
0
        break;
433
0
      case ':':
434
0
        type = TOK_COLON;
435
0
        break;
436
0
      case ',':
437
0
        type = TOK_COMMA;
438
0
        break;
439
0
      default:
440
0
        type = TOK_VALUE;
441
0
        break;
442
0
      }
443
0
    }
444
0
    if (type == TOK_VALUE) {
445
0
      scan = json_tokenize_value(tokens, loc);
446
0
      if (scan == -1)
447
0
        goto fail;
448
0
      input += scan - 1;
449
0
    }
450
0
    json_add_token(tokens, type, start, loc, scan);
451
0
    if (type == TOK_QUOTE)
452
0
      in_string = !in_string;
453
454
0
    input++;
455
0
  }
456
0
  json_add_token(tokens, TOK_EOF, start, loc, 0);
457
458
0
  return (tokens);
459
460
0
fail:
461
0
  json_error(cause, "tokenization error", loc);
462
0
  json_destroy_tokens(tokens);
463
0
  return (NULL);
464
0
}
465
466
/*
467
 * Tokenize a value from the input string. Strings are terminated by a '"', and
468
 * numbers/booleans are terminated by a ',', ']', '}', or whitespace.
469
 */
470
static int
471
json_tokenize_value(struct json_tokens *tokens, const char *loc)
472
0
{
473
0
  struct json_token *prev;
474
0
  int      i, scan = 0;
475
476
0
  if (tokens->size == 0)
477
0
    return (-1);
478
0
  prev = &tokens->toks[tokens->size - 1];
479
480
0
  if (prev->type == TOK_QUOTE) {
481
0
    while (loc[scan] != '"') {
482
0
      if (loc[scan] == '\0' || (u_char)loc[scan] < 0x20)
483
0
        return (-1);
484
0
      if (loc[scan] != '\\') {
485
0
        scan++;
486
0
        continue;
487
0
      }
488
0
      scan++;
489
0
      switch (loc[scan]) {
490
0
      case '"':
491
0
      case '\\':
492
0
      case '/':
493
0
      case 'b':
494
0
      case 'f':
495
0
      case 'n':
496
0
      case 'r':
497
0
      case 't':
498
0
        scan++;
499
0
        break;
500
0
      case 'u':
501
0
        for (i = 1; i <= 4; i++) {
502
0
          if (!isxdigit((u_char)loc[scan + i]))
503
0
            return (-1);
504
0
        }
505
0
        scan += 5;
506
0
        break;
507
0
      default:
508
0
        return (-1);
509
0
      }
510
0
    }
511
0
  } else if (prev->type == TOK_COLON) {
512
0
    do {
513
0
      if (loc[scan] == '\0')
514
0
        return (-1);
515
0
      scan++;
516
0
    } while (loc[scan] != ']' && loc[scan] != '}' &&
517
0
        loc[scan] != ',' && !isspace((u_char) loc[scan]));
518
0
  } else
519
0
    return (-1);
520
521
0
  return (scan);
522
0
}
523
524
/* Create a new token container. */
525
static struct json_tokens *
526
json_create_tokens(void)
527
0
{
528
0
  struct json_tokens  *tokens;
529
530
0
  tokens = xmalloc(sizeof *tokens);
531
0
  tokens->size = 0;
532
0
  tokens->capacity = 1024;
533
0
  tokens->toks = xmalloc(tokens->capacity * sizeof *tokens->toks);
534
535
0
  return (tokens);
536
0
}
537
538
/* Free a token container. */
539
static void
540
json_destroy_tokens(struct json_tokens *tokens)
541
0
{
542
0
  free(tokens->toks);
543
0
  tokens->toks = NULL;
544
0
  free(tokens);
545
0
}
546
547
/* Add a token to tokens. */
548
static void
549
json_add_token(struct json_tokens *tokens, enum json_token_type type,
550
    const char *input, const char *loc, int len)
551
0
{
552
0
  struct json_token *tok;
553
554
0
  while (tokens->size >= tokens->capacity) {
555
0
    tokens->capacity *= 2;
556
0
    tokens->toks = xrealloc(tokens->toks,
557
0
        sizeof *tokens->toks * tokens->capacity);
558
0
  }
559
560
0
  tok = &tokens->toks[tokens->size++];
561
0
  tok->type = type;
562
0
  tok->offset = loc - input;
563
0
  tok->len = len;
564
0
}
565
566
/* Create a node and assign given values. */
567
static struct json_node *
568
json_create_node(struct json_node *parent, enum json_node_type type,
569
    const char *key, void *val)
570
0
{
571
0
  struct json_node  *node;
572
573
0
  node = xcalloc(1, sizeof *node);
574
0
  node->parent = parent;
575
0
  if (key != NULL)
576
0
    node->key = xstrdup(key);
577
0
  node->type = type;
578
0
  if (type == NODE_OBJECT)
579
0
    RB_INIT(&node->fields);
580
0
  else if (type == NODE_ARRAY)
581
0
    TAILQ_INIT(&node->members);
582
0
  if (val != NULL)
583
0
    json_assign_value(node, val);
584
585
0
  return (node);
586
0
}
587
588
/* Destroy a node and all of the node's fields. */
589
void
590
json_destroy_node(struct json_node *node)
591
0
{
592
0
  struct json_node  *field, *field1, *member;
593
594
0
  if (node == NULL)
595
0
    return;
596
597
0
  switch (node->type) {
598
0
  case NODE_STRING:
599
0
    free(node->str);
600
0
    break;
601
0
  case NODE_NUMBER:
602
0
  case NODE_BOOLEAN:
603
0
    break;
604
0
  case NODE_OBJECT:
605
0
    RB_FOREACH_SAFE(field, json_fields, &node->fields, field1) {
606
0
      RB_REMOVE(json_fields, &node->fields, field);
607
0
      json_destroy_node(field);
608
0
    }
609
0
    break;
610
0
  case NODE_ARRAY:
611
0
    while (!TAILQ_EMPTY(&node->members)) {
612
0
      member = TAILQ_FIRST(&node->members);
613
0
      TAILQ_REMOVE(&node->members, member, aentry);
614
0
      json_destroy_node(member);
615
0
    }
616
0
    break;
617
0
  }
618
619
0
  if (node->key != NULL)
620
0
    free(node->key);
621
0
  free(node);
622
0
}
623
624
/* Assign a value to a node. */
625
static void
626
json_assign_value(struct json_node *node, void *val)
627
0
{
628
0
  struct json_node  *child = val;
629
630
0
  switch (node->type) {
631
0
  case NODE_STRING:
632
0
    node->str = val;
633
0
    break;
634
0
  case NODE_NUMBER:
635
0
    node->num = *(int64_t *)val;
636
0
    break;
637
0
  case NODE_BOOLEAN:
638
0
    node->boolean = *(int *)val;
639
0
    break;
640
0
  case NODE_OBJECT:
641
0
    RB_INSERT(json_fields, &node->fields, child);
642
0
    break;
643
0
  case NODE_ARRAY:
644
0
    TAILQ_INSERT_TAIL(&node->members, child, aentry);
645
0
    break;
646
0
  default:
647
0
    fatalx("unknown node type");
648
0
  }
649
0
}
650
651
/* Parse a stream of tokens into nodes. Consumes the tokens. */
652
static struct json_node *
653
json_parse_tokens(struct json_tokens **tokens, struct json_parse_ctx *pctx)
654
0
{
655
0
  struct json_token *tok = (*tokens)->toks;
656
0
  struct json_node  *jn = NULL;
657
658
0
  if (tok->type == TOK_OPENOBJECT)
659
0
    jn = json_parse_object(&tok, pctx, NULL, NULL);
660
0
  else {
661
0
    json_error(pctx->cause, "expected object",
662
0
        pctx->input + tok->offset);
663
0
    goto fail;
664
0
  }
665
0
  if (jn == NULL)
666
0
    goto fail;
667
668
0
  if (tok->type != TOK_EOF) {
669
0
    json_error(pctx->cause, "unexpected trailing data",
670
0
        pctx->input + tok->offset);
671
0
    goto fail;
672
0
  }
673
0
  json_destroy_tokens(*tokens);
674
0
  *tokens = NULL;
675
676
0
  return (jn);
677
678
0
fail:
679
0
  if (jn != NULL)
680
0
    json_destroy_node(jn);
681
0
  json_destroy_tokens(*tokens);
682
0
  *tokens = NULL;
683
0
  return (NULL);
684
0
}
685
686
/* Parse and return a key string, and advance the token pointer. */
687
static char *
688
json_parse_key(struct json_token **tok, struct json_parse_ctx *pctx)
689
0
{
690
0
  int    len;
691
0
  const char  *loc, *start = pctx->input + (*tok)->offset;
692
0
  char    *key;
693
694
0
  if ((*tok)->type != TOK_QUOTE)
695
0
    goto fail;
696
0
  (*tok)++;
697
698
0
  loc = pctx->input + (*tok)->offset;
699
0
  len = (*tok)->len;
700
701
0
  if ((*tok)->type != TOK_VALUE)
702
0
    goto fail;
703
0
  (*tok)++;
704
0
  if ((*tok)->type != TOK_QUOTE)
705
0
    goto fail;
706
707
0
  key = xstrndup(loc, len);
708
0
  (*tok)++;
709
710
0
  return (key);
711
712
0
fail:
713
0
  json_error(pctx->cause, "invalid key", start);
714
0
  return (NULL);
715
0
}
716
717
/* Parse an object value, return the node, and advance the token pointer. */
718
static struct json_node *
719
json_parse_object(struct json_token **tok, struct json_parse_ctx *pctx,
720
    const char *key, struct json_node *parent)
721
0
{
722
0
  struct json_node  *object, *field;
723
0
  char      *fkey = NULL;
724
0
  u_char      *valstr;
725
726
0
  if ((*tok)->type != TOK_OPENOBJECT)
727
0
    return (NULL);
728
729
0
  pctx->depth++;
730
0
  if (pctx->depth > PARSE_DEPTH_MAX) {
731
0
    json_error(pctx->cause, "parse depth exceeded",
732
0
        pctx->input + (*tok)->offset);
733
0
    return (NULL);
734
0
  }
735
736
0
  (*tok)++;
737
738
0
  object = json_create_node(parent, NODE_OBJECT, key, NULL);
739
0
  while ((*tok)->type != TOK_CLOSEOBJECT) {
740
0
    if ((fkey = json_parse_key(tok, pctx)) == NULL)
741
0
      goto fail;
742
0
    if (json_find(object, fkey) != NULL) {
743
0
      json_error(pctx->cause, "duplicate key",
744
0
          pctx->input + (*tok)->offset);
745
0
      goto fail;
746
0
    }
747
0
    if ((*tok)->type != TOK_COLON) {
748
0
      json_error(pctx->cause, "missing colon",
749
0
          pctx->input + (*tok)->offset);
750
0
      goto fail;
751
0
    }
752
0
    (*tok)++;
753
754
0
    switch ((*tok)->type) {
755
0
    case TOK_QUOTE:
756
0
      field = json_parse_string(tok, pctx, fkey, object);
757
0
      break;
758
0
    case TOK_VALUE:
759
0
      valstr = (u_char *)(pctx->input + (*tok)->offset);
760
0
      if ((*valstr == '-' && isdigit(valstr[1])) ||
761
0
          isdigit(*valstr)) {
762
0
        field = json_parse_number(tok, pctx, fkey,
763
0
            object);
764
0
      } else {
765
0
        field = json_parse_boolean(tok, pctx, fkey,
766
0
            object);
767
0
      }
768
0
      break;
769
0
    case TOK_OPENOBJECT:
770
0
      field = json_parse_object(tok, pctx, fkey, object);
771
0
      break;
772
0
    case TOK_OPENARRAY:
773
0
      field = json_parse_array(tok, pctx, fkey, object);
774
0
      break;
775
0
    default:
776
0
      json_error(pctx->cause,
777
0
          "unexpected value when parsing object",
778
0
          pctx->input + (*tok)->offset);
779
0
      goto fail;
780
0
    }
781
0
    if (field == NULL)
782
0
      goto fail;
783
784
0
    json_assign_value(object, field);
785
0
    if ((*tok)->type == TOK_COMMA) {
786
0
      if ((*tok)[1].type == TOK_CLOSEOBJECT) {
787
0
        json_error(pctx->cause, "invalid object",
788
0
            pctx->input + (*tok)->offset);
789
0
        goto fail;
790
0
      }
791
0
      (*tok)++;
792
0
    } else if ((*tok)->type != TOK_CLOSEOBJECT) {
793
0
      json_error(pctx->cause, "invalid object",
794
0
          pctx->input + (*tok)->offset);
795
0
      goto fail;
796
0
    }
797
0
    free(fkey);
798
0
  }
799
0
  (*tok)++;
800
0
  pctx->depth--;
801
0
  return (object);
802
803
0
fail:
804
0
  if (fkey != NULL)
805
0
    free(fkey);
806
0
  json_destroy_node(object);
807
0
  return (NULL);
808
0
}
809
810
/* Parse an array value, return the node, and advance the token pointer. */
811
static struct json_node *
812
json_parse_array(struct json_token **tok, struct json_parse_ctx *pctx,
813
    const char *key, struct json_node *parent)
814
0
{
815
0
  struct json_node  *array, *member;
816
817
0
  if ((*tok)->type != TOK_OPENARRAY)
818
0
    return (NULL);
819
0
  (*tok)++;
820
821
0
  array = json_create_node(parent, NODE_ARRAY, key, NULL);
822
0
  while ((*tok)->type != TOK_CLOSEARRAY) {
823
0
    switch ((*tok)->type) {
824
0
    case TOK_OPENOBJECT:
825
0
      member = json_parse_object(tok, pctx, NULL, array);
826
0
      break;
827
0
    default:
828
0
      json_error(pctx->cause, "invalid array member",
829
0
          pctx->input + (*tok)->offset);
830
0
      goto fail;
831
0
    }
832
0
    if (member == NULL)
833
0
      goto fail;
834
835
0
    json_assign_value(array, member);
836
837
0
    if ((*tok)->type == TOK_COMMA) {
838
0
      if ((*tok)[1].type == TOK_CLOSEARRAY) {
839
0
        json_error(pctx->cause, "invalid array",
840
0
            pctx->input + (*tok)->offset);
841
0
        goto fail;
842
0
      }
843
0
      (*tok)++;
844
0
    } else if ((*tok)->type != TOK_CLOSEARRAY) {
845
0
      json_error(pctx->cause, "invalid array",
846
0
          pctx->input + (*tok)->offset);
847
0
      goto fail;
848
0
    }
849
0
  }
850
0
  (*tok)++;
851
0
  return (array);
852
853
0
fail:
854
0
  json_destroy_node(array);
855
0
  return (NULL);
856
0
}
857
858
/* Parse a string value, return the node, and advance the token pointer. */
859
static struct json_node *
860
json_parse_string(struct json_token **tok, struct json_parse_ctx *pctx,
861
    const char *key, struct json_node *parent)
862
0
{
863
0
  const char  *loc, *start = pctx->input + (*tok)->offset;
864
0
  char    *str;
865
0
  int    len;
866
867
0
  if ((*tok)->type != TOK_QUOTE)
868
0
    goto fail;
869
0
  (*tok)++;
870
0
  if ((*tok)->type != TOK_VALUE)
871
0
    goto fail;
872
873
0
  loc = pctx->input + (*tok)->offset;
874
0
  len = (*tok)->len;
875
0
  (*tok)++;
876
877
0
  if ((*tok)->type != TOK_QUOTE)
878
0
    goto fail;
879
0
  (*tok)++;
880
881
0
  str = xstrndup(loc, len);
882
0
  return (json_create_node(parent, NODE_STRING, key, str));
883
884
0
fail:
885
0
  json_error(pctx->cause, "invalid string", start);
886
0
  return (NULL);
887
0
}
888
889
/* Parse a number value, return the node, and advance the token pointer. */
890
static struct json_node *
891
json_parse_number(struct json_token **tok, struct json_parse_ctx *pctx,
892
    const char *key, struct json_node *parent)
893
0
{
894
0
  const char  *start = pctx->input + (*tok)->offset;
895
0
  char    *endptr;
896
0
  int64_t    num;
897
0
  int    len = (*tok)->len;
898
899
0
  if ((start[0] == '0' && len != 1) ||
900
0
      (start[0] == '-' && start[1] == '0' && len != 2))
901
0
    goto fail;
902
903
0
  errno = 0;
904
0
  num = strtoll(start, &endptr, 10);
905
0
  if (errno != 0 || endptr != start + len)
906
0
    goto fail;
907
0
  (*tok)++;
908
909
0
  return (json_create_node(parent, NODE_NUMBER, key, &num));
910
911
0
fail:
912
0
  json_error(pctx->cause, "invalid number", start);
913
0
  return (NULL);
914
0
}
915
916
/* Parse a boolean value, return the node, and advance the token pointer. */
917
static struct json_node *
918
json_parse_boolean(struct json_token **tok, struct json_parse_ctx *pctx,
919
    const char *key, struct json_node *parent)
920
0
{
921
0
  int    len = (*tok)->len, boolean;
922
0
  const char  *start = pctx->input + (*tok)->offset;
923
924
0
  if (strncmp(start, "true", len) == 0 && len == 4)
925
0
    boolean = 1;
926
0
  else if (strncmp(start, "false", len) == 0 && len == 5)
927
0
    boolean = 0;
928
0
  else
929
0
    goto fail;
930
0
  (*tok)++;
931
932
0
  return (json_create_node(parent, NODE_BOOLEAN, key, &boolean));
933
934
0
fail:
935
0
  json_error(pctx->cause, "invalid boolean", start);
936
0
  return (NULL);
937
0
}
938
939
/* Append a node as JSON. */
940
static void
941
json_string_append(struct evbuffer *buffer, struct json_node *node)
942
0
{
943
0
  struct json_node  *field, *member;
944
0
  const char  *s;
945
0
  int    comma = 0;
946
947
0
  switch (node->type) {
948
0
  case NODE_STRING:
949
0
    evbuffer_add_printf(buffer, "\"%s\"", node->str);
950
0
    break;
951
0
  case NODE_NUMBER:
952
0
    evbuffer_add_printf(buffer, "%lld", (long long)node->num);
953
0
    break;
954
0
  case NODE_BOOLEAN:
955
0
    if (node->boolean)
956
0
      s = "true";
957
0
    else
958
0
      s = "false";
959
0
    evbuffer_add(buffer, s, strlen(s));
960
0
    break;
961
0
  case NODE_OBJECT:
962
0
    evbuffer_add(buffer, "{", 1);
963
0
    RB_FOREACH(field, json_fields, &node->fields) {
964
0
      if (comma)
965
0
        evbuffer_add(buffer, ",", 1);
966
0
      evbuffer_add_printf(buffer, "\"%s\":", field->key);
967
0
      json_string_append(buffer, field);
968
0
      comma = 1;
969
0
    }
970
0
    evbuffer_add(buffer, "}", 1);
971
0
    break;
972
0
  case NODE_ARRAY:
973
0
    evbuffer_add(buffer, "[", 1);
974
0
    TAILQ_FOREACH(member, &node->members, aentry) {
975
0
      if (comma)
976
0
        evbuffer_add(buffer, ",", 1);
977
0
      json_string_append(buffer, member);
978
0
      comma = 1;
979
0
    }
980
0
    evbuffer_add(buffer, "]", 1);
981
0
    break;
982
0
  }
983
0
}
984
985
/* Convert a node back to JSON. */
986
char *
987
json_to_string(struct json_node *node)
988
0
{
989
0
  struct evbuffer *buffer;
990
0
  char    *out;
991
992
0
  if (node == NULL)
993
0
    return (NULL);
994
0
  buffer = evbuffer_new();
995
0
  if (buffer == NULL)
996
0
    fatalx("out of memory");
997
0
  json_string_append(buffer, node);
998
0
  out = xmemdup(EVBUFFER_DATA(buffer), EVBUFFER_LENGTH(buffer));
999
0
  evbuffer_free(buffer);
1000
0
  return (out);
1001
0
}