Coverage Report

Created: 2026-10-16 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/json-c/json_tokener.c
Line
Count
Source
1
/*
2
 * $Id: json_tokener.c,v 1.20 2006/07/25 03:24:50 mclark Exp $
3
 *
4
 * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
5
 * Michael Clark <michael@metaparadigm.com>
6
 *
7
 * This library is free software; you can redistribute it and/or modify
8
 * it under the terms of the MIT license. See COPYING for details.
9
 *
10
 *
11
 * Copyright (c) 2008-2009 Yahoo! Inc.  All rights reserved.
12
 * The copyrights to the contents of this file are licensed under the MIT License
13
 * (https://www.opensource.org/licenses/mit-license.php)
14
 */
15
16
#include "config.h"
17
18
#include "math_compat.h"
19
#include <assert.h>
20
#include <errno.h>
21
#include <limits.h>
22
#include <math.h>
23
#include <stddef.h>
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <string.h>
27
28
#include "debug.h"
29
#include "json_inttypes.h"
30
#include "json_object.h"
31
#include "json_object_private.h"
32
#include "json_tokener.h"
33
#include "json_util.h"
34
#include "printbuf.h"
35
#include "strdup_compat.h"
36
37
#ifdef HAVE_LOCALE_H
38
#include <locale.h>
39
#endif /* HAVE_LOCALE_H */
40
#ifdef HAVE_XLOCALE_H
41
#include <xlocale.h>
42
#endif
43
#ifdef HAVE_STRINGS_H
44
#include <strings.h>
45
#endif /* HAVE_STRINGS_H */
46
47
11.3k
#define jt_hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x)&7) + 9)
48
49
#if !HAVE_STRNCASECMP && defined(_WIN32)
50
/* MSC has the version as _strnicmp */
51
#define strncasecmp _strnicmp
52
#elif !HAVE_STRNCASECMP
53
#error You do not have strncasecmp on your system.
54
#endif /* HAVE_STRNCASECMP */
55
56
#if defined(_MSC_VER) && (_MSC_VER <= 1800)
57
/* VS2013 doesn't know about "inline" */
58
#define inline __inline
59
#elif defined(AIX_CC)
60
#define inline
61
#endif
62
63
/* The following helper functions are used to speed up parsing. They
64
 * are faster than their ctype counterparts because they assume that
65
 * the input is in ASCII and that the locale is set to "C". The
66
 * compiler will also inline these functions, providing an additional
67
 * speedup by saving on function calls.
68
 */
69
static inline int is_ws_char(char c)
70
1.07M
{
71
1.07M
  return c == ' '
72
864k
      || c == '\t'
73
836k
      || c == '\n'
74
833k
      || c == '\r';
75
1.07M
}
76
77
static inline int is_hex_char(char c)
78
11.3k
{
79
11.3k
  return (c >= '0' && c <= '9')
80
3.73k
      || (c >= 'A' && c <= 'F')
81
225
      || (c >= 'a' && c <= 'f');
82
11.3k
}
83
84
/* Use C99 NAN by default; if not available, nan("") should work too. */
85
#ifndef NAN
86
#define NAN nan("")
87
#endif /* !NAN */
88
89
static const char json_null_str[] = "null";
90
static const int json_null_str_len = sizeof(json_null_str) - 1;
91
static const char json_inf_str[] = "Infinity";
92
/* Swapped case "Infinity" to avoid need to call tolower() on input chars: */
93
static const char json_inf_str_invert[] = "iNFINITY";
94
static const unsigned int json_inf_str_len = sizeof(json_inf_str) - 1;
95
static const char json_nan_str[] = "NaN";
96
static const int json_nan_str_len = sizeof(json_nan_str) - 1;
97
static const char json_true_str[] = "true";
98
static const int json_true_str_len = sizeof(json_true_str) - 1;
99
static const char json_false_str[] = "false";
100
static const int json_false_str_len = sizeof(json_false_str) - 1;
101
102
/* clang-format off */
103
static const char *json_tokener_errors[] = {
104
  "success",
105
  "continue",
106
  "nesting too deep",
107
  "unexpected end of data",
108
  "unexpected character",
109
  "null expected",
110
  "boolean expected",
111
  "number expected",
112
  "array value separator ',' expected",
113
  "quoted object property name expected",
114
  "object property name separator ':' expected",
115
  "object value separator ',' expected",
116
  "invalid string sequence",
117
  "expected comment",
118
  "invalid utf-8 string",
119
  "buffer size overflow",
120
  "out of memory"
121
};
122
/* clang-format on */
123
124
/**
125
 * validete the utf-8 string in strict model.
126
 * if not utf-8 format, return err.
127
 */
128
static json_bool json_tokener_validate_utf8(const char c, unsigned int *nBytes);
129
130
static int json_tokener_parse_double(const char *buf, int len, double *retval);
131
132
const char *json_tokener_error_desc(enum json_tokener_error jerr)
133
419
{
134
419
  int jerr_int = (int)jerr;
135
419
  if (jerr_int < 0 ||
136
419
      jerr_int >= (int)(sizeof(json_tokener_errors) / sizeof(json_tokener_errors[0])))
137
0
    return "Unknown error, "
138
0
           "invalid json_tokener_error value passed to json_tokener_error_desc()";
139
419
  return json_tokener_errors[jerr];
140
419
}
141
142
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok)
143
838
{
144
838
  return tok->err;
145
838
}
146
147
/* Stuff for decoding unicode sequences */
148
1.92k
#define IS_HIGH_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xD800)
149
1.67k
#define IS_LOW_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xDC00)
150
311
#define DECODE_SURROGATE_PAIR(hi, lo) ((((hi)&0x3FF) << 10) + ((lo)&0x3FF) + 0x10000)
151
static unsigned char utf8_replacement_char[3] = {0xEF, 0xBF, 0xBD};
152
153
struct json_tokener *json_tokener_new_ex(int depth)
154
7.00k
{
155
7.00k
  struct json_tokener *tok;
156
157
7.00k
  if (depth < 1)
158
0
    return NULL;
159
160
7.00k
  tok = (struct json_tokener *)calloc(1, sizeof(struct json_tokener));
161
7.00k
  if (!tok)
162
0
    return NULL;
163
7.00k
  tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
164
7.00k
  if (!tok->stack)
165
0
  {
166
0
    free(tok);
167
0
    return NULL;
168
0
  }
169
7.00k
  tok->pb = printbuf_new();
170
7.00k
  if (!tok->pb)
171
0
  {
172
0
    free(tok->stack);
173
0
    free(tok);
174
0
    return NULL;
175
0
  }
176
7.00k
  tok->max_depth = depth;
177
7.00k
  json_tokener_reset(tok);
178
7.00k
  return tok;
179
7.00k
}
180
181
struct json_tokener *json_tokener_new(void)
182
7.00k
{
183
7.00k
  return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
184
7.00k
}
185
186
void json_tokener_free(struct json_tokener *tok)
187
7.00k
{
188
7.00k
  if (!tok)
189
0
    return;
190
7.00k
  json_tokener_reset(tok);
191
7.00k
  if (tok->pb)
192
7.00k
    printbuf_free(tok->pb);
193
7.00k
  free(tok->stack);
194
7.00k
  free(tok);
195
7.00k
}
196
197
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
198
308k
{
199
308k
  tok->stack[depth].state = json_tokener_state_eatws;
200
308k
  tok->stack[depth].saved_state = json_tokener_state_start;
201
308k
  json_object_put(tok->stack[depth].current);
202
308k
  tok->stack[depth].current = NULL;
203
308k
  free(tok->stack[depth].obj_field_name);
204
308k
  tok->stack[depth].obj_field_name = NULL;
205
308k
}
206
207
void json_tokener_reset(struct json_tokener *tok)
208
14.0k
{
209
14.0k
  int i;
210
14.0k
  if (!tok)
211
0
    return;
212
213
29.0k
  for (i = tok->depth; i >= 0; i--)
214
15.0k
    json_tokener_reset_level(tok, i);
215
14.0k
  tok->depth = 0;
216
14.0k
  tok->err = json_tokener_success;
217
14.0k
}
218
219
struct json_object *json_tokener_parse(const char *str)
220
0
{
221
0
  enum json_tokener_error jerr_ignored;
222
0
  struct json_object *obj;
223
0
  obj = json_tokener_parse_verbose(str, &jerr_ignored);
224
0
  return obj;
225
0
}
226
227
struct json_object *json_tokener_parse_verbose(const char *str, enum json_tokener_error *error)
228
0
{
229
0
  struct json_tokener *tok;
230
0
  struct json_object *obj;
231
232
0
  tok = json_tokener_new();
233
0
  if (!tok)
234
0
  {
235
0
    *error = json_tokener_error_memory;
236
0
    return NULL;
237
0
  }
238
0
  obj = json_tokener_parse_ex(tok, str, -1);
239
0
  *error = tok->err;
240
0
  if (tok->err != json_tokener_success
241
#if 0
242
    /* This would be a more sensible default, and cause parsing
243
     * things like "null123" to fail when the caller can't know
244
     * where the parsing left off, but starting to fail would
245
     * be a notable behaviour change.  Save for a 1.0 release.
246
     */
247
      || json_tokener_get_parse_end(tok) != strlen(str)
248
#endif
249
0
  )
250
251
0
  {
252
0
    if (obj != NULL)
253
0
      json_object_put(obj);
254
0
    obj = NULL;
255
0
  }
256
257
0
  json_tokener_free(tok);
258
0
  return obj;
259
0
}
260
261
4.13M
#define state tok->stack[tok->depth].state
262
1.62M
#define saved_state tok->stack[tok->depth].saved_state
263
603k
#define current tok->stack[tok->depth].current
264
561k
#define obj_field_name tok->stack[tok->depth].obj_field_name
265
266
/* Optimization:
267
 * json_tokener_parse_ex() consumed a lot of CPU in its main loop,
268
 * iterating character-by character.  A large performance boost is
269
 * achieved by using tighter loops to locally handle units such as
270
 * comments and strings.  Loops that handle an entire token within
271
 * their scope also gather entire strings and pass them to
272
 * printbuf_memappend() in a single call, rather than calling
273
 * printbuf_memappend() one char at a time.
274
 *
275
 * PEEK_CHAR() and ADVANCE_CHAR() macros are used for code that is
276
 * common to both the main loop and the tighter loops.
277
 */
278
279
/* PEEK_CHAR(dest, tok) macro:
280
 *   Peeks at the current char and stores it in dest.
281
 *   Returns 1 on success, sets tok->err and returns 0 if no more chars.
282
 *   Implicit inputs:  str, len, nBytesp vars
283
 */
284
#define PEEK_CHAR(dest, tok)                                                 \
285
3.78M
  (((tok)->char_offset == len)                                         \
286
3.78M
       ? (((tok)->depth == 0 && state == json_tokener_state_eatws &&   \
287
0
           saved_state == json_tokener_state_finish)                   \
288
0
              ? (((tok)->err = json_tokener_success), 0)               \
289
0
              : (((tok)->err = json_tokener_continue), 0))             \
290
3.78M
       : (((tok->flags & JSON_TOKENER_VALIDATE_UTF8) &&                \
291
3.78M
           (!json_tokener_validate_utf8(*str, nBytesp)))               \
292
3.78M
              ? ((tok->err = json_tokener_error_parse_utf8_string), 0) \
293
3.78M
              : (((dest) = *str), 1)))
294
295
/* ADVANCE_CHAR() macro:
296
 *   Increments str & tok->char_offset.
297
 *   For convenience of existing conditionals, returns the old value of c (0 on eof).
298
 *   Implicit inputs:  c var
299
 */
300
6.46M
#define ADVANCE_CHAR(str, tok) (++(str), ((tok)->char_offset)++, c)
301
302
/* printbuf_memappend_checked(p, s, l) macro:
303
 *   Add string s of length l to printbuffer p.
304
 *   If operation fails abort parse operation with memory error.
305
 */
306
#define printbuf_memappend_checked(p, s, l)                   \
307
320k
  do {                                                  \
308
320k
    if (printbuf_memappend((p), (s), (l)) < 0)    \
309
320k
    {                                             \
310
0
      tok->err = json_tokener_error_memory; \
311
0
      goto out;                             \
312
0
    }                                             \
313
320k
  } while (0)
314
315
/* End optimization macro defs */
316
317
struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *str, int len)
318
7.00k
{
319
7.00k
  struct json_object *obj = NULL;
320
7.00k
  char c = '\1';
321
7.00k
  unsigned int nBytes = 0;
322
7.00k
  unsigned int *nBytesp = &nBytes;
323
324
7.00k
#ifdef HAVE_USELOCALE
325
7.00k
  locale_t oldlocale = uselocale(NULL);
326
7.00k
  locale_t newloc;
327
#elif defined(HAVE_SETLOCALE)
328
  char *oldlocale = NULL;
329
#endif
330
331
7.00k
  tok->char_offset = 0;
332
7.00k
  tok->err = json_tokener_success;
333
334
  /* this interface is presently not 64-bit clean due to the int len argument
335
   * and the internal printbuf interface that takes 32-bit int len arguments
336
   * so the function limits the maximum string size to INT32_MAX (2GB).
337
   * If the function is called with len == -1 then strlen is called to check
338
   * the string length is less than INT32_MAX (2GB)
339
   */
340
7.00k
  if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX))
341
0
  {
342
0
    tok->err = json_tokener_error_size;
343
0
    return NULL;
344
0
  }
345
346
7.00k
#ifdef HAVE_USELOCALE
347
7.00k
  {
348
7.00k
#ifdef HAVE_DUPLOCALE
349
7.00k
    locale_t duploc = duplocale(oldlocale);
350
7.00k
    if (duploc == NULL && errno == ENOMEM)
351
0
    {
352
0
      tok->err = json_tokener_error_memory;
353
0
      return NULL;
354
0
    }
355
7.00k
    newloc = newlocale(LC_NUMERIC_MASK, "C", duploc);
356
#else
357
    newloc = newlocale(LC_NUMERIC_MASK, "C", oldlocale);
358
#endif
359
7.00k
    if (newloc == NULL)
360
0
    {
361
0
      tok->err = json_tokener_error_memory;
362
0
#ifdef HAVE_DUPLOCALE
363
0
      freelocale(duploc);
364
0
#endif
365
0
      return NULL;
366
0
    }
367
#ifdef NEWLOCALE_NEEDS_FREELOCALE
368
#ifdef HAVE_DUPLOCALE
369
    // Older versions of FreeBSD (<12.4) don't free the locale
370
    // passed to newlocale(), so do it here
371
    freelocale(duploc);
372
#endif
373
#endif
374
7.00k
    uselocale(newloc);
375
7.00k
  }
376
#elif defined(HAVE_SETLOCALE)
377
  {
378
    char *tmplocale;
379
    tmplocale = setlocale(LC_NUMERIC, NULL);
380
    if (tmplocale)
381
    {
382
      oldlocale = strdup(tmplocale);
383
      if (oldlocale == NULL)
384
      {
385
        tok->err = json_tokener_error_memory;
386
        return NULL;
387
      }
388
    }
389
    setlocale(LC_NUMERIC, "C");
390
  }
391
#endif
392
393
844k
  while (PEEK_CHAR(c, tok)) // Note: c might be '\0' !
394
844k
  {
395
396
2.13M
  redo_char:
397
2.13M
    switch (state)
398
2.13M
    {
399
400
833k
    case json_tokener_state_eatws:
401
      /* Advance until we change state */
402
1.07M
      while (is_ws_char(c))
403
243k
      {
404
243k
        if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
405
0
          goto out;
406
243k
      }
407
833k
      if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT))
408
1.05k
      {
409
1.05k
        printbuf_reset(tok->pb);
410
1.05k
        printbuf_memappend_checked(tok->pb, &c, 1);
411
1.05k
        state = json_tokener_state_comment_start;
412
1.05k
      }
413
832k
      else
414
832k
      {
415
832k
        state = saved_state;
416
832k
        goto redo_char;
417
832k
      }
418
1.05k
      break;
419
420
150k
    case json_tokener_state_start:
421
150k
      switch (c)
422
150k
      {
423
50.7k
      case '{':
424
50.7k
        state = json_tokener_state_eatws;
425
50.7k
        saved_state = json_tokener_state_object_field_start;
426
50.7k
        current = json_object_new_object();
427
50.7k
        if (current == NULL)
428
0
        {
429
0
          tok->err = json_tokener_error_memory;
430
0
          goto out;
431
0
        }
432
50.7k
        break;
433
50.7k
      case '[':
434
10.8k
        state = json_tokener_state_eatws;
435
10.8k
        saved_state = json_tokener_state_array;
436
10.8k
        current = json_object_new_array();
437
10.8k
        if (current == NULL)
438
0
        {
439
0
          tok->err = json_tokener_error_memory;
440
0
          goto out;
441
0
        }
442
10.8k
        break;
443
10.8k
      case 'I':
444
17
      case 'i':
445
17
        state = json_tokener_state_inf;
446
17
        printbuf_reset(tok->pb);
447
17
        tok->st_pos = 0;
448
17
        goto redo_char;
449
138
      case 'N':
450
383
      case 'n':
451
383
        state = json_tokener_state_null; // or NaN
452
383
        printbuf_reset(tok->pb);
453
383
        tok->st_pos = 0;
454
383
        goto redo_char;
455
100
      case '\'':
456
100
        if (tok->flags & JSON_TOKENER_STRICT)
457
0
        {
458
          /* in STRICT mode only double-quote are allowed */
459
0
          tok->err = json_tokener_error_parse_unexpected;
460
0
          goto out;
461
0
        }
462
        /* FALLTHRU */
463
76.2k
      case '"':
464
76.2k
        state = json_tokener_state_string;
465
76.2k
        printbuf_reset(tok->pb);
466
76.2k
        tok->quote_char = c;
467
76.2k
        break;
468
30
      case 'T':
469
76
      case 't':
470
199
      case 'F':
471
331
      case 'f':
472
331
        state = json_tokener_state_boolean;
473
331
        printbuf_reset(tok->pb);
474
331
        tok->st_pos = 0;
475
331
        goto redo_char;
476
2.94k
      case '0':
477
5.70k
      case '1':
478
6.55k
      case '2':
479
6.92k
      case '3':
480
8.54k
      case '4':
481
9.23k
      case '5':
482
9.37k
      case '6':
483
9.52k
      case '7':
484
9.59k
      case '8':
485
10.0k
      case '9':
486
12.1k
      case '-':
487
12.1k
        state = json_tokener_state_number;
488
12.1k
        printbuf_reset(tok->pb);
489
12.1k
        tok->is_double = 0;
490
12.1k
        goto redo_char;
491
92
      default: tok->err = json_tokener_error_parse_unexpected; goto out;
492
150k
      }
493
137k
      break;
494
495
149k
    case json_tokener_state_finish:
496
149k
      if (tok->depth == 0)
497
6.55k
        goto out;
498
142k
      obj = json_object_get(current);
499
142k
      json_tokener_reset_level(tok, tok->depth);
500
142k
      tok->depth--;
501
142k
      goto redo_char;
502
503
18
    case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */
504
18
    {
505
      /* If we were guaranteed to have len set, then we could (usually) handle
506
       * the entire "Infinity" check in a single strncmp (strncasecmp), but
507
       * since len might be -1 (i.e. "read until \0"), we need to check it
508
       * a character at a time.
509
       * Trying to handle it both ways would make this code considerably more
510
       * complicated with likely little performance benefit.
511
       */
512
18
      int is_negative = 0;
513
514
      /* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */
515
45
      while (tok->st_pos < (int)json_inf_str_len)
516
45
      {
517
45
        char inf_char = *str;
518
45
        if (inf_char != json_inf_str[tok->st_pos] &&
519
35
            ((tok->flags & JSON_TOKENER_STRICT) ||
520
35
              inf_char != json_inf_str_invert[tok->st_pos])
521
45
           )
522
18
        {
523
18
          tok->err = json_tokener_error_parse_unexpected;
524
18
          goto out;
525
18
        }
526
27
        tok->st_pos++;
527
27
        (void)ADVANCE_CHAR(str, tok);
528
27
        if (!PEEK_CHAR(c, tok))
529
0
        {
530
          /* out of input chars, for now at least */
531
0
          goto out;
532
0
        }
533
27
      }
534
      /* We checked the full length of "Infinity", so create the object.
535
       * When handling -Infinity, the number parsing code will have dropped
536
       * the "-" into tok->pb for us, so check it now.
537
       */
538
0
      if (printbuf_length(tok->pb) > 0 && *(tok->pb->buf) == '-')
539
0
      {
540
0
        is_negative = 1;
541
0
      }
542
0
      current = json_object_new_double(is_negative ? -INFINITY : INFINITY);
543
0
      if (current == NULL)
544
0
      {
545
0
        tok->err = json_tokener_error_memory;
546
0
        goto out;
547
0
      }
548
0
      saved_state = json_tokener_state_finish;
549
0
      state = json_tokener_state_eatws;
550
0
      goto redo_char;
551
0
    }
552
0
    break;
553
1.72k
    case json_tokener_state_null: /* aka starts with 'n' */
554
1.72k
    {
555
1.72k
      int size;
556
1.72k
      int size_nan;
557
1.72k
      printbuf_memappend_checked(tok->pb, &c, 1);
558
1.72k
      size = json_min(tok->st_pos + 1, json_null_str_len);
559
1.72k
      size_nan = json_min(tok->st_pos + 1, json_nan_str_len);
560
1.72k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
561
1.72k
           strncasecmp(json_null_str, tok->pb->buf, size) == 0) ||
562
416
          (strncmp(json_null_str, tok->pb->buf, size) == 0))
563
1.30k
      {
564
1.30k
        if (tok->st_pos == json_null_str_len)
565
230
        {
566
230
          current = NULL;
567
230
          saved_state = json_tokener_state_finish;
568
230
          state = json_tokener_state_eatws;
569
230
          goto redo_char;
570
230
        }
571
1.30k
      }
572
416
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
573
416
                strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
574
23
               (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0))
575
393
      {
576
393
        if (tok->st_pos == json_nan_str_len)
577
130
        {
578
130
          current = json_object_new_double(NAN);
579
130
          if (current == NULL)
580
0
          {
581
0
            tok->err = json_tokener_error_memory;
582
0
            goto out;
583
0
          }
584
130
          saved_state = json_tokener_state_finish;
585
130
          state = json_tokener_state_eatws;
586
130
          goto redo_char;
587
130
        }
588
393
      }
589
23
      else
590
23
      {
591
23
        tok->err = json_tokener_error_parse_null;
592
23
        goto out;
593
23
      }
594
1.34k
      tok->st_pos++;
595
1.34k
    }
596
0
    break;
597
598
1.05k
    case json_tokener_state_comment_start:
599
1.05k
      if (c == '*')
600
261
      {
601
261
        state = json_tokener_state_comment;
602
261
      }
603
791
      else if (c == '/')
604
777
      {
605
777
        state = json_tokener_state_comment_eol;
606
777
      }
607
14
      else
608
14
      {
609
14
        tok->err = json_tokener_error_parse_comment;
610
14
        goto out;
611
14
      }
612
1.03k
      printbuf_memappend_checked(tok->pb, &c, 1);
613
1.03k
      break;
614
615
1.32k
    case json_tokener_state_comment:
616
1.32k
    {
617
      /* Advance until we change state */
618
1.32k
      const char *case_start = str;
619
21.7k
      while (c != '*')
620
20.4k
      {
621
20.4k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
622
24
        {
623
24
          printbuf_memappend_checked(tok->pb, case_start,
624
24
                                     str - case_start);
625
24
          goto out;
626
24
        }
627
20.4k
      }
628
1.30k
      printbuf_memappend_checked(tok->pb, case_start, 1 + str - case_start);
629
1.30k
      state = json_tokener_state_comment_end;
630
1.30k
    }
631
0
    break;
632
633
777
    case json_tokener_state_comment_eol:
634
777
    {
635
      /* Advance until we change state */
636
777
      const char *case_start = str;
637
56.6k
      while (c != '\n')
638
55.9k
      {
639
55.9k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
640
45
        {
641
45
          printbuf_memappend_checked(tok->pb, case_start,
642
45
                                     str - case_start);
643
45
          goto out;
644
45
        }
645
55.9k
      }
646
732
      printbuf_memappend_checked(tok->pb, case_start, str - case_start);
647
732
      MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
648
732
      state = json_tokener_state_eatws;
649
732
    }
650
0
    break;
651
652
1.30k
    case json_tokener_state_comment_end:
653
1.30k
      printbuf_memappend_checked(tok->pb, &c, 1);
654
1.30k
      if (c == '/')
655
232
      {
656
232
        MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
657
232
        state = json_tokener_state_eatws;
658
232
      }
659
1.07k
      else
660
1.07k
      {
661
1.07k
        state = json_tokener_state_comment;
662
1.07k
      }
663
1.30k
      break;
664
665
124k
    case json_tokener_state_string:
666
124k
    {
667
      /* Advance until we change state */
668
124k
      const char *case_start = str;
669
1.80M
      while (1)
670
1.80M
      {
671
1.80M
        if (c == tok->quote_char)
672
76.1k
        {
673
76.1k
          printbuf_memappend_checked(tok->pb, case_start,
674
76.1k
                                     str - case_start);
675
76.1k
          current =
676
76.1k
              json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
677
76.1k
          if (current == NULL)
678
0
          {
679
0
            tok->err = json_tokener_error_memory;
680
0
            goto out;
681
0
          }
682
76.1k
          saved_state = json_tokener_state_finish;
683
76.1k
          state = json_tokener_state_eatws;
684
76.1k
          break;
685
76.1k
        }
686
1.72M
        else if (c == '\\')
687
47.9k
        {
688
47.9k
          printbuf_memappend_checked(tok->pb, case_start,
689
47.9k
                                     str - case_start);
690
47.9k
          saved_state = json_tokener_state_string;
691
47.9k
          state = json_tokener_state_string_escape;
692
47.9k
          break;
693
47.9k
        }
694
1.67M
        else if ((tok->flags & JSON_TOKENER_STRICT) && (unsigned char)c <= 0x1f)
695
0
        {
696
          // Disallow control characters in strict mode
697
0
          tok->err = json_tokener_error_parse_string;
698
0
          goto out;
699
0
        }
700
1.67M
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
701
43
        {
702
43
          printbuf_memappend_checked(tok->pb, case_start,
703
43
                                     str - case_start);
704
43
          goto out;
705
43
        }
706
1.67M
      }
707
124k
    }
708
124k
    break;
709
710
124k
    case json_tokener_state_string_escape:
711
55.3k
      switch (c)
712
55.3k
      {
713
10.6k
      case '"':
714
32.7k
      case '\\':
715
32.8k
      case '/':
716
32.8k
        printbuf_memappend_checked(tok->pb, &c, 1);
717
32.8k
        state = saved_state;
718
32.8k
        break;
719
765
      case 'b':
720
18.9k
      case 'n':
721
19.2k
      case 'r':
722
19.8k
      case 't':
723
20.0k
      case 'f':
724
20.0k
        if (c == 'b')
725
765
          printbuf_memappend_checked(tok->pb, "\b", 1);
726
19.3k
        else if (c == 'n')
727
18.2k
          printbuf_memappend_checked(tok->pb, "\n", 1);
728
1.09k
        else if (c == 'r')
729
284
          printbuf_memappend_checked(tok->pb, "\r", 1);
730
811
        else if (c == 't')
731
574
          printbuf_memappend_checked(tok->pb, "\t", 1);
732
237
        else if (c == 'f')
733
237
          printbuf_memappend_checked(tok->pb, "\f", 1);
734
20.0k
        state = saved_state;
735
20.0k
        break;
736
2.40k
      case 'u':
737
2.40k
        tok->ucs_char = 0;
738
2.40k
        tok->st_pos = 0;
739
2.40k
        state = json_tokener_state_escape_unicode;
740
2.40k
        break;
741
13
      default: tok->err = json_tokener_error_parse_string; goto out;
742
55.3k
      }
743
55.3k
      break;
744
745
      // ===================================================
746
747
55.3k
    case json_tokener_state_escape_unicode:
748
2.85k
    {
749
      /* Handle a 4-byte \uNNNN sequence, or two sequences if a surrogate pair */
750
11.3k
      while (1)
751
11.3k
      {
752
11.3k
        if (!c || !is_hex_char(c))
753
13
        {
754
13
          tok->err = json_tokener_error_parse_string;
755
13
          goto out;
756
13
        }
757
11.3k
        tok->ucs_char |=
758
11.3k
            ((unsigned int)jt_hexdigit(c) << ((3 - tok->st_pos) * 4));
759
11.3k
        tok->st_pos++;
760
11.3k
        if (tok->st_pos >= 4)
761
2.84k
          break;
762
763
8.54k
        (void)ADVANCE_CHAR(str, tok);
764
8.54k
        if (!PEEK_CHAR(c, tok))
765
0
        {
766
          /*
767
           * We're out of characters in the current call to
768
           * json_tokener_parse(), but a subsequent call might
769
           * provide us with more, so leave our current state
770
           * as-is (including tok->high_surrogate) and return.
771
           */
772
0
          goto out;
773
0
        }
774
8.54k
      }
775
2.84k
      tok->st_pos = 0;
776
777
      /* Now, we have a full \uNNNN sequence in tok->ucs_char */
778
779
      /* If the *previous* sequence was a high surrogate ... */
780
2.84k
      if (tok->high_surrogate)
781
446
      {
782
446
        if (IS_LOW_SURROGATE(tok->ucs_char))
783
311
        {
784
          /* Recalculate the ucs_char, then fall thru to process normally */
785
311
          tok->ucs_char = DECODE_SURROGATE_PAIR(tok->high_surrogate,
786
311
                                                tok->ucs_char);
787
311
        }
788
135
        else
789
135
        {
790
          /* High surrogate was not followed by a low surrogate
791
           * Replace the high and process the rest normally
792
           */
793
135
          printbuf_memappend_checked(tok->pb,
794
135
                                     (char *)utf8_replacement_char, 3);
795
135
        }
796
446
        tok->high_surrogate = 0;
797
446
      }
798
799
2.84k
      if (tok->ucs_char < 0x80)
800
874
      {
801
874
        unsigned char unescaped_utf[1];
802
874
        unescaped_utf[0] = tok->ucs_char;
803
874
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 1);
804
874
      }
805
1.96k
      else if (tok->ucs_char < 0x800)
806
42
      {
807
42
        unsigned char unescaped_utf[2];
808
42
        unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
809
42
        unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
810
42
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 2);
811
42
      }
812
1.92k
      else if (IS_HIGH_SURROGATE(tok->ucs_char))
813
695
      {
814
        /*
815
         * The next two characters should be \u, HOWEVER,
816
         * we can't simply peek ahead here, because the
817
         * characters we need might not be passed to us
818
         * until a subsequent call to json_tokener_parse.
819
         * Instead, transition through a couple of states.
820
         * (now):
821
         *   _escape_unicode => _unicode_need_escape
822
         * (see a '\\' char):
823
         *   _unicode_need_escape => _unicode_need_u
824
         * (see a 'u' char):
825
         *   _unicode_need_u => _escape_unicode
826
         *      ...and we'll end up back around here.
827
         */
828
695
        tok->high_surrogate = tok->ucs_char;
829
695
        tok->ucs_char = 0;
830
695
        state = json_tokener_state_escape_unicode_need_escape;
831
695
        break;
832
695
      }
833
1.22k
      else if (IS_LOW_SURROGATE(tok->ucs_char))
834
420
      {
835
        /* Got a low surrogate not preceded by a high */
836
420
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
837
420
      }
838
809
      else if (tok->ucs_char < 0x10000)
839
498
      {
840
498
        unsigned char unescaped_utf[3];
841
498
        unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
842
498
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
843
498
        unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
844
498
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 3);
845
498
      }
846
311
      else if (tok->ucs_char < 0x110000)
847
311
      {
848
311
        unsigned char unescaped_utf[4];
849
311
        unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
850
311
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
851
311
        unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
852
311
        unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
853
311
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 4);
854
311
      }
855
0
      else
856
0
      {
857
        /* Don't know what we got--insert the replacement char */
858
0
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
859
0
      }
860
2.14k
      state = saved_state; // i.e. _state_string or _state_object_field
861
2.14k
    }
862
0
    break;
863
864
695
    case json_tokener_state_escape_unicode_need_escape:
865
      // We get here after processing a high_surrogate
866
      // require a '\\' char
867
695
      if (!c || c != '\\')
868
149
      {
869
        /* Got a high surrogate without another sequence following
870
         * it.  Put a replacement char in for the high surrogate
871
         * and pop back up to _state_string or _state_object_field.
872
         */
873
149
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
874
149
        tok->high_surrogate = 0;
875
149
        tok->ucs_char = 0;
876
149
        tok->st_pos = 0;
877
149
        state = saved_state;
878
149
        goto redo_char;
879
149
      }
880
546
      state = json_tokener_state_escape_unicode_need_u;
881
546
      break;
882
883
546
    case json_tokener_state_escape_unicode_need_u:
884
      /* We already had a \ char, check that it's \u */
885
546
      if (!c || c != 'u')
886
98
      {
887
        /* Got a high surrogate with some non-unicode escape
888
         * sequence following it.
889
         * Put a replacement char in for the high surrogate
890
         * and handle the escape sequence normally.
891
         */
892
98
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
893
98
        tok->high_surrogate = 0;
894
98
        tok->ucs_char = 0;
895
98
        tok->st_pos = 0;
896
98
        state = json_tokener_state_string_escape;
897
98
        goto redo_char;
898
98
      }
899
448
      state = json_tokener_state_escape_unicode;
900
448
      break;
901
902
      // ===================================================
903
904
1.83k
    case json_tokener_state_boolean:
905
1.83k
    {
906
1.83k
      int size1, size2;
907
1.83k
      printbuf_memappend_checked(tok->pb, &c, 1);
908
1.83k
      size1 = json_min(tok->st_pos + 1, json_true_str_len);
909
1.83k
      size2 = json_min(tok->st_pos + 1, json_false_str_len);
910
1.83k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
911
1.83k
           strncasecmp(json_true_str, tok->pb->buf, size1) == 0) ||
912
1.51k
          (strncmp(json_true_str, tok->pb->buf, size1) == 0))
913
324
      {
914
324
        if (tok->st_pos == json_true_str_len)
915
61
        {
916
61
          current = json_object_new_boolean(1);
917
61
          if (current == NULL)
918
0
          {
919
0
            tok->err = json_tokener_error_memory;
920
0
            goto out;
921
0
          }
922
61
          saved_state = json_tokener_state_finish;
923
61
          state = json_tokener_state_eatws;
924
61
          goto redo_char;
925
61
        }
926
324
      }
927
1.51k
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
928
1.51k
                strncasecmp(json_false_str, tok->pb->buf, size2) == 0) ||
929
26
               (strncmp(json_false_str, tok->pb->buf, size2) == 0))
930
1.48k
      {
931
1.48k
        if (tok->st_pos == json_false_str_len)
932
244
        {
933
244
          current = json_object_new_boolean(0);
934
244
          if (current == NULL)
935
0
          {
936
0
            tok->err = json_tokener_error_memory;
937
0
            goto out;
938
0
          }
939
244
          saved_state = json_tokener_state_finish;
940
244
          state = json_tokener_state_eatws;
941
244
          goto redo_char;
942
244
        }
943
1.48k
      }
944
26
      else
945
26
      {
946
26
        tok->err = json_tokener_error_parse_boolean;
947
26
        goto out;
948
26
      }
949
1.50k
      tok->st_pos++;
950
1.50k
    }
951
0
    break;
952
953
12.1k
    case json_tokener_state_number:
954
12.1k
    {
955
      /* Advance until we change state */
956
12.1k
      const char *case_start = str;
957
12.1k
      int case_len = 0;
958
12.1k
      int is_exponent = 0;
959
12.1k
      int neg_sign_ok = 1;
960
12.1k
      int pos_sign_ok = 0;
961
12.1k
      if (printbuf_length(tok->pb) > 0)
962
0
      {
963
        /* We don't save all state from the previous incremental parse
964
           so we need to re-generate it based on the saved string so far.
965
         */
966
0
        char *e_loc = strchr(tok->pb->buf, 'e');
967
0
        if (!e_loc)
968
0
          e_loc = strchr(tok->pb->buf, 'E');
969
0
        if (e_loc)
970
0
        {
971
0
          char *last_saved_char =
972
0
              &tok->pb->buf[printbuf_length(tok->pb) - 1];
973
0
          is_exponent = 1;
974
0
          pos_sign_ok = neg_sign_ok = 1;
975
          /* If the "e" isn't at the end, we can't start with a '-' */
976
0
          if (e_loc != last_saved_char)
977
0
          {
978
0
            neg_sign_ok = 0;
979
0
            pos_sign_ok = 0;
980
0
          }
981
          // else leave it set to 1, i.e. start of the new input
982
0
        }
983
0
      }
984
985
86.9k
      while (c && ((c >= '0' && c <= '9') ||
986
15.6k
                   (!is_exponent && (c == 'e' || c == 'E')) ||
987
15.1k
                   (neg_sign_ok && c == '-') || (pos_sign_ok && c == '+') ||
988
12.6k
                   (!tok->is_double && c == '.')))
989
74.8k
      {
990
74.8k
        pos_sign_ok = neg_sign_ok = 0;
991
74.8k
        ++case_len;
992
993
        /* non-digit characters checks */
994
        /* note: since the main loop condition to get here was
995
         * an input starting with 0-9 or '-', we are
996
         * protected from input starting with '.' or
997
         * e/E.
998
         */
999
74.8k
        switch (c)
1000
74.8k
        {
1001
511
        case '.':
1002
511
          tok->is_double = 1;
1003
511
          pos_sign_ok = 1;
1004
511
          neg_sign_ok = 1;
1005
511
          break;
1006
465
        case 'e': /* FALLTHRU */
1007
499
        case 'E':
1008
499
          is_exponent = 1;
1009
499
          tok->is_double = 1;
1010
          /* the exponent part can begin with a negative sign */
1011
499
          pos_sign_ok = neg_sign_ok = 1;
1012
499
          break;
1013
73.8k
        default: break;
1014
74.8k
        }
1015
1016
74.8k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
1017
0
        {
1018
0
          printbuf_memappend_checked(tok->pb, case_start, case_len);
1019
0
          goto out;
1020
0
        }
1021
74.8k
      }
1022
      /*
1023
        Now we know c isn't a valid number char, but check whether
1024
        it might have been intended to be, and return a potentially
1025
        more understandable error right away.
1026
        However, if we're at the top-level, use the number as-is
1027
        because c can be part of a new object to parse on the
1028
        next call to json_tokener_parse().
1029
       */
1030
12.1k
      if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' &&
1031
981
          c != 'I' && c != 'i' && !is_ws_char(c))
1032
34
      {
1033
34
        tok->err = json_tokener_error_parse_number;
1034
34
        goto out;
1035
34
      }
1036
12.1k
      if (case_len > 0)
1037
12.1k
        printbuf_memappend_checked(tok->pb, case_start, case_len);
1038
1039
      // Check for -Infinity
1040
12.1k
      if (tok->pb->buf[0] == '-' && case_len <= 1 && (c == 'i' || c == 'I'))
1041
1
      {
1042
1
        state = json_tokener_state_inf;
1043
1
        tok->st_pos = 0;
1044
1
        goto redo_char;
1045
1
      }
1046
12.1k
      if (tok->flags & JSON_TOKENER_STRICT)
1047
0
      {
1048
        /* Check the accumulated text against the RFC 8259 grammar:
1049
         *
1050
         *   number = [ minus ] int [ frac ] [ exp ]
1051
         *   int    = zero / ( digit1-9 *DIGIT )
1052
         *   frac   = decimal-point 1*DIGIT
1053
         *   exp    = e [ minus / plus ] 1*DIGIT
1054
         *
1055
         * so the integer part is mandatory and may not carry a
1056
         * leading zero, and both the fraction and the exponent
1057
         * need at least one digit of their own. That rejects
1058
         * "01", ".5", "-.123", "1.", "2.e3" and "1e", while
1059
         * "0", "-0", "0.5" and "2e3" stay valid.
1060
         */
1061
0
        const char *num = tok->pb->buf;
1062
0
        if (*num == '-')
1063
0
          num++;
1064
0
        if (*num == '0')
1065
0
        {
1066
0
          num++;
1067
0
          if (*num >= '0' && *num <= '9')
1068
0
          {
1069
0
            tok->err = json_tokener_error_parse_number;
1070
0
            goto out;
1071
0
          }
1072
0
        }
1073
0
        else if (*num >= '1' && *num <= '9')
1074
0
        {
1075
0
          while (*num >= '0' && *num <= '9')
1076
0
            num++;
1077
0
        }
1078
0
        else
1079
0
        {
1080
          /* no integer part at all, e.g. ".5" or "-.123" */
1081
0
          tok->err = json_tokener_error_parse_number;
1082
0
          goto out;
1083
0
        }
1084
0
        if (*num == '.')
1085
0
        {
1086
0
          num++;
1087
0
          if (!(*num >= '0' && *num <= '9'))
1088
0
          {
1089
0
            tok->err = json_tokener_error_parse_number;
1090
0
            goto out;
1091
0
          }
1092
0
          while (*num >= '0' && *num <= '9')
1093
0
            num++;
1094
0
        }
1095
0
        if (*num == 'e' || *num == 'E')
1096
0
        {
1097
0
          num++;
1098
0
          if (*num == '+' || *num == '-')
1099
0
            num++;
1100
0
          if (!(*num >= '0' && *num <= '9'))
1101
0
          {
1102
0
            tok->err = json_tokener_error_parse_number;
1103
0
            goto out;
1104
0
          }
1105
0
          while (*num >= '0' && *num <= '9')
1106
0
            num++;
1107
0
        }
1108
0
        if (*num != '\0')
1109
0
        {
1110
0
          tok->err = json_tokener_error_parse_number;
1111
0
          goto out;
1112
0
        }
1113
0
      }
1114
12.1k
      if (tok->is_double && !(tok->flags & JSON_TOKENER_STRICT))
1115
588
      {
1116
        /* Trim some chars off the end, to allow things
1117
           like "123e+" to parse ok. */
1118
1.20k
        while (printbuf_length(tok->pb) > 1)
1119
1.18k
        {
1120
1.18k
          char last_char = tok->pb->buf[printbuf_length(tok->pb) - 1];
1121
1.18k
          if (last_char != 'e' && last_char != 'E' &&
1122
850
              last_char != '-' && last_char != '+')
1123
565
          {
1124
565
            break;
1125
565
          }
1126
619
          tok->pb->buf[printbuf_length(tok->pb) - 1] = '\0';
1127
619
          printbuf_length(tok->pb)--;
1128
619
        }
1129
588
      }
1130
12.1k
    }
1131
0
      {
1132
12.1k
        int64_t num64;
1133
12.1k
        uint64_t numuint64;
1134
12.1k
        double numd;
1135
12.1k
        if (!tok->is_double && tok->pb->buf[0] == '-' &&
1136
1.63k
            json_parse_int64(tok->pb->buf, &num64) == 0)
1137
1.63k
        {
1138
1.63k
          if (errno == ERANGE && (tok->flags & JSON_TOKENER_STRICT))
1139
0
          {
1140
0
            tok->err = json_tokener_error_parse_number;
1141
0
            goto out;
1142
0
          }
1143
1.63k
          current = json_object_new_int64(num64);
1144
1.63k
          if (current == NULL)
1145
0
          {
1146
0
            tok->err = json_tokener_error_memory;
1147
0
            goto out;
1148
0
          }
1149
1.63k
        }
1150
10.4k
        else if (!tok->is_double && tok->pb->buf[0] != '-' &&
1151
9.88k
                 json_parse_uint64(tok->pb->buf, &numuint64) == 0)
1152
9.88k
        {
1153
9.88k
          if (errno == ERANGE && (tok->flags & JSON_TOKENER_STRICT))
1154
0
          {
1155
0
            tok->err = json_tokener_error_parse_number;
1156
0
            goto out;
1157
0
          }
1158
9.88k
          if (numuint64 <= INT64_MAX)
1159
9.38k
          {
1160
9.38k
            num64 = (int64_t)numuint64;
1161
9.38k
            current = json_object_new_int64(num64);
1162
9.38k
            if (current == NULL)
1163
0
            {
1164
0
              tok->err = json_tokener_error_memory;
1165
0
              goto out;
1166
0
            }
1167
9.38k
          }
1168
494
          else
1169
494
          {
1170
494
            current = json_object_new_uint64(numuint64);
1171
494
            if (current == NULL)
1172
0
            {
1173
0
              tok->err = json_tokener_error_memory;
1174
0
              goto out;
1175
0
            }
1176
494
          }
1177
9.88k
        }
1178
593
        else if (tok->is_double &&
1179
588
                 json_tokener_parse_double(
1180
588
                     tok->pb->buf, printbuf_length(tok->pb), &numd) == 0)
1181
586
        {
1182
586
          current = json_object_new_double_s(numd, tok->pb->buf);
1183
586
          if (current == NULL)
1184
0
          {
1185
0
            tok->err = json_tokener_error_memory;
1186
0
            goto out;
1187
0
          }
1188
586
        }
1189
7
        else
1190
7
        {
1191
7
          tok->err = json_tokener_error_parse_number;
1192
7
          goto out;
1193
7
        }
1194
12.0k
        saved_state = json_tokener_state_finish;
1195
12.0k
        state = json_tokener_state_eatws;
1196
12.0k
        goto redo_char;
1197
12.1k
      }
1198
0
      break;
1199
1200
20.9k
    case json_tokener_state_array_after_sep:
1201
31.7k
    case json_tokener_state_array:
1202
31.7k
      if (c == ']')
1203
428
      {
1204
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1205
428
        json_object_array_shrink(current, 0);
1206
1207
428
        if (state == json_tokener_state_array_after_sep &&
1208
25
            (tok->flags & JSON_TOKENER_STRICT))
1209
0
        {
1210
0
          tok->err = json_tokener_error_parse_unexpected;
1211
0
          goto out;
1212
0
        }
1213
428
        saved_state = json_tokener_state_finish;
1214
428
        state = json_tokener_state_eatws;
1215
428
      }
1216
31.3k
      else
1217
31.3k
      {
1218
31.3k
        if (tok->depth >= tok->max_depth - 1)
1219
1
        {
1220
1
          tok->err = json_tokener_error_depth;
1221
1
          goto out;
1222
1
        }
1223
31.3k
        state = json_tokener_state_array_add;
1224
31.3k
        tok->depth++;
1225
31.3k
        json_tokener_reset_level(tok, tok->depth);
1226
31.3k
        goto redo_char;
1227
31.3k
      }
1228
428
      break;
1229
1230
30.8k
    case json_tokener_state_array_add:
1231
30.8k
      if (json_object_array_add(current, obj) != 0)
1232
0
      {
1233
0
        tok->err = json_tokener_error_memory;
1234
0
        goto out;
1235
0
      }
1236
30.8k
      saved_state = json_tokener_state_array_sep;
1237
30.8k
      state = json_tokener_state_eatws;
1238
30.8k
      goto redo_char;
1239
1240
30.8k
    case json_tokener_state_array_sep:
1241
30.8k
      if (c == ']')
1242
9.90k
      {
1243
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1244
9.90k
        json_object_array_shrink(current, 0);
1245
1246
9.90k
        saved_state = json_tokener_state_finish;
1247
9.90k
        state = json_tokener_state_eatws;
1248
9.90k
      }
1249
20.9k
      else if (c == ',')
1250
20.9k
      {
1251
20.9k
        saved_state = json_tokener_state_array_after_sep;
1252
20.9k
        state = json_tokener_state_eatws;
1253
20.9k
      }
1254
24
      else
1255
24
      {
1256
24
        tok->err = json_tokener_error_parse_array;
1257
24
        goto out;
1258
24
      }
1259
30.8k
      break;
1260
1261
50.7k
    case json_tokener_state_object_field_start:
1262
132k
    case json_tokener_state_object_field_start_after_sep:
1263
132k
      if (c == '}')
1264
19.6k
      {
1265
19.6k
        if (state == json_tokener_state_object_field_start_after_sep &&
1266
4
            (tok->flags & JSON_TOKENER_STRICT))
1267
0
        {
1268
0
          tok->err = json_tokener_error_parse_unexpected;
1269
0
          goto out;
1270
0
        }
1271
19.6k
        saved_state = json_tokener_state_finish;
1272
19.6k
        state = json_tokener_state_eatws;
1273
19.6k
      }
1274
112k
      else if (c == '"' || c == '\'')
1275
112k
      {
1276
112k
        tok->quote_char = c;
1277
112k
        printbuf_reset(tok->pb);
1278
112k
        state = json_tokener_state_object_field;
1279
112k
      }
1280
18
      else
1281
18
      {
1282
18
        tok->err = json_tokener_error_parse_object_key_name;
1283
18
        goto out;
1284
18
      }
1285
132k
      break;
1286
1287
132k
    case json_tokener_state_object_field:
1288
119k
    {
1289
      /* Advance until we change state */
1290
119k
      const char *case_start = str;
1291
980k
      while (1)
1292
980k
      {
1293
980k
        if (c == tok->quote_char)
1294
112k
        {
1295
112k
          printbuf_memappend_checked(tok->pb, case_start,
1296
112k
                                     str - case_start);
1297
112k
          obj_field_name = strdup(tok->pb->buf);
1298
112k
          if (obj_field_name == NULL)
1299
0
          {
1300
0
            tok->err = json_tokener_error_memory;
1301
0
            goto out;
1302
0
          }
1303
112k
          saved_state = json_tokener_state_object_field_end;
1304
112k
          state = json_tokener_state_eatws;
1305
112k
          break;
1306
112k
        }
1307
867k
        else if (c == '\\')
1308
7.32k
        {
1309
7.32k
          printbuf_memappend_checked(tok->pb, case_start,
1310
7.32k
                                     str - case_start);
1311
7.32k
          saved_state = json_tokener_state_object_field;
1312
7.32k
          state = json_tokener_state_string_escape;
1313
7.32k
          break;
1314
7.32k
        }
1315
860k
        else if ((tok->flags & JSON_TOKENER_STRICT) && (unsigned char)c <= 0x1f)
1316
0
        {
1317
          // Disallow control characters in strict mode
1318
0
          tok->err = json_tokener_error_parse_string;
1319
0
          goto out;
1320
0
        }
1321
860k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
1322
21
        {
1323
21
          printbuf_memappend_checked(tok->pb, case_start,
1324
21
                                     str - case_start);
1325
21
          goto out;
1326
21
        }
1327
860k
      }
1328
119k
    }
1329
119k
    break;
1330
1331
119k
    case json_tokener_state_object_field_end:
1332
112k
      if (c == ':')
1333
112k
      {
1334
112k
        saved_state = json_tokener_state_object_value;
1335
112k
        state = json_tokener_state_eatws;
1336
112k
      }
1337
19
      else
1338
19
      {
1339
19
        tok->err = json_tokener_error_parse_object_key_sep;
1340
19
        goto out;
1341
19
      }
1342
112k
      break;
1343
1344
112k
    case json_tokener_state_object_value:
1345
112k
      if (tok->depth >= tok->max_depth - 1)
1346
0
      {
1347
0
        tok->err = json_tokener_error_depth;
1348
0
        goto out;
1349
0
      }
1350
112k
      state = json_tokener_state_object_value_add;
1351
112k
      tok->depth++;
1352
112k
      json_tokener_reset_level(tok, tok->depth);
1353
112k
      goto redo_char;
1354
1355
111k
    case json_tokener_state_object_value_add:
1356
111k
      if (json_object_object_add(current, obj_field_name, obj) != 0)
1357
0
      {
1358
0
        tok->err = json_tokener_error_memory;
1359
0
        goto out;
1360
0
      }
1361
111k
      free(obj_field_name);
1362
111k
      obj_field_name = NULL;
1363
111k
      saved_state = json_tokener_state_object_sep;
1364
111k
      state = json_tokener_state_eatws;
1365
111k
      goto redo_char;
1366
1367
111k
    case json_tokener_state_object_sep:
1368
      /* { */
1369
111k
      if (c == '}')
1370
30.5k
      {
1371
30.5k
        saved_state = json_tokener_state_finish;
1372
30.5k
        state = json_tokener_state_eatws;
1373
30.5k
      }
1374
81.4k
      else if (c == ',')
1375
81.4k
      {
1376
81.4k
        saved_state = json_tokener_state_object_field_start_after_sep;
1377
81.4k
        state = json_tokener_state_eatws;
1378
81.4k
      }
1379
16
      else
1380
16
      {
1381
16
        tok->err = json_tokener_error_parse_object_value_sep;
1382
16
        goto out;
1383
16
      }
1384
111k
      break;
1385
2.13M
    }
1386
837k
    (void)ADVANCE_CHAR(str, tok);
1387
837k
    if (!c) // This is the char *before* advancing
1388
5
      break;
1389
837k
  } /* while(PEEK_CHAR) */
1390
1391
7.00k
out:
1392
7.00k
  if ((tok->flags & JSON_TOKENER_VALIDATE_UTF8) && (nBytes != 0))
1393
0
  {
1394
0
    tok->err = json_tokener_error_parse_utf8_string;
1395
0
  }
1396
7.00k
  if (c && (state == json_tokener_state_finish) && (tok->depth == 0) &&
1397
62
      (tok->flags & (JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS)) ==
1398
62
          JSON_TOKENER_STRICT)
1399
0
  {
1400
    /* unexpected char after JSON data */
1401
0
    tok->err = json_tokener_error_parse_unexpected;
1402
0
  }
1403
7.00k
  if (!c)
1404
6.71k
  {
1405
    /* We hit an eof char (0) */
1406
6.71k
    if (state != json_tokener_state_finish && saved_state != json_tokener_state_finish)
1407
191
      tok->err = json_tokener_error_parse_eof;
1408
6.71k
  }
1409
1410
7.00k
#ifdef HAVE_USELOCALE
1411
7.00k
  uselocale(oldlocale);
1412
7.00k
  freelocale(newloc);
1413
#elif defined(HAVE_SETLOCALE)
1414
  setlocale(LC_NUMERIC, oldlocale);
1415
  free(oldlocale);
1416
#endif
1417
1418
7.00k
  if (tok->err == json_tokener_success)
1419
6.58k
  {
1420
6.58k
    json_object *ret = json_object_get(current);
1421
6.58k
    int ii;
1422
1423
    /* Partially reset, so we parse additional objects on subsequent calls. */
1424
13.2k
    for (ii = tok->depth; ii >= 0; ii--)
1425
6.64k
      json_tokener_reset_level(tok, ii);
1426
6.58k
    return ret;
1427
6.58k
  }
1428
1429
418
  MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", json_tokener_errors[tok->err],
1430
418
           tok->char_offset);
1431
418
  return NULL;
1432
7.00k
}
1433
1434
static json_bool json_tokener_validate_utf8(const char c, unsigned int *nBytes)
1435
0
{
1436
0
  unsigned char chr = c;
1437
0
  if (*nBytes == 0)
1438
0
  {
1439
0
    if (chr >= 0x80)
1440
0
    {
1441
0
      if ((chr & 0xe0) == 0xc0)
1442
0
        *nBytes = 1;
1443
0
      else if ((chr & 0xf0) == 0xe0)
1444
0
        *nBytes = 2;
1445
0
      else if ((chr & 0xf8) == 0xf0)
1446
0
        *nBytes = 3;
1447
0
      else
1448
0
        return 0;
1449
0
    }
1450
0
  }
1451
0
  else
1452
0
  {
1453
0
    if ((chr & 0xC0) != 0x80)
1454
0
      return 0;
1455
0
    (*nBytes)--;
1456
0
  }
1457
0
  return 1;
1458
0
}
1459
1460
void json_tokener_set_flags(struct json_tokener *tok, int flags)
1461
0
{
1462
0
  tok->flags = flags;
1463
0
}
1464
1465
size_t json_tokener_get_parse_end(struct json_tokener *tok)
1466
0
{
1467
0
  assert(tok->char_offset >= 0); /* Drop this line when char_offset becomes a size_t */
1468
0
  return (size_t)tok->char_offset;
1469
0
}
1470
1471
static int json_tokener_parse_double(const char *buf, int len, double *retval)
1472
588
{
1473
588
  char *end;
1474
588
  *retval = strtod(buf, &end);
1475
588
  if (buf + len == end)
1476
586
    return 0; // It worked
1477
2
  return 1;
1478
588
}